@strapi/content-manager 0.0.0-experimental.5b211b38912691ee2eab22d47b5095ea2fcfec76 → 0.0.0-experimental.5bd54472327d69041855d9b38a3d4e445535c9a3

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 (227) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  3. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-9_4yUE9L.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-9_4yUE9L.mjs.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-DBSh-kET.js} +5 -6
  7. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-DBSh-kET.js.map} +1 -1
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  9. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  10. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  11. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-Bl_U2JgH.js} +5 -6
  12. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-Bl_U2JgH.js.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-COe6hjPC.mjs} +4 -4
  14. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-COe6hjPC.mjs.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-D4yFJET6.js} +36 -49
  16. package/dist/_chunks/EditViewPage-D4yFJET6.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-DrmVmYN0.mjs} +34 -46
  18. package/dist/_chunks/EditViewPage-DrmVmYN0.mjs.map +1 -0
  19. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  20. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  21. package/dist/_chunks/{Form-y5g1SRsh.js → Form-C4rSaGsz.js} +39 -21
  22. package/dist/_chunks/Form-C4rSaGsz.js.map +1 -0
  23. package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DamaxNpG.mjs} +37 -18
  24. package/dist/_chunks/Form-DamaxNpG.mjs.map +1 -0
  25. package/dist/_chunks/{History-Bru_KoeP.mjs → History-D1PreDSY.mjs} +108 -116
  26. package/dist/_chunks/History-D1PreDSY.mjs.map +1 -0
  27. package/dist/_chunks/{History-CqN6K7SX.js → History-DTm8UCCQ.js} +118 -127
  28. package/dist/_chunks/History-DTm8UCCQ.js.map +1 -0
  29. package/dist/_chunks/{Field-Boxf9Ajp.js → Input-B7sapvBG.js} +1431 -1312
  30. package/dist/_chunks/Input-B7sapvBG.js.map +1 -0
  31. package/dist/_chunks/{Field-dha5VnIQ.mjs → Input-CZ1YvjHR.mjs} +1439 -1320
  32. package/dist/_chunks/Input-CZ1YvjHR.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-Bbi32isk.mjs} +25 -12
  34. package/dist/_chunks/ListConfigurationPage-Bbi32isk.mjs.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-ysFMjKI3.js} +25 -13
  36. package/dist/_chunks/ListConfigurationPage-ysFMjKI3.js.map +1 -0
  37. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-Bud_jBDQ.mjs} +122 -78
  38. package/dist/_chunks/ListViewPage-Bud_jBDQ.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-DTuuxU3n.js} +121 -78
  40. package/dist/_chunks/ListViewPage-DTuuxU3n.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-CL7VVeYs.js} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-CL7VVeYs.js.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-DVhkugsf.mjs} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-DVhkugsf.mjs.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-CMdM-dCo.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-CMdM-dCo.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-v7I599vC.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-v7I599vC.js.map} +1 -1
  49. package/dist/_chunks/Preview-BNuU0SuQ.mjs +287 -0
  50. package/dist/_chunks/Preview-BNuU0SuQ.mjs.map +1 -0
  51. package/dist/_chunks/Preview-Cxq-uI6D.js +305 -0
  52. package/dist/_chunks/Preview-Cxq-uI6D.js.map +1 -0
  53. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-C2Ahkrdg.mjs} +76 -42
  54. package/dist/_chunks/Relations-C2Ahkrdg.mjs.map +1 -0
  55. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CWS79QQn.js} +76 -43
  56. package/dist/_chunks/Relations-CWS79QQn.js.map +1 -0
  57. package/dist/_chunks/{en-fbKQxLGn.js → en-BR48D_RH.js} +39 -18
  58. package/dist/_chunks/{en-fbKQxLGn.js.map → en-BR48D_RH.js.map} +1 -1
  59. package/dist/_chunks/{en-Ux26r5pl.mjs → en-D65uIF6Y.mjs} +39 -18
  60. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-D65uIF6Y.mjs.map} +1 -1
  61. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  62. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  63. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  64. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  65. package/dist/_chunks/{fr-B7kGGg3E.js → fr-C43IbhA_.js} +16 -3
  66. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-C43IbhA_.js.map} +1 -1
  67. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr-DBseuRuB.mjs} +16 -3
  68. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr-DBseuRuB.mjs.map} +1 -1
  69. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  70. package/dist/_chunks/{index-DVPWZkbS.js → index-DQsvBb_N.js} +1463 -762
  71. package/dist/_chunks/index-DQsvBb_N.js.map +1 -0
  72. package/dist/_chunks/{index-DJXJw9V5.mjs → index-ZKrsjv-2.mjs} +1481 -780
  73. package/dist/_chunks/index-ZKrsjv-2.mjs.map +1 -0
  74. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  75. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  77. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  78. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-Cl0NhlQB.js} +26 -14
  79. package/dist/_chunks/layout-Cl0NhlQB.js.map +1 -0
  80. package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-fQk1rMk9.mjs} +26 -13
  81. package/dist/_chunks/layout-fQk1rMk9.mjs.map +1 -0
  82. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  83. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  84. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  85. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  86. package/dist/_chunks/{relations-CKnpRgrN.js → relations-BRfBxVbX.js} +6 -7
  87. package/dist/_chunks/relations-BRfBxVbX.js.map +1 -0
  88. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-BakOFl_1.mjs} +6 -7
  89. package/dist/_chunks/relations-BakOFl_1.mjs.map +1 -0
  90. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  91. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  92. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  93. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  94. package/dist/_chunks/usePrev-CZGy2Vjf.mjs +29 -0
  95. package/dist/_chunks/usePrev-CZGy2Vjf.mjs.map +1 -0
  96. package/dist/_chunks/{usePrev-B9w_-eYc.js → usePrev-D5J_2fEu.js} +14 -1
  97. package/dist/_chunks/usePrev-D5J_2fEu.js.map +1 -0
  98. package/dist/admin/index.js +3 -1
  99. package/dist/admin/index.js.map +1 -1
  100. package/dist/admin/index.mjs +6 -4
  101. package/dist/admin/src/content-manager.d.ts +3 -2
  102. package/dist/admin/src/exports.d.ts +2 -1
  103. package/dist/admin/src/history/index.d.ts +3 -0
  104. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  105. package/dist/admin/src/hooks/useDocument.d.ts +49 -1
  106. package/dist/admin/src/index.d.ts +1 -0
  107. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  108. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -1
  109. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
  110. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  112. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  113. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
  114. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
  115. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  116. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  117. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  118. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  119. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
  120. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  121. package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
  122. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  123. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  124. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  125. package/dist/admin/src/preview/index.d.ts +4 -0
  126. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  127. package/dist/admin/src/preview/routes.d.ts +3 -0
  128. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  129. package/dist/admin/src/router.d.ts +1 -1
  130. package/dist/admin/src/services/api.d.ts +1 -1
  131. package/dist/admin/src/services/components.d.ts +2 -2
  132. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  133. package/dist/admin/src/services/documents.d.ts +19 -20
  134. package/dist/admin/src/services/init.d.ts +1 -1
  135. package/dist/admin/src/services/relations.d.ts +2 -2
  136. package/dist/admin/src/services/uid.d.ts +3 -3
  137. package/dist/admin/src/utils/validation.d.ts +4 -1
  138. package/dist/server/index.js +762 -432
  139. package/dist/server/index.js.map +1 -1
  140. package/dist/server/index.mjs +763 -432
  141. package/dist/server/index.mjs.map +1 -1
  142. package/dist/server/src/bootstrap.d.ts.map +1 -1
  143. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  144. package/dist/server/src/controllers/index.d.ts.map +1 -1
  145. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  146. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  147. package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
  148. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  149. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  150. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  151. package/dist/server/src/history/controllers/history-version.d.ts +1 -1
  152. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  153. package/dist/server/src/history/services/history.d.ts +3 -3
  154. package/dist/server/src/history/services/history.d.ts.map +1 -1
  155. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  156. package/dist/server/src/history/services/utils.d.ts +8 -12
  157. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  158. package/dist/server/src/index.d.ts +7 -6
  159. package/dist/server/src/index.d.ts.map +1 -1
  160. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  161. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  162. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  163. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  164. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  165. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  166. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  167. package/dist/server/src/preview/index.d.ts +4 -0
  168. package/dist/server/src/preview/index.d.ts.map +1 -0
  169. package/dist/server/src/preview/routes/index.d.ts +8 -0
  170. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  171. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  172. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  173. package/dist/server/src/preview/services/index.d.ts +16 -0
  174. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  175. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  176. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  177. package/dist/server/src/preview/services/preview.d.ts +12 -0
  178. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  179. package/dist/server/src/preview/utils.d.ts +19 -0
  180. package/dist/server/src/preview/utils.d.ts.map +1 -0
  181. package/dist/server/src/register.d.ts.map +1 -1
  182. package/dist/server/src/routes/index.d.ts.map +1 -1
  183. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  184. package/dist/server/src/services/document-metadata.d.ts +12 -10
  185. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  186. package/dist/server/src/services/index.d.ts +7 -6
  187. package/dist/server/src/services/index.d.ts.map +1 -1
  188. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  189. package/dist/server/src/services/utils/populate.d.ts +2 -2
  190. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  191. package/dist/server/src/utils/index.d.ts +2 -0
  192. package/dist/server/src/utils/index.d.ts.map +1 -1
  193. package/dist/shared/contracts/collection-types.d.ts +3 -1
  194. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  195. package/dist/shared/contracts/index.d.ts +1 -0
  196. package/dist/shared/contracts/index.d.ts.map +1 -1
  197. package/dist/shared/contracts/preview.d.ts +27 -0
  198. package/dist/shared/contracts/preview.d.ts.map +1 -0
  199. package/dist/shared/index.js +4 -0
  200. package/dist/shared/index.js.map +1 -1
  201. package/dist/shared/index.mjs +4 -0
  202. package/dist/shared/index.mjs.map +1 -1
  203. package/package.json +17 -16
  204. package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
  205. package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
  206. package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
  207. package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
  208. package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
  209. package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
  210. package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
  211. package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
  212. package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
  213. package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
  214. package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
  215. package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
  216. package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
  217. package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
  218. package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
  219. package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
  220. package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
  221. package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
  222. package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
  223. package/dist/_chunks/relations-CKnpRgrN.js.map +0 -1
  224. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  225. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  226. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  227. package/strapi-server.js +0 -3
@@ -1,25 +1,75 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { useState, useEffect, useCallback, memo } from "react";
4
- import { useStrapiApp, createContext, useField, useNotification, useForm, useAPIErrorHandler, useQueryParams, useFocusInputField, InputRenderer as InputRenderer$1 } from "@strapi/admin/strapi-admin";
5
- import { Box, SingleSelect, SingleSelectOption, Typography, Flex, BaseLink, Button, Popover, Field, Tooltip, IconButton, useComposedRefs, Portal, FocusTrap, Divider, VisuallyHidden, Grid as Grid$1, Accordion, TextButton, BaseButton, 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, d as buildValidParams, f as useDocumentRBAC, n as useDocLayout } from "./index-DJXJw9V5.mjs";
9
- import { generateNKeysBetween } from "fractional-indexing";
10
- import { u as useComponent, C as ComponentProvider, M as MemoizedRelationsField } from "./Relations-B9Crnhnn.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-ZKrsjv-2.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-mKMAmfec.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 } from "./usePrev-DH6iah0A.mjs";
13
+ import * as Prism from "prismjs";
14
+ import "prismjs/themes/prism-solarizedlight.css";
15
+ import "prismjs/components/prism-asmatmel";
16
+ import "prismjs/components/prism-bash";
17
+ import "prismjs/components/prism-basic";
18
+ import "prismjs/components/prism-c";
19
+ import "prismjs/components/prism-clojure";
20
+ import "prismjs/components/prism-cobol";
21
+ import "prismjs/components/prism-cpp";
22
+ import "prismjs/components/prism-csharp";
23
+ import "prismjs/components/prism-dart";
24
+ import "prismjs/components/prism-docker";
25
+ import "prismjs/components/prism-elixir";
26
+ import "prismjs/components/prism-erlang";
27
+ import "prismjs/components/prism-fortran";
28
+ import "prismjs/components/prism-fsharp";
29
+ import "prismjs/components/prism-go";
30
+ import "prismjs/components/prism-graphql";
31
+ import "prismjs/components/prism-groovy";
32
+ import "prismjs/components/prism-haskell";
33
+ import "prismjs/components/prism-haxe";
34
+ import "prismjs/components/prism-ini";
35
+ import "prismjs/components/prism-java";
36
+ import "prismjs/components/prism-javascript";
37
+ import "prismjs/components/prism-jsx";
38
+ import "prismjs/components/prism-json";
39
+ import "prismjs/components/prism-julia";
40
+ import "prismjs/components/prism-kotlin";
41
+ import "prismjs/components/prism-latex";
42
+ import "prismjs/components/prism-lua";
43
+ import "prismjs/components/prism-markdown";
44
+ import "prismjs/components/prism-matlab";
45
+ import "prismjs/components/prism-makefile";
46
+ import "prismjs/components/prism-objectivec";
47
+ import "prismjs/components/prism-perl";
48
+ import "prismjs/components/prism-php";
49
+ import "prismjs/components/prism-powershell";
50
+ import "prismjs/components/prism-python";
51
+ import "prismjs/components/prism-r";
52
+ import "prismjs/components/prism-ruby";
53
+ import "prismjs/components/prism-rust";
54
+ import "prismjs/components/prism-sas";
55
+ import "prismjs/components/prism-scala";
56
+ import "prismjs/components/prism-scheme";
57
+ import "prismjs/components/prism-sql";
58
+ import "prismjs/components/prism-stata";
59
+ import "prismjs/components/prism-swift";
60
+ import "prismjs/components/prism-typescript";
61
+ import "prismjs/components/prism-tsx";
62
+ import "prismjs/components/prism-vbnet";
63
+ import "prismjs/components/prism-yaml";
64
+ import { p as prefixFileUrlWithBackendUrl, u as useDebounce, a as usePrev } from "./usePrev-CZGy2Vjf.mjs";
65
+ import { a as DIRECTIONS, u as useDragAndDrop, I as ItemTypes } from "./useDragAndDrop-DJ6jqvZN.mjs";
21
66
  import * as Toolbar from "@radix-ui/react-toolbar";
22
- import { useLocation } 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-C2Ahkrdg.mjs";
71
+ import pipe$1 from "lodash/fp/pipe";
72
+ import { C as ComponentIcon, a as COMPONENT_ICONS } from "./ComponentIcon-u4bIXTFY.mjs";
23
73
  import CodeMirror from "codemirror5";
24
74
  import sanitizeHtml from "sanitize-html";
25
75
  import { getLanguage, highlight, highlightAuto } from "highlight.js";
@@ -35,93 +85,6 @@ import sub from "markdown-it-sub";
35
85
  import sup from "markdown-it-sup";
36
86
  import "highlight.js/styles/solarized-dark.css";
37
87
  import "codemirror5/addon/display/placeholder";
38
- const BLOCK_LIST_ATTRIBUTE_KEYS = ["__component", "__temp_key__"];
39
- const traverseData = (predicate, transform) => (schema, components = {}) => (data = {}) => {
40
- const traverse = (datum, attributes) => {
41
- return Object.entries(datum).reduce((acc, [key, value]) => {
42
- const attribute = attributes[key];
43
- if (BLOCK_LIST_ATTRIBUTE_KEYS.includes(key) || value === null || value === void 0) {
44
- acc[key] = value;
45
- return acc;
46
- }
47
- if (attribute.type === "component") {
48
- if (attribute.repeatable) {
49
- const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
50
- acc[key] = componentValue.map(
51
- (componentData) => traverse(componentData, components[attribute.component]?.attributes ?? {})
52
- );
53
- } else {
54
- const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
55
- acc[key] = traverse(componentValue, components[attribute.component]?.attributes ?? {});
56
- }
57
- } else if (attribute.type === "dynamiczone") {
58
- const dynamicZoneValue = predicate(attribute, value) ? transform(value, attribute) : value;
59
- acc[key] = dynamicZoneValue.map(
60
- (componentData) => traverse(componentData, components[componentData.__component]?.attributes ?? {})
61
- );
62
- } else if (predicate(attribute, value)) {
63
- acc[key] = transform(value, attribute);
64
- } else {
65
- acc[key] = value;
66
- }
67
- return acc;
68
- }, {});
69
- };
70
- return traverse(data, schema.attributes);
71
- };
72
- const removeProhibitedFields = (prohibitedFields) => traverseData(
73
- (attribute) => prohibitedFields.includes(attribute.type),
74
- () => ""
75
- );
76
- const prepareRelations = traverseData(
77
- (attribute) => attribute.type === "relation",
78
- () => ({
79
- connect: [],
80
- disconnect: []
81
- })
82
- );
83
- const prepareTempKeys = traverseData(
84
- (attribute) => attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone",
85
- (data) => {
86
- if (Array.isArray(data) && data.length > 0) {
87
- const keys = generateNKeysBetween(void 0, void 0, data.length);
88
- return data.map((datum, index) => ({
89
- ...datum,
90
- __temp_key__: keys[index]
91
- }));
92
- }
93
- return data;
94
- }
95
- );
96
- const removeFieldsThatDontExistOnSchema = (schema) => (data) => {
97
- const schemaKeys = Object.keys(schema.attributes);
98
- const dataKeys = Object.keys(data);
99
- const keysToRemove = dataKeys.filter((key) => !schemaKeys.includes(key));
100
- const revisedData = [...keysToRemove, ...DOCUMENT_META_FIELDS].reduce((acc, key) => {
101
- delete acc[key];
102
- return acc;
103
- }, structuredClone(data));
104
- return revisedData;
105
- };
106
- const removeNullValues = (data) => {
107
- return Object.entries(data).reduce((acc, [key, value]) => {
108
- if (value === null) {
109
- return acc;
110
- }
111
- acc[key] = value;
112
- return acc;
113
- }, {});
114
- };
115
- const transformDocument = (schema, components = {}) => (document2) => {
116
- const transformations = pipe$1(
117
- removeFieldsThatDontExistOnSchema(schema),
118
- removeProhibitedFields(["password"])(schema, components),
119
- removeNullValues,
120
- prepareRelations(schema, components),
121
- prepareTempKeys(schema, components)
122
- );
123
- return transformations(document2);
124
- };
125
88
  const componentStore = /* @__PURE__ */ new Map();
126
89
  const useLazyComponents = (componentUids = []) => {
127
90
  const [lazyComponentStore, setLazyComponentStore] = useState(Object.fromEntries(componentStore));
@@ -163,7 +126,8 @@ const useLazyComponents = (componentUids = []) => {
163
126
  const codeLanguages = [
164
127
  {
165
128
  value: "asm",
166
- label: "Assembly"
129
+ label: "Assembly",
130
+ decorate: "asmatmel"
167
131
  },
168
132
  {
169
133
  value: "bash",
@@ -199,7 +163,8 @@ const codeLanguages = [
199
163
  },
200
164
  {
201
165
  value: "dockerfile",
202
- label: "Dockerfile"
166
+ label: "Dockerfile",
167
+ decorate: "docker"
203
168
  },
204
169
  {
205
170
  value: "elixir",
@@ -355,7 +320,8 @@ const codeLanguages = [
355
320
  },
356
321
  {
357
322
  value: "typescript",
358
- label: "TypeScript"
323
+ label: "TypeScript",
324
+ decorate: "ts"
359
325
  },
360
326
  {
361
327
  value: "tsx",
@@ -371,7 +337,8 @@ const codeLanguages = [
371
337
  },
372
338
  {
373
339
  value: "yaml",
374
- label: "YAML"
340
+ label: "YAML",
341
+ decorate: "yml"
375
342
  }
376
343
  ];
377
344
  const baseHandleConvert = (editor, attributesToSet) => {
@@ -437,6 +404,29 @@ const pressEnterTwiceToExit = (editor) => {
437
404
  });
438
405
  }
439
406
  };
407
+ const decorateCode = ([node, path]) => {
408
+ const ranges = [];
409
+ if (!Element.isElement(node) || node.type !== "code") return ranges;
410
+ const text = Node.string(node);
411
+ const language = codeLanguages.find((lang) => lang.value === node.language);
412
+ const decorateKey = language?.decorate ?? language?.value;
413
+ const selectedLanguage = Prism.languages[decorateKey || "plaintext"];
414
+ const tokens = Prism.tokenize(text, selectedLanguage);
415
+ let start = 0;
416
+ for (const token of tokens) {
417
+ const length = token.length;
418
+ const end = start + length;
419
+ if (typeof token !== "string") {
420
+ ranges.push({
421
+ anchor: { path, offset: start },
422
+ focus: { path, offset: end },
423
+ className: `token ${token.type}`
424
+ });
425
+ }
426
+ start = end;
427
+ }
428
+ return ranges;
429
+ };
440
430
  const CodeBlock = styled.pre`
441
431
  border-radius: ${({ theme }) => theme.borderRadius};
442
432
  background-color: ${({ theme }) => theme.colors.neutral100};
@@ -508,7 +498,7 @@ const CodeEditor = (props) => {
508
498
  const codeBlocks = {
509
499
  code: {
510
500
  renderElement: (props) => /* @__PURE__ */ jsx(CodeEditor, { ...props }),
511
- icon: Code,
501
+ icon: CodeBlock$1,
512
502
  label: {
513
503
  id: "components.Blocks.blocks.code",
514
504
  defaultMessage: "Code block"
@@ -521,8 +511,7 @@ const codeBlocks = {
521
511
  handleEnterKey(editor) {
522
512
  pressEnterTwiceToExit(editor);
523
513
  },
524
- snippets: ["```"],
525
- dragHandleTopMargin: "10px"
514
+ snippets: ["```"]
526
515
  }
527
516
  };
528
517
  const H1 = styled(Typography).attrs({ tag: "h1" })`
@@ -697,8 +686,7 @@ const ImageDialog = () => {
697
686
  const [isOpen, setIsOpen] = React.useState(true);
698
687
  const { editor } = useBlocksEditorContext("ImageDialog");
699
688
  const components = useStrapiApp("ImageDialog", (state) => state.components);
700
- if (!components || !isOpen)
701
- return null;
689
+ if (!components || !isOpen) return null;
702
690
  const MediaLibraryDialog = components["media-library"];
703
691
  const insertImages = (images) => {
704
692
  Transforms.unwrapNodes(editor, {
@@ -707,14 +695,12 @@ const ImageDialog = () => {
707
695
  });
708
696
  const nodeEntryBeingReplaced = Editor$1.above(editor, {
709
697
  match(node) {
710
- if (Editor$1.isEditor(node))
711
- return false;
698
+ if (Editor$1.isEditor(node)) return false;
712
699
  const isInlineNode = ["text", "link"].includes(node.type);
713
700
  return !isInlineNode;
714
701
  }
715
702
  });
716
- if (!nodeEntryBeingReplaced)
717
- return;
703
+ if (!nodeEntryBeingReplaced) return;
718
704
  const [, pathToInsert] = nodeEntryBeingReplaced;
719
705
  Transforms.removeNodes(editor);
720
706
  const nodesToInsert = images.map((image) => {
@@ -860,20 +846,8 @@ const LinkContent = React.forwardRef(
860
846
  const [linkText, setLinkText] = React.useState(elementText);
861
847
  const [linkUrl, setLinkUrl] = React.useState(link.url);
862
848
  const linkInputRef = React.useRef(null);
863
- const [showRemoveButton, setShowRemoveButton] = React.useState(false);
849
+ const isLastInsertedLink = editor.lastInsertedLinkPath ? !Path.equals(path, editor.lastInsertedLinkPath) : true;
864
850
  const [isSaveDisabled, setIsSaveDisabled] = React.useState(false);
865
- const handleOpenChange = (isOpen) => {
866
- if (isOpen) {
867
- setPopoverOpen(isOpen);
868
- setShowRemoveButton(isOpen);
869
- } else {
870
- setPopoverOpen(isOpen);
871
- if (link.url === "") {
872
- removeLink(editor);
873
- }
874
- ReactEditor.focus(editor);
875
- }
876
- };
877
851
  const onLinkChange = (e) => {
878
852
  setIsSaveDisabled(false);
879
853
  setLinkUrl(e.target.value);
@@ -894,15 +868,32 @@ const LinkContent = React.forwardRef(
894
868
  editLink(editor, { url: linkUrl, text: linkText });
895
869
  setPopoverOpen(false);
896
870
  editor.lastInsertedLinkPath = null;
871
+ ReactEditor.focus(editor);
872
+ };
873
+ const handleClose = () => {
874
+ if (link.url === "") {
875
+ removeLink(editor);
876
+ }
877
+ setPopoverOpen(false);
878
+ ReactEditor.focus(editor);
897
879
  };
898
880
  React.useEffect(() => {
899
- if (popoverOpen)
900
- linkInputRef.current?.focus();
881
+ if (popoverOpen) linkInputRef.current?.focus();
901
882
  }, [popoverOpen]);
902
883
  const inputNotDirty = !linkText || !linkUrl || link.url && link.url === linkUrl && elementText && elementText === linkText;
903
- return /* @__PURE__ */ jsxs(Popover.Root, { onOpenChange: handleOpenChange, open: popoverOpen, children: [
904
- /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(StyledBaseLink, { ...attributes, ref: forwardedRef, href: link.url, color: "primary600", children }) }),
905
- /* @__PURE__ */ jsx(Popover.Content, { children: /* @__PURE__ */ jsxs(Flex, { padding: 4, tag: "form", onSubmit: handleSave, direction: "column", gap: 4, children: [
884
+ return /* @__PURE__ */ jsxs(Popover.Root, { open: popoverOpen, children: [
885
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(
886
+ StyledBaseLink,
887
+ {
888
+ ...attributes,
889
+ ref: forwardedRef,
890
+ href: link.url,
891
+ onClick: () => setPopoverOpen(true),
892
+ color: "primary600",
893
+ children
894
+ }
895
+ ) }),
896
+ /* @__PURE__ */ jsx(Popover.Content, { onPointerDownOutside: handleClose, children: /* @__PURE__ */ jsxs(Flex, { padding: 4, direction: "column", gap: 4, children: [
906
897
  /* @__PURE__ */ jsx(Field.Root, { width: "368px", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, alignItems: "stretch", children: [
907
898
  /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
908
899
  id: "components.Blocks.popover.text",
@@ -948,7 +939,7 @@ const LinkContent = React.forwardRef(
948
939
  {
949
940
  variant: "danger-light",
950
941
  onClick: () => removeLink(editor),
951
- $visible: showRemoveButton,
942
+ $visible: isLastInsertedLink,
952
943
  children: formatMessage({
953
944
  id: "components.Blocks.popover.remove",
954
945
  defaultMessage: "Remove"
@@ -956,12 +947,12 @@ const LinkContent = React.forwardRef(
956
947
  }
957
948
  ),
958
949
  /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
959
- /* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: () => handleOpenChange(false), children: formatMessage({
960
- id: "components.Blocks.popover.cancel",
950
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: handleClose, children: formatMessage({
951
+ id: "global.cancel",
961
952
  defaultMessage: "Cancel"
962
953
  }) }),
963
- /* @__PURE__ */ jsx(Button, { type: "submit", disabled: Boolean(inputNotDirty) || isSaveDisabled, children: formatMessage({
964
- id: "components.Blocks.popover.save",
954
+ /* @__PURE__ */ jsx(Button, { disabled: Boolean(inputNotDirty) || isSaveDisabled, onClick: handleSave, children: formatMessage({
955
+ id: "global.save",
965
956
  defaultMessage: "Save"
966
957
  }) })
967
958
  ] })
@@ -1042,8 +1033,7 @@ const isText$1 = (node) => {
1042
1033
  return Node.isNode(node) && !Editor$1.isEditor(node) && node.type === "text";
1043
1034
  };
1044
1035
  const handleBackspaceKeyOnList = (editor, event) => {
1045
- if (!editor.selection)
1046
- return;
1036
+ if (!editor.selection) return;
1047
1037
  const [currentListItem, currentListItemPath] = Editor$1.parent(editor, editor.selection.anchor);
1048
1038
  const [currentList, currentListPath] = Editor$1.parent(editor, currentListItemPath);
1049
1039
  const isListEmpty = currentList.children.length === 1 && isText$1(currentListItem.children[0]) && currentListItem.children[0].text === "";
@@ -1152,8 +1142,7 @@ const handleEnterKeyOnList = (editor) => {
1152
1142
  };
1153
1143
  const handleConvertToList = (editor, format) => {
1154
1144
  const convertedPath = baseHandleConvert(editor, { type: "list-item" });
1155
- if (!convertedPath)
1156
- return;
1145
+ if (!convertedPath) return;
1157
1146
  Transforms.wrapNodes(editor, { type: "list", format, children: [] }, { at: convertedPath });
1158
1147
  };
1159
1148
  const handleTabOnList = (editor) => {
@@ -1165,8 +1154,7 @@ const handleTabOnList = (editor) => {
1165
1154
  }
1166
1155
  const [currentListItem, currentListItemPath] = currentListItemEntry;
1167
1156
  const [currentList] = Editor$1.parent(editor, currentListItemPath);
1168
- if (currentListItem === currentList.children[0])
1169
- return;
1157
+ if (currentListItem === currentList.children[0]) return;
1170
1158
  const currentListItemIndex = currentList.children.findIndex((item) => item === currentListItem);
1171
1159
  const previousNode = currentList.children[currentListItemIndex - 1];
1172
1160
  if (previousNode.type === "list") {
@@ -1302,13 +1290,13 @@ const quoteBlocks = {
1302
1290
  handleEnterKey(editor) {
1303
1291
  pressEnterTwiceToExit(editor);
1304
1292
  },
1305
- snippets: [">"],
1306
- dragHandleTopMargin: "6px"
1293
+ snippets: [">"]
1307
1294
  }
1308
1295
  };
1309
1296
  const ToolbarWrapper = styled(Flex)`
1310
1297
  &[aria-disabled='true'] {
1311
1298
  cursor: not-allowed;
1299
+ background: ${({ theme }) => theme.colors.neutral150};
1312
1300
  }
1313
1301
  `;
1314
1302
  const Separator = styled(Toolbar.Separator)`
@@ -1319,7 +1307,7 @@ const Separator = styled(Toolbar.Separator)`
1319
1307
  const FlexButton = styled(Flex)`
1320
1308
  // Inherit the not-allowed cursor from ToolbarWrapper when disabled
1321
1309
  &[aria-disabled] {
1322
- cursor: inherit;
1310
+ cursor: not-allowed;
1323
1311
  }
1324
1312
 
1325
1313
  &[aria-disabled='false'] {
@@ -1401,7 +1389,7 @@ const ToolbarButton = ({
1401
1389
  width: 7,
1402
1390
  height: 7,
1403
1391
  hasRadius: true,
1404
- children: /* @__PURE__ */ jsx(Icon, { width: "1.2rem", height: "1.2rem", fill: disabled ? "neutral300" : enabledColor })
1392
+ children: /* @__PURE__ */ jsx(Icon, { fill: disabled ? "neutral300" : enabledColor })
1405
1393
  }
1406
1394
  )
1407
1395
  }
@@ -1533,8 +1521,7 @@ const isListNode = (node) => {
1533
1521
  const ListButton = ({ block, format }) => {
1534
1522
  const { editor, disabled, blocks } = useBlocksEditorContext("ListButton");
1535
1523
  const isListActive = () => {
1536
- if (!editor.selection)
1537
- return false;
1524
+ if (!editor.selection) return false;
1538
1525
  const currentListEntry = Editor$1.above(editor, {
1539
1526
  match: (node) => !Editor$1.isEditor(node) && node.type === "list",
1540
1527
  at: editor.selection.anchor
@@ -1546,6 +1533,26 @@ const ListButton = ({ block, format }) => {
1546
1533
  }
1547
1534
  return false;
1548
1535
  };
1536
+ const isListDisabled = () => {
1537
+ if (disabled) {
1538
+ return true;
1539
+ }
1540
+ if (!editor.selection) {
1541
+ return false;
1542
+ }
1543
+ const anchorNodeEntry = Editor$1.above(editor, {
1544
+ at: editor.selection.anchor,
1545
+ match: (node) => !Editor$1.isEditor(node) && node.type !== "text"
1546
+ });
1547
+ const focusNodeEntry = Editor$1.above(editor, {
1548
+ at: editor.selection.focus,
1549
+ match: (node) => !Editor$1.isEditor(node) && node.type !== "text"
1550
+ });
1551
+ if (!anchorNodeEntry || !focusNodeEntry) {
1552
+ return false;
1553
+ }
1554
+ return anchorNodeEntry[0] !== focusNodeEntry[0];
1555
+ };
1549
1556
  const toggleList = (format2) => {
1550
1557
  let currentListEntry;
1551
1558
  if (editor.selection) {
@@ -1579,7 +1586,7 @@ const ListButton = ({ block, format }) => {
1579
1586
  name: format,
1580
1587
  label: block.label,
1581
1588
  isActive: isListActive(),
1582
- disabled,
1589
+ disabled: isListDisabled(),
1583
1590
  handleClick: () => toggleList(format)
1584
1591
  }
1585
1592
  );
@@ -1588,8 +1595,7 @@ const LinkButton = ({ disabled }) => {
1588
1595
  const { editor } = useBlocksEditorContext("LinkButton");
1589
1596
  const isLinkActive = () => {
1590
1597
  const { selection } = editor;
1591
- if (!selection)
1592
- return false;
1598
+ if (!selection) return false;
1593
1599
  const [match] = Array.from(
1594
1600
  Editor$1.nodes(editor, {
1595
1601
  at: Editor$1.unhangRange(editor, selection),
@@ -1653,7 +1659,7 @@ const BlocksToolbar = () => {
1653
1659
  return false;
1654
1660
  };
1655
1661
  const isButtonDisabled = checkButtonDisabled();
1656
- return /* @__PURE__ */ jsx(Toolbar.Root, { "aria-disabled": disabled, asChild: true, children: /* @__PURE__ */ jsxs(ToolbarWrapper, { gap: 2, padding: 2, children: [
1662
+ return /* @__PURE__ */ jsx(Toolbar.Root, { "aria-disabled": disabled, asChild: true, children: /* @__PURE__ */ jsxs(ToolbarWrapper, { gap: 2, padding: 2, width: "100%", children: [
1657
1663
  /* @__PURE__ */ jsx(BlocksDropdown, {}),
1658
1664
  /* @__PURE__ */ jsx(Separator, {}),
1659
1665
  /* @__PURE__ */ jsx(Toolbar.ToggleGroup, { type: "multiple", asChild: true, children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
@@ -1723,33 +1729,36 @@ const DragItem = styled(Flex)`
1723
1729
  }
1724
1730
  `;
1725
1731
  const DragIconButton = styled(IconButton)`
1732
+ user-select: none;
1726
1733
  display: flex;
1727
1734
  align-items: center;
1728
1735
  justify-content: center;
1736
+ border: none;
1729
1737
  border-radius: ${({ theme }) => theme.borderRadius};
1730
- width: ${({ theme }) => theme.spaces[4]};
1731
- height: ${({ theme }) => theme.spaces[6]};
1738
+ padding-left: ${({ theme }) => theme.spaces[0]};
1739
+ padding-right: ${({ theme }) => theme.spaces[0]};
1740
+ padding-top: ${({ theme }) => theme.spaces[1]};
1741
+ padding-bottom: ${({ theme }) => theme.spaces[1]};
1732
1742
  visibility: hidden;
1733
1743
  cursor: grab;
1734
1744
  opacity: inherit;
1735
1745
  margin-top: ${(props) => props.$dragHandleTopMargin ?? 0};
1736
1746
 
1737
1747
  &:hover {
1738
- background: ${({ theme }) => theme.colors.neutral200};
1748
+ background: ${({ theme }) => theme.colors.neutral100};
1739
1749
  }
1740
1750
  &:active {
1741
1751
  cursor: grabbing;
1752
+ background: ${({ theme }) => theme.colors.neutral150};
1742
1753
  }
1743
1754
  &[aria-disabled='true'] {
1744
- cursor: not-allowed;
1745
- background: transparent;
1755
+ visibility: hidden;
1746
1756
  }
1747
1757
  svg {
1748
- height: auto;
1749
- width: ${({ theme }) => theme.spaces[3]};
1758
+ min-width: ${({ theme }) => theme.spaces[3]};
1750
1759
 
1751
1760
  path {
1752
- fill: ${({ theme }) => theme.colors.neutral700};
1761
+ fill: ${({ theme }) => theme.colors.neutral500};
1753
1762
  }
1754
1763
  }
1755
1764
  `;
@@ -1794,8 +1803,7 @@ const DragAndDropElement = ({
1794
1803
  displayedValue: children
1795
1804
  },
1796
1805
  onDropItem(currentIndex, newIndex) {
1797
- if (newIndex)
1798
- handleMoveBlock(newIndex, currentIndex);
1806
+ if (newIndex) handleMoveBlock(newIndex, currentIndex);
1799
1807
  }
1800
1808
  });
1801
1809
  const composedBoxRefs = useComposedRefs(blockRef, dropRef);
@@ -1851,6 +1859,7 @@ const DragAndDropElement = ({
1851
1859
  DragIconButton,
1852
1860
  {
1853
1861
  tag: "div",
1862
+ contentEditable: false,
1854
1863
  role: "button",
1855
1864
  tabIndex: 0,
1856
1865
  withTooltip: false,
@@ -1863,7 +1872,7 @@ const DragAndDropElement = ({
1863
1872
  disabled,
1864
1873
  draggable: true,
1865
1874
  $dragHandleTopMargin: dragHandleTopMargin,
1866
- children: /* @__PURE__ */ jsx(Drag, { color: "neutral600" })
1875
+ children: /* @__PURE__ */ jsx(Drag, { color: "primary500" })
1867
1876
  }
1868
1877
  ),
1869
1878
  children
@@ -1900,7 +1909,7 @@ const baseRenderLeaf = (props, modifiers2) => {
1900
1909
  }
1901
1910
  return currentChildren;
1902
1911
  }, props.children);
1903
- return /* @__PURE__ */ jsx("span", { ...props.attributes, children: wrappedChildren });
1912
+ return /* @__PURE__ */ jsx("span", { ...props.attributes, className: props.leaf.className, children: wrappedChildren });
1904
1913
  };
1905
1914
  const baseRenderElement = ({
1906
1915
  props,
@@ -1938,8 +1947,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
1938
1947
  [modifiers2]
1939
1948
  );
1940
1949
  const handleMoveBlocks = (editor2, event) => {
1941
- if (!editor2.selection)
1942
- return;
1950
+ if (!editor2.selection) return;
1943
1951
  const start = Range.start(editor2.selection);
1944
1952
  const currentIndex = [start.path[0]];
1945
1953
  let newIndexPosition = 0;
@@ -2076,8 +2084,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2076
2084
  }
2077
2085
  };
2078
2086
  const handleScrollSelectionIntoView = () => {
2079
- if (!editor.selection)
2080
- return;
2087
+ if (!editor.selection) return;
2081
2088
  const domRange = ReactEditor.toDOMRange(editor, editor.selection);
2082
2089
  const domRect = domRange.getBoundingClientRect();
2083
2090
  const blocksInput = blocksRef.current;
@@ -2104,7 +2111,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2104
2111
  background: "neutral0",
2105
2112
  color: "neutral800",
2106
2113
  lineHeight: 6,
2107
- paddingRight: 4,
2114
+ paddingRight: 7,
2108
2115
  paddingTop: 6,
2109
2116
  paddingBottom: 3,
2110
2117
  children: [
@@ -2115,6 +2122,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2115
2122
  readOnly: disabled,
2116
2123
  placeholder,
2117
2124
  isExpandedMode,
2125
+ decorate: decorateCode,
2118
2126
  renderElement,
2119
2127
  renderLeaf,
2120
2128
  onKeyDown: handleKeyDown,
@@ -2187,7 +2195,7 @@ const EditorLayout$1 = ({
2187
2195
  /* @__PURE__ */ jsx(
2188
2196
  CollapseIconButton,
2189
2197
  {
2190
- "aria-label": formatMessage({
2198
+ label: formatMessage({
2191
2199
  id: getTranslation("components.Blocks.collapse"),
2192
2200
  defaultMessage: "Collapse"
2193
2201
  }),
@@ -2271,8 +2279,7 @@ const InlineCode = styled.code`
2271
2279
  `;
2272
2280
  const baseCheckIsActive = (editor, name2) => {
2273
2281
  const marks = Editor$1.marks(editor);
2274
- if (!marks)
2275
- return false;
2282
+ if (!marks) return false;
2276
2283
  return Boolean(marks[name2]);
2277
2284
  };
2278
2285
  const baseHandleToggle = (editor, name2) => {
@@ -2438,6 +2445,7 @@ const ExpandIconButton = styled(IconButton)`
2438
2445
  position: absolute;
2439
2446
  bottom: 1.2rem;
2440
2447
  right: 1.2rem;
2448
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
2441
2449
  `;
2442
2450
  function useResetKey(value) {
2443
2451
  const slateUpdatesCount = React.useRef(0);
@@ -2526,7 +2534,7 @@ const BlocksEditor = React.forwardRef(
2526
2534
  !isExpandedMode && /* @__PURE__ */ jsx(
2527
2535
  ExpandIconButton,
2528
2536
  {
2529
- "aria-label": formatMessage({
2537
+ label: formatMessage({
2530
2538
  id: getTranslation("components.Blocks.expand"),
2531
2539
  defaultMessage: "Expand"
2532
2540
  }),
@@ -2569,628 +2577,653 @@ const BlocksInput = React.forwardRef(
2569
2577
  }
2570
2578
  );
2571
2579
  const MemoizedBlocksInput = React.memo(BlocksInput);
2572
- const createDefaultForm = (contentType, components = {}) => {
2573
- const traverseSchema = (attributes) => {
2574
- return Object.entries(attributes).reduce((acc, [key, attribute]) => {
2575
- if ("default" in attribute) {
2576
- acc[key] = attribute.default;
2577
- } else if (attribute.type === "component" && attribute.required) {
2578
- const defaultComponentForm = traverseSchema(components[attribute.component].attributes);
2579
- if (attribute.repeatable) {
2580
- acc[key] = attribute.min ? [...Array(attribute.min).fill(defaultComponentForm)] : [];
2581
- } else {
2582
- acc[key] = defaultComponentForm;
2583
- }
2584
- } else if (attribute.type === "dynamiczone" && attribute.required) {
2585
- acc[key] = [];
2586
- }
2587
- return acc;
2588
- }, {});
2589
- };
2590
- return traverseSchema(contentType.attributes);
2591
- };
2592
2580
  const Initializer = ({ disabled, name: name2, onClick }) => {
2593
2581
  const { formatMessage } = useIntl();
2594
2582
  const field = useField(name2);
2595
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2596
- /* @__PURE__ */ jsx(
2597
- Box,
2583
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
2584
+ Box,
2585
+ {
2586
+ tag: "button",
2587
+ background: disabled ? "neutral150" : "neutral100",
2588
+ borderColor: field.error ? "danger600" : "neutral200",
2589
+ hasRadius: true,
2590
+ disabled,
2591
+ onClick,
2592
+ paddingTop: 9,
2593
+ paddingBottom: 9,
2594
+ type: "button",
2595
+ style: { cursor: disabled ? "not-allowed" : "pointer" },
2596
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2597
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", color: disabled ? "neutral500" : "primary600", children: /* @__PURE__ */ jsx(PlusCircle, { width: "3.2rem", height: "3.2rem" }) }),
2598
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
2599
+ Typography,
2600
+ {
2601
+ textColor: disabled ? "neutral600" : "primary600",
2602
+ variant: "pi",
2603
+ fontWeight: "bold",
2604
+ children: formatMessage({
2605
+ id: getTranslation("components.empty-repeatable"),
2606
+ defaultMessage: "No entry yet. Click to add one."
2607
+ })
2608
+ }
2609
+ ) })
2610
+ ] })
2611
+ }
2612
+ ) });
2613
+ };
2614
+ const AddComponentButton = ({
2615
+ hasError,
2616
+ isDisabled,
2617
+ isOpen,
2618
+ children,
2619
+ onClick
2620
+ }) => {
2621
+ return /* @__PURE__ */ jsx(
2622
+ StyledButton,
2623
+ {
2624
+ type: "button",
2625
+ onClick,
2626
+ disabled: isDisabled,
2627
+ background: "neutral0",
2628
+ style: { cursor: isDisabled ? "not-allowed" : "pointer" },
2629
+ variant: "tertiary",
2630
+ children: /* @__PURE__ */ jsxs(Flex, { tag: "span", gap: 2, children: [
2631
+ /* @__PURE__ */ jsx(StyledAddIcon, { "aria-hidden": true, $isOpen: isOpen, $hasError: hasError && !isOpen }),
2632
+ /* @__PURE__ */ jsx(
2633
+ Typography,
2634
+ {
2635
+ variant: "pi",
2636
+ fontWeight: "bold",
2637
+ textColor: hasError && !isOpen ? "danger600" : "neutral600",
2638
+ children
2639
+ }
2640
+ )
2641
+ ] })
2642
+ }
2643
+ );
2644
+ };
2645
+ const StyledAddIcon = styled(PlusCircle)`
2646
+ height: ${({ theme }) => theme.spaces[6]};
2647
+ width: ${({ theme }) => theme.spaces[6]};
2648
+ transform: ${({ $isOpen }) => $isOpen ? "rotate(45deg)" : "rotate(0deg)"};
2649
+
2650
+ > circle {
2651
+ fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150};
2652
+ }
2653
+ > path {
2654
+ fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger600 : theme.colors.neutral500};
2655
+ }
2656
+ `;
2657
+ const StyledButton = styled(Button)`
2658
+ padding-left: ${({ theme }) => theme.spaces[3]};
2659
+ border-radius: 26px;
2660
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
2661
+ height: 5rem;
2662
+ `;
2663
+ const ComponentCategory = ({
2664
+ category,
2665
+ components = [],
2666
+ variant = "primary",
2667
+ onAddComponent
2668
+ }) => {
2669
+ const { formatMessage } = useIntl();
2670
+ return /* @__PURE__ */ jsxs(Accordion.Item, { value: category, children: [
2671
+ /* @__PURE__ */ jsx(Accordion.Header, { variant, children: /* @__PURE__ */ jsx(Accordion.Trigger, { children: formatMessage({ id: category, defaultMessage: category }) }) }),
2672
+ /* @__PURE__ */ jsx(ResponsiveAccordionContent, { children: /* @__PURE__ */ jsx(Grid, { paddingTop: 4, paddingBottom: 4, paddingLeft: 3, paddingRight: 3, children: components.map(({ uid, displayName, icon }) => /* @__PURE__ */ jsx(
2673
+ ComponentBox,
2598
2674
  {
2599
2675
  tag: "button",
2676
+ type: "button",
2600
2677
  background: "neutral100",
2601
- borderColor: field.error ? "danger600" : "neutral200",
2678
+ justifyContent: "center",
2679
+ onClick: onAddComponent(uid),
2602
2680
  hasRadius: true,
2603
- disabled,
2604
- onClick,
2605
- paddingTop: 9,
2606
- paddingBottom: 9,
2607
- type: "button",
2608
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2609
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(CircleIcon, {}) }),
2610
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { textColor: "primary600", variant: "pi", fontWeight: "bold", children: formatMessage({
2611
- id: getTranslation("components.empty-repeatable"),
2612
- defaultMessage: "No entry yet. Click on the button below to add one."
2613
- }) }) })
2681
+ height: "8.4rem",
2682
+ shrink: 0,
2683
+ borderColor: "neutral200",
2684
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, alignItems: "center", justifyContent: "center", children: [
2685
+ /* @__PURE__ */ jsx(ComponentIcon, { color: "currentColor", background: "primary200", icon }),
2686
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: displayName })
2614
2687
  ] })
2615
- }
2616
- ),
2617
- field.error && /* @__PURE__ */ jsx(Typography, { textColor: "danger600", variant: "pi", children: field.error })
2688
+ },
2689
+ uid
2690
+ )) }) })
2618
2691
  ] });
2619
2692
  };
2620
- const CircleIcon = styled(PlusCircle)`
2621
- width: 2.4rem;
2622
- height: 2.4rem;
2623
- > circle {
2624
- fill: ${({ theme }) => theme.colors.primary200};
2693
+ const ResponsiveAccordionContent = styled(Accordion.Content)`
2694
+ container-type: inline-size;
2695
+ `;
2696
+ const Grid = styled(Box)`
2697
+ display: grid;
2698
+ grid-template-columns: repeat(auto-fill, 100%);
2699
+ grid-gap: ${({ theme }) => theme.spaces[1]};
2700
+
2701
+ @container (min-width: ${() => RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
2702
+ grid-template-columns: repeat(auto-fill, 14rem);
2625
2703
  }
2626
- > path {
2627
- fill: ${({ theme }) => theme.colors.primary600};
2704
+ `;
2705
+ const ComponentBox = styled(Flex)`
2706
+ color: ${({ theme }) => theme.colors.neutral600};
2707
+ cursor: pointer;
2708
+
2709
+ @media (prefers-reduced-motion: no-preference) {
2710
+ transition: color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
2711
+ }
2712
+
2713
+ &:focus,
2714
+ &:hover {
2715
+ border: 1px solid ${({ theme }) => theme.colors.primary200};
2716
+ background: ${({ theme }) => theme.colors.primary100};
2717
+ color: ${({ theme }) => theme.colors.primary600};
2628
2718
  }
2629
2719
  `;
2630
- const NonRepeatableComponent = ({
2631
- attribute,
2632
- name: name2,
2633
- children,
2634
- layout
2720
+ const ComponentPicker = ({
2721
+ dynamicComponentsByCategory = {},
2722
+ isOpen,
2723
+ onClickAddComponent
2635
2724
  }) => {
2636
- const { value } = useField(name2);
2637
- const level = useComponent("NonRepeatableComponent", (state) => state.level);
2638
- const isNested = level > 0;
2639
- return /* @__PURE__ */ jsx(ComponentProvider, { id: value?.id, uid: attribute.component, level: level + 1, type: "component", children: /* @__PURE__ */ jsx(
2725
+ const { formatMessage } = useIntl();
2726
+ const handleAddComponentToDz = (componentUid) => () => {
2727
+ onClickAddComponent(componentUid);
2728
+ };
2729
+ if (!isOpen) {
2730
+ return null;
2731
+ }
2732
+ return /* @__PURE__ */ jsxs(
2640
2733
  Box,
2641
2734
  {
2642
- background: "neutral100",
2643
- paddingLeft: 6,
2644
- paddingRight: 6,
2645
2735
  paddingTop: 6,
2646
2736
  paddingBottom: 6,
2647
- hasRadius: isNested,
2648
- borderColor: isNested ? "neutral200" : void 0,
2649
- children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((row, index) => {
2650
- return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
2651
- const completeFieldName = `${name2}.${field.name}`;
2652
- return /* @__PURE__ */ jsx(Grid$1.Item, { col: size, s: 12, xs: 12, children: children({ ...field, name: completeFieldName }) }, completeFieldName);
2653
- }) }, index);
2654
- }) })
2737
+ paddingLeft: 5,
2738
+ paddingRight: 5,
2739
+ background: "neutral0",
2740
+ shadow: "tableShadow",
2741
+ borderColor: "neutral150",
2742
+ hasRadius: true,
2743
+ children: [
2744
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral600", children: formatMessage({
2745
+ id: getTranslation("components.DynamicZone.ComponentPicker-label"),
2746
+ defaultMessage: "Pick one component"
2747
+ }) }) }),
2748
+ /* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */ jsx(Accordion.Root, { defaultValue: Object.keys(dynamicComponentsByCategory)[0], children: Object.entries(dynamicComponentsByCategory).map(([category, components], index) => /* @__PURE__ */ jsx(
2749
+ ComponentCategory,
2750
+ {
2751
+ category,
2752
+ components,
2753
+ onAddComponent: handleAddComponentToDz,
2754
+ variant: index % 2 === 1 ? "primary" : "secondary"
2755
+ },
2756
+ category
2757
+ )) }) })
2758
+ ]
2655
2759
  }
2656
- ) });
2760
+ );
2657
2761
  };
2658
- const RepeatableComponent = ({
2659
- attribute,
2762
+ const DynamicComponent = ({
2763
+ componentUid,
2660
2764
  disabled,
2765
+ index,
2661
2766
  name: name2,
2662
- mainField,
2663
- children,
2664
- layout
2767
+ onRemoveComponentClick,
2768
+ onMoveComponent,
2769
+ onGrabItem,
2770
+ onDropItem,
2771
+ onCancel,
2772
+ dynamicComponentsByCategory = {},
2773
+ onAddComponent,
2774
+ children
2665
2775
  }) => {
2666
- const { toggleNotification } = useNotification();
2667
2776
  const { formatMessage } = useIntl();
2668
- const { search: searchString } = useLocation();
2669
- const search = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
2670
- const { components } = useDoc();
2671
- const { value = [], error } = useField(name2);
2672
- const addFieldRow = useForm("RepeatableComponent", (state) => state.addFieldRow);
2673
- const moveFieldRow = useForm("RepeatableComponent", (state) => state.moveFieldRow);
2674
- const removeFieldRow = useForm("RepeatableComponent", (state) => state.removeFieldRow);
2675
- const { max = Infinity } = attribute;
2676
- const [collapseToOpen, setCollapseToOpen] = React.useState("");
2677
- const [liveText, setLiveText] = React.useState("");
2678
- const componentTmpKeyWithFocussedField = React.useMemo(() => {
2679
- if (search.has("field")) {
2680
- const fieldParam = search.get("field");
2681
- if (!fieldParam) {
2682
- return void 0;
2683
- }
2684
- const [, path] = fieldParam.split(`${name2}.`);
2685
- if (getIn(value, path, void 0) !== void 0) {
2686
- const [subpath] = path.split(".");
2687
- return getIn(value, subpath, void 0)?.__temp_key__;
2688
- }
2689
- }
2690
- return void 0;
2691
- }, [search, name2, value]);
2692
- const prevValue = usePrev(value);
2777
+ const formValues = useForm("DynamicComponent", (state) => state.values);
2778
+ const {
2779
+ edit: { components }
2780
+ } = useDocLayout();
2781
+ const title = React.useMemo(() => {
2782
+ const { mainField } = components[componentUid]?.settings ?? { mainField: "id" };
2783
+ const mainFieldValue = getIn(formValues, `${name2}.${index}.${mainField}`);
2784
+ const displayedValue = mainField === "id" || !mainFieldValue ? "" : String(mainFieldValue).trim();
2785
+ const mainValue = displayedValue.length > 0 ? `- ${displayedValue}` : displayedValue;
2786
+ return mainValue;
2787
+ }, [componentUid, components, formValues, name2, index]);
2788
+ const { icon, displayName } = React.useMemo(() => {
2789
+ const [category] = componentUid.split(".");
2790
+ const { icon: icon2, displayName: displayName2 } = (dynamicComponentsByCategory[category] ?? []).find(
2791
+ (component) => component.uid === componentUid
2792
+ ) ?? { icon: null, displayName: null };
2793
+ return { icon: icon2, displayName: displayName2 };
2794
+ }, [componentUid, dynamicComponentsByCategory]);
2795
+ const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
2796
+ type: `${ItemTypes.DYNAMIC_ZONE}_${name2}`,
2797
+ index,
2798
+ item: {
2799
+ index,
2800
+ displayedValue: `${displayName} ${title}`,
2801
+ icon
2802
+ },
2803
+ onMoveItem: onMoveComponent,
2804
+ onDropItem,
2805
+ onGrabItem,
2806
+ onCancel
2807
+ });
2693
2808
  React.useEffect(() => {
2694
- if (prevValue && prevValue.length < value.length) {
2695
- setCollapseToOpen(value[value.length - 1].__temp_key__);
2696
- }
2697
- }, [value, prevValue]);
2809
+ dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
2810
+ }, [dragPreviewRef, index]);
2811
+ const accordionValue = React.useId();
2812
+ const { value = [], rawError } = useField(`${name2}.${index}`);
2813
+ const [collapseToOpen, setCollapseToOpen] = React.useState("");
2698
2814
  React.useEffect(() => {
2699
- if (typeof componentTmpKeyWithFocussedField === "string") {
2700
- setCollapseToOpen(componentTmpKeyWithFocussedField);
2701
- }
2702
- }, [componentTmpKeyWithFocussedField]);
2703
- const toggleCollapses = () => {
2704
- setCollapseToOpen("");
2705
- };
2706
- const handleClick = () => {
2707
- if (value.length < max) {
2708
- const schema = components[attribute.component];
2709
- const form = createDefaultForm(schema, components);
2710
- const data = transformDocument(schema, components)(form);
2711
- addFieldRow(name2, data);
2712
- } else if (value.length >= max) {
2713
- toggleNotification({
2714
- type: "info",
2715
- message: formatMessage({
2716
- id: getTranslation("components.notification.info.maximum-requirement")
2717
- })
2718
- });
2815
+ if (rawError && value) {
2816
+ setCollapseToOpen(accordionValue);
2719
2817
  }
2720
- };
2721
- const handleMoveComponentField = (newIndex, currentIndex) => {
2722
- setLiveText(
2723
- formatMessage(
2724
- {
2725
- id: getTranslation("dnd.reorder"),
2726
- defaultMessage: "{item}, moved. New position in list: {position}."
2727
- },
2728
- {
2729
- item: `${name2}.${currentIndex}`,
2730
- position: getItemPos(newIndex)
2731
- }
2732
- )
2733
- );
2734
- moveFieldRow(name2, currentIndex, newIndex);
2735
- };
2736
- const handleValueChange = (key) => {
2737
- setCollapseToOpen(key);
2738
- };
2739
- const getItemPos = (index) => `${index + 1} of ${value.length}`;
2740
- const handleCancel = (index) => {
2741
- setLiveText(
2742
- formatMessage(
2743
- {
2744
- id: getTranslation("dnd.cancel-item"),
2745
- defaultMessage: "{item}, dropped. Re-order cancelled."
2746
- },
2747
- {
2748
- item: `${name2}.${index}`
2749
- }
2750
- )
2751
- );
2752
- };
2753
- const handleGrabItem = (index) => {
2754
- setLiveText(
2755
- formatMessage(
2756
- {
2757
- id: getTranslation("dnd.grab-item"),
2758
- defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
2759
- },
2818
+ }, [rawError, value, accordionValue]);
2819
+ const composedBoxRefs = useComposedRefs(boxRef, dropRef);
2820
+ const accordionActions = disabled ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
2821
+ /* @__PURE__ */ jsx(
2822
+ IconButton,
2823
+ {
2824
+ variant: "ghost",
2825
+ label: formatMessage(
2826
+ {
2827
+ id: getTranslation("components.DynamicZone.delete-label"),
2828
+ defaultMessage: "Delete {name}"
2829
+ },
2830
+ { name: title }
2831
+ ),
2832
+ onClick: onRemoveComponentClick,
2833
+ children: /* @__PURE__ */ jsx(Trash, {})
2834
+ }
2835
+ ),
2836
+ /* @__PURE__ */ jsx(
2837
+ IconButton,
2838
+ {
2839
+ variant: "ghost",
2840
+ onClick: (e) => e.stopPropagation(),
2841
+ "data-handler-id": handlerId,
2842
+ ref: dragRef,
2843
+ label: formatMessage({
2844
+ id: getTranslation("components.DragHandle-label"),
2845
+ defaultMessage: "Drag"
2846
+ }),
2847
+ onKeyDown: handleKeyDown,
2848
+ children: /* @__PURE__ */ jsx(Drag, {})
2849
+ }
2850
+ ),
2851
+ /* @__PURE__ */ jsxs(Menu.Root, { children: [
2852
+ /* @__PURE__ */ jsx(Menu.Trigger, { size: "S", endIcon: null, paddingLeft: 0, paddingRight: 0, children: /* @__PURE__ */ jsx(
2853
+ IconButton,
2760
2854
  {
2761
- item: `${name2}.${index}`,
2762
- position: getItemPos(index)
2855
+ variant: "ghost",
2856
+ label: formatMessage({
2857
+ id: getTranslation("components.DynamicZone.more-actions"),
2858
+ defaultMessage: "More actions"
2859
+ }),
2860
+ tag: "span",
2861
+ children: /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false })
2763
2862
  }
2764
- )
2765
- );
2766
- };
2767
- const handleDropItem = (index) => {
2768
- setLiveText(
2769
- formatMessage(
2770
- {
2771
- id: getTranslation("dnd.drop-item"),
2772
- defaultMessage: `{item}, dropped. Final position in list: {position}.`
2773
- },
2863
+ ) }),
2864
+ /* @__PURE__ */ jsxs(Menu.Content, { children: [
2865
+ /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
2866
+ /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
2867
+ id: getTranslation("components.DynamicZone.add-item-above"),
2868
+ defaultMessage: "Add component above"
2869
+ }) }),
2870
+ /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
2871
+ /* @__PURE__ */ jsx(Menu.Label, { children: category }),
2872
+ components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index), children: displayName2 }, componentUid))
2873
+ ] }, category)) })
2874
+ ] }),
2875
+ /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
2876
+ /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
2877
+ id: getTranslation("components.DynamicZone.add-item-below"),
2878
+ defaultMessage: "Add component below"
2879
+ }) }),
2880
+ /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
2881
+ /* @__PURE__ */ jsx(Menu.Label, { children: category }),
2882
+ components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index + 1), children: displayName2 }, componentUid))
2883
+ ] }, category)) })
2884
+ ] })
2885
+ ] })
2886
+ ] })
2887
+ ] });
2888
+ const accordionTitle = title ? `${displayName} ${title}` : displayName;
2889
+ return /* @__PURE__ */ jsxs(ComponentContainer, { tag: "li", width: "100%", children: [
2890
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Rectangle, { background: "neutral200" }) }),
2891
+ /* @__PURE__ */ jsx(StyledBox, { ref: composedBoxRefs, hasRadius: true, children: isDragging ? /* @__PURE__ */ jsx(Preview$1, {}) : /* @__PURE__ */ jsx(Accordion.Root, { value: collapseToOpen, onValueChange: setCollapseToOpen, children: /* @__PURE__ */ jsxs(Accordion.Item, { value: accordionValue, children: [
2892
+ /* @__PURE__ */ jsxs(Accordion.Header, { children: [
2893
+ /* @__PURE__ */ jsx(
2894
+ Accordion.Trigger,
2895
+ {
2896
+ icon: icon && COMPONENT_ICONS[icon] ? COMPONENT_ICONS[icon] : COMPONENT_ICONS.dashboard,
2897
+ children: accordionTitle
2898
+ }
2899
+ ),
2900
+ /* @__PURE__ */ jsx(Accordion.Actions, { children: accordionActions })
2901
+ ] }),
2902
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(AccordionContentRadius, { background: "neutral0", children: /* @__PURE__ */ jsx(Box, { paddingLeft: 6, paddingRight: 6, paddingTop: 6, paddingBottom: 6, children: /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: components[componentUid]?.layout?.map((row, rowInd) => /* @__PURE__ */ jsx(
2903
+ Grid$1.Item,
2774
2904
  {
2775
- item: `${name2}.${index}`,
2776
- position: getItemPos(index)
2777
- }
2778
- )
2779
- );
2780
- };
2781
- const ariaDescriptionId = React.useId();
2782
- const level = useComponent("RepeatableComponent", (state) => state.level);
2783
- if (value.length === 0) {
2784
- return /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleClick });
2785
- }
2786
- return /* @__PURE__ */ jsxs(Box, { hasRadius: true, children: [
2787
- /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
2788
- id: getTranslation("dnd.instructions"),
2789
- defaultMessage: `Press spacebar to grab and re-order`
2790
- }) }),
2791
- /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
2792
- /* @__PURE__ */ jsxs(
2793
- AccordionRoot,
2794
- {
2795
- $error: error,
2796
- value: collapseToOpen,
2797
- onValueChange: handleValueChange,
2798
- "aria-describedby": ariaDescriptionId,
2799
- children: [
2800
- value.map(({ __temp_key__: key, id }, index) => {
2801
- const nameWithIndex = `${name2}.${index}`;
2905
+ col: 12,
2906
+ s: 12,
2907
+ xs: 12,
2908
+ direction: "column",
2909
+ alignItems: "stretch",
2910
+ children: /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
2911
+ const fieldName = `${name2}.${index}.${field.name}`;
2912
+ const fieldWithTranslatedLabel = {
2913
+ ...field,
2914
+ label: formatMessage({
2915
+ id: `content-manager.components.${componentUid}.${field.name}`,
2916
+ defaultMessage: field.label
2917
+ })
2918
+ };
2802
2919
  return /* @__PURE__ */ jsx(
2803
- ComponentProvider,
2920
+ ResponsiveGridItem,
2804
2921
  {
2805
- id,
2806
- uid: attribute.component,
2807
- level: level + 1,
2808
- type: "repeatable",
2809
- children: /* @__PURE__ */ jsx(
2810
- Component,
2811
- {
2812
- disabled,
2813
- name: nameWithIndex,
2814
- attribute,
2815
- index,
2816
- mainField,
2817
- onMoveItem: handleMoveComponentField,
2818
- onDeleteComponent: () => {
2819
- removeFieldRow(name2, index);
2820
- toggleCollapses();
2821
- },
2822
- toggleCollapses,
2823
- onCancel: handleCancel,
2824
- onDropItem: handleDropItem,
2825
- onGrabItem: handleGrabItem,
2826
- __temp_key__: key,
2827
- children: layout.map((row, index2) => {
2828
- return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
2829
- const completeFieldName = `${nameWithIndex}.${field.name}`;
2830
- return /* @__PURE__ */ jsx(Grid$1.Item, { col: size, s: 12, xs: 12, children: children({ ...field, name: completeFieldName }) }, completeFieldName);
2831
- }) }, index2);
2832
- })
2833
- }
2834
- )
2922
+ col: size,
2923
+ s: 12,
2924
+ xs: 12,
2925
+ direction: "column",
2926
+ alignItems: "stretch",
2927
+ children: children ? children({ ...fieldWithTranslatedLabel, name: fieldName }) : /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel, name: fieldName })
2835
2928
  },
2836
- key
2929
+ fieldName
2837
2930
  );
2838
- }),
2839
- /* @__PURE__ */ jsx(TextButtonCustom, { disabled, onClick: handleClick, startIcon: /* @__PURE__ */ jsx(Plus, {}), children: formatMessage({
2840
- id: getTranslation("containers.EditView.add.new-entry"),
2841
- defaultMessage: "Add an entry"
2842
2931
  }) })
2843
- ]
2844
- }
2845
- )
2932
+ },
2933
+ rowInd
2934
+ )) }) }) }) })
2935
+ ] }) }) })
2846
2936
  ] });
2847
2937
  };
2848
- const AccordionRoot = styled(Accordion.Root)`
2849
- border: 1px solid
2850
- ${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
2851
- `;
2852
- const TextButtonCustom = styled(TextButton)`
2853
- width: 100%;
2854
- display: flex;
2855
- justify-content: center;
2856
- border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
2857
- padding-inline: ${(props) => props.theme.spaces[6]};
2858
- padding-block: ${(props) => props.theme.spaces[3]};
2859
-
2860
- &:not([disabled]) {
2861
- cursor: pointer;
2862
-
2863
- &:hover {
2864
- background-color: ${(props) => props.theme.colors.primary100};
2865
- }
2866
- }
2867
-
2868
- span {
2869
- font-weight: 600;
2870
- font-size: 1.4rem;
2871
- line-height: 2.4rem;
2872
- }
2873
-
2874
- @media (prefers-reduced-motion: no-preference) {
2875
- transition: background-color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
2938
+ const StyledBox = styled(Box)`
2939
+ > div:first-child {
2940
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
2876
2941
  }
2877
2942
  `;
2878
- const Component = ({
2879
- disabled,
2880
- index,
2881
- name: name2,
2882
- mainField = {
2883
- name: "id",
2884
- type: "integer"
2885
- },
2886
- children,
2887
- onDeleteComponent,
2888
- toggleCollapses,
2889
- __temp_key__,
2890
- ...dragProps
2891
- }) => {
2892
- const { formatMessage } = useIntl();
2893
- const displayValue = useForm("RepeatableComponent", (state) => {
2894
- return getIn(state.values, [...name2.split("."), mainField.name]);
2895
- });
2896
- const accordionRef = React.useRef(null);
2897
- const componentKey = name2.split(".").slice(0, -1).join(".");
2898
- const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
2899
- type: `${ItemTypes.COMPONENT}_${componentKey}`,
2900
- index,
2901
- item: {
2902
- index,
2903
- displayedValue: displayValue
2904
- },
2905
- onStart() {
2906
- toggleCollapses();
2907
- },
2908
- ...dragProps
2909
- });
2910
- React.useEffect(() => {
2911
- dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
2912
- }, [dragPreviewRef, index]);
2913
- const composedAccordionRefs = useComposedRefs(accordionRef, dragRef);
2914
- const composedBoxRefs = useComposedRefs(
2915
- boxRef,
2916
- dropRef
2917
- );
2918
- return /* @__PURE__ */ jsx(Fragment, { children: isDragging ? /* @__PURE__ */ jsx(Preview$1, {}) : /* @__PURE__ */ jsxs(Accordion.Item, { ref: composedBoxRefs, value: __temp_key__, children: [
2919
- /* @__PURE__ */ jsxs(Accordion.Header, { children: [
2920
- /* @__PURE__ */ jsx(Accordion.Trigger, { children: displayValue }),
2921
- /* @__PURE__ */ jsxs(Accordion.Actions, { children: [
2922
- /* @__PURE__ */ jsx(
2923
- IconButton,
2924
- {
2925
- borderWidth: 0,
2926
- onClick: onDeleteComponent,
2927
- label: formatMessage({
2928
- id: getTranslation("containers.Edit.delete"),
2929
- defaultMessage: "Delete"
2930
- }),
2931
- children: /* @__PURE__ */ jsx(Trash, {})
2932
- }
2933
- ),
2934
- /* @__PURE__ */ jsx(
2935
- IconButton,
2936
- {
2937
- ref: composedAccordionRefs,
2938
- borderWidth: 0,
2939
- onClick: (e) => e.stopPropagation(),
2940
- "data-handler-id": handlerId,
2941
- label: formatMessage({
2942
- id: getTranslation("components.DragHandle-label"),
2943
- defaultMessage: "Drag"
2944
- }),
2945
- onKeyDown: handleKeyDown,
2946
- children: /* @__PURE__ */ jsx(Drag, {})
2947
- }
2948
- )
2949
- ] })
2950
- ] }),
2951
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(
2952
- Flex,
2953
- {
2954
- direction: "column",
2955
- alignItems: "stretch",
2956
- background: "neutral100",
2957
- padding: 6,
2958
- gap: 6,
2959
- children
2960
- }
2961
- ) })
2962
- ] }) });
2963
- };
2964
- const Preview$1 = () => {
2965
- return /* @__PURE__ */ jsx(StyledSpan, { tag: "span", padding: 6, background: "primary100" });
2966
- };
2967
- const StyledSpan = styled(Box)`
2943
+ const AccordionContentRadius = styled(Box)`
2944
+ border-radius: 0 0 ${({ theme }) => theme.spaces[1]} ${({ theme }) => theme.spaces[1]};
2945
+ `;
2946
+ const Rectangle = styled(Box)`
2947
+ width: ${({ theme }) => theme.spaces[2]};
2948
+ height: ${({ theme }) => theme.spaces[4]};
2949
+ `;
2950
+ const Preview$1 = styled.span`
2968
2951
  display: block;
2952
+ background-color: ${({ theme }) => theme.colors.primary100};
2969
2953
  outline: 1px dashed ${({ theme }) => theme.colors.primary500};
2970
2954
  outline-offset: -1px;
2955
+ padding: ${({ theme }) => theme.spaces[6]};
2971
2956
  `;
2972
- const ComponentInput = ({
2957
+ const ComponentContainer = styled(Box)`
2958
+ list-style: none;
2959
+ padding: 0;
2960
+ margin: 0;
2961
+ `;
2962
+ const DynamicZoneLabel = ({
2963
+ hint,
2973
2964
  label,
2974
- required,
2975
- name: name2,
2976
- attribute,
2977
- disabled,
2978
2965
  labelAction,
2979
- ...props
2980
- }) => {
2981
- const { formatMessage } = useIntl();
2982
- const field = useField(name2);
2983
- const showResetComponent = !attribute.repeatable && field.value && !disabled;
2984
- const { components } = useDoc();
2985
- const handleInitialisationClick = () => {
2986
- const schema = components[attribute.component];
2987
- const form = createDefaultForm(schema, components);
2988
- const data = transformDocument(schema, components)(form);
2989
- field.onChange(name2, data);
2990
- };
2991
- return /* @__PURE__ */ jsxs(Field.Root, { error: field.error, required, children: [
2992
- /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
2993
- /* @__PURE__ */ jsxs(Field.Label, { action: labelAction, children: [
2994
- label,
2995
- attribute.repeatable && /* @__PURE__ */ jsxs(Fragment, { children: [
2996
- " (",
2997
- Array.isArray(field.value) ? field.value.length : 0,
2998
- ")"
2999
- ] })
3000
- ] }),
3001
- showResetComponent && /* @__PURE__ */ jsx(
3002
- IconButton,
3003
- {
3004
- label: formatMessage({
3005
- id: getTranslation("components.reset-entry"),
3006
- defaultMessage: "Reset Entry"
3007
- }),
3008
- borderWidth: 0,
3009
- onClick: () => {
3010
- field.onChange(name2, null);
3011
- },
3012
- children: /* @__PURE__ */ jsx(Trash, {})
3013
- }
3014
- )
3015
- ] }),
3016
- !attribute.repeatable && !field.value && /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleInitialisationClick }),
3017
- !attribute.repeatable && field.value ? /* @__PURE__ */ jsx(NonRepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }) : null,
3018
- attribute.repeatable && /* @__PURE__ */ jsx(RepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }),
3019
- /* @__PURE__ */ jsx(Field.Error, {})
3020
- ] });
3021
- };
3022
- const MemoizedComponentInput = React.memo(ComponentInput);
3023
- const AddComponentButton = ({
3024
- hasError,
3025
- isDisabled,
3026
- isOpen,
3027
- children,
3028
- onClick
2966
+ name: name2,
2967
+ numberOfComponents = 0,
2968
+ required
3029
2969
  }) => {
3030
- return /* @__PURE__ */ jsx(
3031
- StyledButton,
2970
+ return /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
2971
+ Box,
3032
2972
  {
3033
- type: "button",
3034
- onClick,
3035
- disabled: isDisabled,
3036
- background: "neutral0",
3037
2973
  paddingTop: 3,
3038
2974
  paddingBottom: 3,
3039
- paddingLeft: 4,
3040
2975
  paddingRight: 4,
3041
- style: { cursor: isDisabled ? "not-allowed" : "pointer" },
3042
- children: /* @__PURE__ */ jsxs(Flex, { tag: "span", gap: 2, children: [
3043
- /* @__PURE__ */ jsx(StyledAddIcon, { "aria-hidden": true, $isOpen: isOpen, $hasError: hasError && !isOpen }),
3044
- /* @__PURE__ */ jsx(
3045
- AddComponentTitle,
3046
- {
3047
- variant: "pi",
3048
- fontWeight: "bold",
3049
- textColor: hasError && !isOpen ? "danger600" : "neutral500",
3050
- children
3051
- }
3052
- )
3053
- ] })
3054
- }
3055
- );
3056
- };
3057
- const StyledAddIcon = styled(PlusCircle)`
3058
- height: ${({ theme }) => theme.spaces[6]};
3059
- width: ${({ theme }) => theme.spaces[6]};
3060
- transform: ${({ $isOpen }) => $isOpen ? "rotate(45deg)" : "rotate(0deg)"};
3061
-
3062
- > circle {
3063
- fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150};
3064
- }
3065
- > path {
3066
- fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger600 : theme.colors.neutral600};
3067
- }
3068
- `;
3069
- const AddComponentTitle = styled(Typography)``;
3070
- const StyledButton = styled(BaseButton)`
3071
- border-radius: 26px;
3072
- border-color: ${({ theme }) => theme.colors.neutral150};
3073
- box-shadow: ${({ theme }) => theme.shadows.filterShadow};
3074
-
3075
- &:hover {
3076
- ${AddComponentTitle} {
3077
- color: ${({ theme }) => theme.colors.primary600};
2976
+ paddingLeft: 4,
2977
+ borderRadius: "26px",
2978
+ background: "neutral0",
2979
+ shadow: "filterShadow",
2980
+ color: "neutral500",
2981
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", justifyContent: "center", children: [
2982
+ /* @__PURE__ */ jsxs(Flex, { maxWidth: "35.6rem", children: [
2983
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", ellipsis: true, children: [
2984
+ label || name2,
2985
+ " "
2986
+ ] }),
2987
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", children: [
2988
+ "(",
2989
+ numberOfComponents,
2990
+ ")"
2991
+ ] }),
2992
+ required && /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: "*" }),
2993
+ labelAction && /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: labelAction })
2994
+ ] }),
2995
+ hint && /* @__PURE__ */ jsx(Box, { paddingTop: 1, maxWidth: "35.6rem", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", ellipsis: true, children: hint }) })
2996
+ ] })
3078
2997
  }
3079
-
3080
- ${StyledAddIcon} {
3081
- > circle {
3082
- fill: ${({ theme }) => theme.colors.primary600};
3083
- }
3084
- > path {
3085
- fill: ${({ theme }) => theme.colors.neutral100};
2998
+ ) });
2999
+ };
3000
+ const [DynamicZoneProvider, useDynamicZone] = createContext(
3001
+ "DynamicZone",
3002
+ {
3003
+ isInDynamicZone: false
3004
+ }
3005
+ );
3006
+ const DynamicZone = ({
3007
+ attribute,
3008
+ disabled: disabledProp,
3009
+ hint,
3010
+ label,
3011
+ labelAction,
3012
+ name: name2,
3013
+ required = false,
3014
+ children
3015
+ }) => {
3016
+ const { max = Infinity, min = -Infinity } = attribute ?? {};
3017
+ const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false);
3018
+ const [liveText, setLiveText] = React.useState("");
3019
+ const { components, isLoading } = useDoc();
3020
+ const disabled = disabledProp || isLoading;
3021
+ const { addFieldRow, removeFieldRow, moveFieldRow } = useForm(
3022
+ "DynamicZone",
3023
+ ({ addFieldRow: addFieldRow2, removeFieldRow: removeFieldRow2, moveFieldRow: moveFieldRow2 }) => ({
3024
+ addFieldRow: addFieldRow2,
3025
+ removeFieldRow: removeFieldRow2,
3026
+ moveFieldRow: moveFieldRow2
3027
+ })
3028
+ );
3029
+ const { value = [], error } = useField(name2);
3030
+ const dynamicComponentsByCategory = React.useMemo(() => {
3031
+ return attribute.components.reduce((acc, componentUid) => {
3032
+ const { category, info } = components[componentUid] ?? { info: {} };
3033
+ const component = { uid: componentUid, displayName: info.displayName, icon: info.icon };
3034
+ if (!acc[category]) {
3035
+ acc[category] = [];
3086
3036
  }
3037
+ acc[category] = [...acc[category], component];
3038
+ return acc;
3039
+ }, {});
3040
+ }, [attribute.components, components]);
3041
+ const { formatMessage } = useIntl();
3042
+ const { toggleNotification } = useNotification();
3043
+ const dynamicDisplayedComponentsLength = value.length;
3044
+ const handleAddComponent = (uid, position) => {
3045
+ setAddComponentIsOpen(false);
3046
+ const schema = components[uid];
3047
+ const form = createDefaultForm(schema, components);
3048
+ const transformations = pipe$1(transformDocument(schema, components), (data2) => ({
3049
+ ...data2,
3050
+ __component: uid
3051
+ }));
3052
+ const data = transformations(form);
3053
+ addFieldRow(name2, data, position);
3054
+ };
3055
+ const handleClickOpenPicker = () => {
3056
+ if (dynamicDisplayedComponentsLength < max) {
3057
+ setAddComponentIsOpen((prev) => !prev);
3058
+ } else {
3059
+ toggleNotification({
3060
+ type: "info",
3061
+ message: formatMessage({
3062
+ id: getTranslation("components.notification.info.maximum-requirement")
3063
+ })
3064
+ });
3087
3065
  }
3088
- }
3089
- &:active {
3090
- ${AddComponentTitle} {
3091
- color: ${({ theme }) => theme.colors.primary600};
3066
+ };
3067
+ const handleMoveComponent = (newIndex, currentIndex) => {
3068
+ setLiveText(
3069
+ formatMessage(
3070
+ {
3071
+ id: getTranslation("dnd.reorder"),
3072
+ defaultMessage: "{item}, moved. New position in list: {position}."
3073
+ },
3074
+ {
3075
+ item: `${name2}.${currentIndex}`,
3076
+ position: getItemPos(newIndex)
3077
+ }
3078
+ )
3079
+ );
3080
+ moveFieldRow(name2, currentIndex, newIndex);
3081
+ };
3082
+ const getItemPos = (index) => `${index + 1} of ${value.length}`;
3083
+ const handleCancel = (index) => {
3084
+ setLiveText(
3085
+ formatMessage(
3086
+ {
3087
+ id: getTranslation("dnd.cancel-item"),
3088
+ defaultMessage: "{item}, dropped. Re-order cancelled."
3089
+ },
3090
+ {
3091
+ item: `${name2}.${index}`
3092
+ }
3093
+ )
3094
+ );
3095
+ };
3096
+ const handleGrabItem = (index) => {
3097
+ setLiveText(
3098
+ formatMessage(
3099
+ {
3100
+ id: getTranslation("dnd.grab-item"),
3101
+ defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
3102
+ },
3103
+ {
3104
+ item: `${name2}.${index}`,
3105
+ position: getItemPos(index)
3106
+ }
3107
+ )
3108
+ );
3109
+ };
3110
+ const handleDropItem = (index) => {
3111
+ setLiveText(
3112
+ formatMessage(
3113
+ {
3114
+ id: getTranslation("dnd.drop-item"),
3115
+ defaultMessage: `{item}, dropped. Final position in list: {position}.`
3116
+ },
3117
+ {
3118
+ item: `${name2}.${index}`,
3119
+ position: getItemPos(index)
3120
+ }
3121
+ )
3122
+ );
3123
+ };
3124
+ const handleRemoveComponent = (name22, currentIndex) => () => {
3125
+ removeFieldRow(name22, currentIndex);
3126
+ };
3127
+ const hasError = error !== void 0;
3128
+ const renderButtonLabel = () => {
3129
+ if (addComponentIsOpen) {
3130
+ return formatMessage({ id: "app.utils.close-label", defaultMessage: "Close" });
3092
3131
  }
3093
- ${StyledAddIcon} {
3094
- > circle {
3095
- fill: ${({ theme }) => theme.colors.primary600};
3096
- }
3097
- > path {
3098
- fill: ${({ theme }) => theme.colors.neutral100};
3099
- }
3132
+ if (hasError && dynamicDisplayedComponentsLength > max) {
3133
+ return formatMessage(
3134
+ {
3135
+ id: getTranslation(`components.DynamicZone.extra-components`),
3136
+ defaultMessage: "There {number, plural, =0 {are # extra components} one {is # extra component} other {are # extra components}}"
3137
+ },
3138
+ {
3139
+ number: dynamicDisplayedComponentsLength - max
3140
+ }
3141
+ );
3100
3142
  }
3101
- }
3102
- `;
3103
- const ComponentCategory = ({
3104
- category,
3105
- components = [],
3106
- variant = "primary",
3107
- onAddComponent
3108
- }) => {
3109
- const { formatMessage } = useIntl();
3110
- return /* @__PURE__ */ jsxs(Accordion.Item, { value: category, children: [
3111
- /* @__PURE__ */ jsx(Accordion.Header, { variant, children: /* @__PURE__ */ jsx(Accordion.Trigger, { children: formatMessage({ id: category, defaultMessage: category }) }) }),
3112
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Grid, { paddingTop: 4, paddingBottom: 4, paddingLeft: 3, paddingRight: 3, children: components.map(({ uid, displayName, icon }) => /* @__PURE__ */ jsx(
3113
- ComponentBox,
3143
+ if (hasError && dynamicDisplayedComponentsLength < min) {
3144
+ return formatMessage(
3145
+ {
3146
+ id: getTranslation(`components.DynamicZone.missing-components`),
3147
+ defaultMessage: "There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}"
3148
+ },
3149
+ { number: min - dynamicDisplayedComponentsLength }
3150
+ );
3151
+ }
3152
+ return formatMessage(
3114
3153
  {
3115
- tag: "button",
3116
- type: "button",
3117
- background: "neutral100",
3118
- justifyContent: "center",
3119
- onClick: onAddComponent(uid),
3120
- hasRadius: true,
3121
- height: "8.4rem",
3122
- shrink: 0,
3123
- borderColor: "neutral200",
3124
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, alignItems: "center", justifyContent: "center", children: [
3125
- /* @__PURE__ */ jsx(ComponentIcon, { color: "currentColor", background: "primary200", icon }),
3126
- /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: displayName })
3127
- ] })
3154
+ id: getTranslation("components.DynamicZone.add-component"),
3155
+ defaultMessage: "Add a component to {componentName}"
3128
3156
  },
3129
- uid
3130
- )) }) })
3131
- ] });
3132
- };
3133
- const Grid = styled(Box)`
3134
- display: grid;
3135
- grid-template-columns: repeat(auto-fit, 14rem);
3136
- grid-gap: ${({ theme }) => theme.spaces[1]};
3137
- `;
3138
- const ComponentBox = styled(Flex)`
3139
- color: ${({ theme }) => theme.colors.neutral600};
3140
- cursor: pointer;
3141
-
3142
- @media (prefers-reduced-motion: no-preference) {
3143
- transition: color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
3144
- }
3145
-
3146
- &:focus,
3147
- &:hover {
3148
- border: 1px solid ${({ theme }) => theme.colors.primary200};
3149
- background: ${({ theme }) => theme.colors.primary100};
3150
- color: ${({ theme }) => theme.colors.primary600};
3151
- }
3152
- `;
3153
- const ComponentPicker = ({
3154
- dynamicComponentsByCategory = {},
3155
- isOpen,
3156
- onClickAddComponent
3157
- }) => {
3158
- const { formatMessage } = useIntl();
3159
- const handleAddComponentToDz = (componentUid) => () => {
3160
- onClickAddComponent(componentUid);
3157
+ { componentName: label || name2 }
3158
+ );
3161
3159
  };
3162
- if (!isOpen) {
3163
- return null;
3164
- }
3165
- return /* @__PURE__ */ jsxs(
3166
- Box,
3167
- {
3168
- paddingTop: 6,
3169
- paddingBottom: 6,
3170
- paddingLeft: 5,
3171
- paddingRight: 5,
3172
- background: "neutral0",
3173
- shadow: "tableShadow",
3174
- borderColor: "neutral150",
3175
- hasRadius: true,
3176
- children: [
3177
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral600", children: formatMessage({
3178
- id: getTranslation("components.DynamicZone.ComponentPicker-label"),
3179
- defaultMessage: "Pick one component"
3180
- }) }) }),
3181
- /* @__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(
3182
- ComponentCategory,
3183
- {
3184
- category,
3185
- components,
3186
- onAddComponent: handleAddComponentToDz,
3187
- variant: index % 2 === 1 ? "primary" : "secondary"
3188
- },
3189
- category
3190
- )) }) })
3191
- ]
3192
- }
3193
- );
3160
+ const level = useComponent("DynamicZone", (state) => state.level);
3161
+ const ariaDescriptionId = React.useId();
3162
+ return /* @__PURE__ */ jsx(DynamicZoneProvider, { isInDynamicZone: true, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
3163
+ dynamicDisplayedComponentsLength > 0 && /* @__PURE__ */ jsxs(Box, { children: [
3164
+ /* @__PURE__ */ jsx(
3165
+ DynamicZoneLabel,
3166
+ {
3167
+ hint,
3168
+ label,
3169
+ labelAction,
3170
+ name: name2,
3171
+ numberOfComponents: dynamicDisplayedComponentsLength,
3172
+ required
3173
+ }
3174
+ ),
3175
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
3176
+ id: getTranslation("dnd.instructions"),
3177
+ defaultMessage: `Press spacebar to grab and re-order`
3178
+ }) }),
3179
+ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
3180
+ /* @__PURE__ */ jsx("ol", { "aria-describedby": ariaDescriptionId, children: value.map((field, index) => /* @__PURE__ */ jsx(
3181
+ ComponentProvider,
3182
+ {
3183
+ level: level + 1,
3184
+ uid: field.__component,
3185
+ id: field.id,
3186
+ type: "dynamiczone",
3187
+ children: /* @__PURE__ */ jsx(
3188
+ DynamicComponent,
3189
+ {
3190
+ disabled,
3191
+ name: name2,
3192
+ index,
3193
+ componentUid: field.__component,
3194
+ onMoveComponent: handleMoveComponent,
3195
+ onRemoveComponentClick: handleRemoveComponent(name2, index),
3196
+ onCancel: handleCancel,
3197
+ onDropItem: handleDropItem,
3198
+ onGrabItem: handleGrabItem,
3199
+ onAddComponent: handleAddComponent,
3200
+ dynamicComponentsByCategory,
3201
+ children
3202
+ }
3203
+ )
3204
+ },
3205
+ field.__temp_key__
3206
+ )) })
3207
+ ] }),
3208
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
3209
+ AddComponentButton,
3210
+ {
3211
+ hasError,
3212
+ isDisabled: disabled,
3213
+ isOpen: addComponentIsOpen,
3214
+ onClick: handleClickOpenPicker,
3215
+ children: renderButtonLabel()
3216
+ }
3217
+ ) }),
3218
+ /* @__PURE__ */ jsx(
3219
+ ComponentPicker,
3220
+ {
3221
+ dynamicComponentsByCategory,
3222
+ isOpen: addComponentIsOpen,
3223
+ onClickAddComponent: handleAddComponent
3224
+ }
3225
+ )
3226
+ ] }) });
3194
3227
  };
3195
3228
  const NotAllowedInput = ({ hint, label, required, name: name2 }) => {
3196
3229
  const { formatMessage } = useIntl();
@@ -3213,18 +3246,6 @@ const NotAllowedInput = ({ hint, label, required, name: name2 }) => {
3213
3246
  /* @__PURE__ */ jsx(Field.Hint, {})
3214
3247
  ] });
3215
3248
  };
3216
- function useDebounce(value, delay) {
3217
- const [debouncedValue, setDebouncedValue] = useState(value);
3218
- useEffect(() => {
3219
- const handler = setTimeout(() => {
3220
- setDebouncedValue(value);
3221
- }, delay);
3222
- return () => {
3223
- clearTimeout(handler);
3224
- };
3225
- }, [value, delay]);
3226
- return debouncedValue;
3227
- }
3228
3249
  const uidApi = contentManagerApi.injectEndpoints({
3229
3250
  endpoints: (builder) => ({
3230
3251
  getDefaultUID: builder.query({
@@ -3259,7 +3280,10 @@ const uidApi = contentManagerApi.injectEndpoints({
3259
3280
  config: {
3260
3281
  params
3261
3282
  }
3262
- })
3283
+ }),
3284
+ providesTags: (_res, _error, params) => [
3285
+ { type: "UidAvailability", id: params.contentTypeUID }
3286
+ ]
3263
3287
  })
3264
3288
  })
3265
3289
  });
@@ -3271,8 +3295,10 @@ const UIDInput = React.forwardRef(
3271
3295
  const allFormValues = useForm("InputUID", (form) => form.values);
3272
3296
  const [availability, setAvailability] = React.useState();
3273
3297
  const [showRegenerate, setShowRegenerate] = React.useState(false);
3298
+ const isCloning = useMatch(CLONE_PATH) !== null;
3274
3299
  const field = useField(name2);
3275
3300
  const debouncedValue = useDebounce(field.value, 300);
3301
+ const hasChanged = debouncedValue !== field.initialValue;
3276
3302
  const { toggleNotification } = useNotification();
3277
3303
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
3278
3304
  const { formatMessage } = useIntl();
@@ -3348,8 +3374,9 @@ const UIDInput = React.forwardRef(
3348
3374
  params
3349
3375
  },
3350
3376
  {
3377
+ // Don't check availability if the value is empty or wasn't changed
3351
3378
  skip: !Boolean(
3352
- debouncedValue !== field.initialValue && debouncedValue && UID_REGEX.test(debouncedValue.trim())
3379
+ (hasChanged || isCloning) && debouncedValue && UID_REGEX.test(debouncedValue.trim())
3353
3380
  )
3354
3381
  }
3355
3382
  );
@@ -3378,6 +3405,7 @@ const UIDInput = React.forwardRef(
3378
3405
  const isLoading = isGeneratingDefaultUID || isGeneratingUID || isCheckingAvailability;
3379
3406
  const fieldRef = useFocusInputField(name2);
3380
3407
  const composedRefs = useComposedRefs(ref, fieldRef);
3408
+ const shouldShowAvailability = (hasChanged || isCloning) && debouncedValue != null && availability && !showRegenerate;
3381
3409
  return /* @__PURE__ */ jsxs(Field.Root, { hint, name: name2, error: field.error, required, children: [
3382
3410
  /* @__PURE__ */ jsx(Field.Label, { action: labelAction, children: label }),
3383
3411
  /* @__PURE__ */ jsx(
@@ -3386,7 +3414,7 @@ const UIDInput = React.forwardRef(
3386
3414
  ref: composedRefs,
3387
3415
  disabled: props.disabled,
3388
3416
  endAction: /* @__PURE__ */ jsxs(Flex, { position: "relative", gap: 1, children: [
3389
- availability && !showRegenerate && /* @__PURE__ */ jsxs(
3417
+ shouldShowAvailability && /* @__PURE__ */ jsxs(
3390
3418
  TextValidation,
3391
3419
  {
3392
3420
  alignItems: "center",
@@ -3675,8 +3703,7 @@ const Wrapper = styled.div`
3675
3703
  `;
3676
3704
  var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, unorderedListRE = /[*+-]\s/;
3677
3705
  function newlineAndIndentContinueMarkdownList(cm) {
3678
- if (cm.getOption("disableInput"))
3679
- return CodeMirror.Pass;
3706
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
3680
3707
  var ranges = cm.listSelections(), replacements = [];
3681
3708
  for (var i = 0; i < ranges.length; i++) {
3682
3709
  var pos = ranges[i].head;
@@ -3710,8 +3737,7 @@ function newlineAndIndentContinueMarkdownList(cm) {
3710
3737
  var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
3711
3738
  var bullet = numbered ? parseInt(match[3], 10) + 1 + match[4] : match[2].replace("x", " ");
3712
3739
  replacements[i] = "\n" + indent + bullet + after;
3713
- if (numbered)
3714
- incrementRemainingMarkdownListNumbers(cm, pos);
3740
+ if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
3715
3741
  }
3716
3742
  }
3717
3743
  cm.replaceSelections(replacements);
@@ -3729,10 +3755,8 @@ function incrementRemainingMarkdownListNumbers(cm, pos) {
3729
3755
  var newNumber = parseInt(startItem[3], 10) + lookAhead - skipCount;
3730
3756
  var nextNumber = parseInt(nextItem[3], 10), itemNumber = nextNumber;
3731
3757
  if (startIndent === nextIndent && !isNaN(nextNumber)) {
3732
- if (newNumber === nextNumber)
3733
- itemNumber = nextNumber + 1;
3734
- if (newNumber > nextNumber)
3735
- itemNumber = newNumber + 1;
3758
+ if (newNumber === nextNumber) itemNumber = nextNumber + 1;
3759
+ if (newNumber > nextNumber) itemNumber = newNumber + 1;
3736
3760
  cm.replaceRange(
3737
3761
  nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
3738
3762
  {
@@ -3745,10 +3769,8 @@ function incrementRemainingMarkdownListNumbers(cm, pos) {
3745
3769
  }
3746
3770
  );
3747
3771
  } else {
3748
- if (startIndent.length > nextIndent.length)
3749
- return;
3750
- if (startIndent.length < nextIndent.length && lookAhead === 1)
3751
- return;
3772
+ if (startIndent.length > nextIndent.length) return;
3773
+ if (startIndent.length < nextIndent.length && lookAhead === 1) return;
3752
3774
  skipCount += 1;
3753
3775
  }
3754
3776
  }
@@ -4220,7 +4242,7 @@ const EditorLayout = ({
4220
4242
  justifyContent: "flex-end",
4221
4243
  shrink: 0,
4222
4244
  width: "100%",
4223
- children: /* @__PURE__ */ jsxs(ExpandButton$1, { onClick: onCollapse, children: [
4245
+ children: /* @__PURE__ */ jsxs(ExpandButton$1, { onClick: onCollapse, variant: "tertiary", size: "M", children: [
4224
4246
  /* @__PURE__ */ jsx(Typography, { children: formatMessage({
4225
4247
  id: "components.Wysiwyg.collapse",
4226
4248
  defaultMessage: "Collapse"
@@ -4238,12 +4260,14 @@ const EditorLayout = ({
4238
4260
  ) }) });
4239
4261
  }
4240
4262
  return /* @__PURE__ */ jsx(
4241
- Box,
4263
+ Flex,
4242
4264
  {
4243
4265
  borderColor: error ? "danger600" : "neutral200",
4244
4266
  borderStyle: "solid",
4245
4267
  borderWidth: "1px",
4246
4268
  hasRadius: true,
4269
+ direction: "column",
4270
+ alignItems: "stretch",
4247
4271
  children
4248
4272
  }
4249
4273
  );
@@ -4254,11 +4278,19 @@ const ExpandWrapper = styled(Flex)`
4254
4278
  const BoxWithBorder = styled(Box)`
4255
4279
  border-right: 1px solid ${({ theme }) => theme.colors.neutral200};
4256
4280
  `;
4257
- const ExpandButton$1 = styled(BaseButton)`
4281
+ const ExpandButton$1 = styled(Button)`
4258
4282
  background-color: transparent;
4259
4283
  border: none;
4260
4284
  align-items: center;
4261
4285
 
4286
+ & > span {
4287
+ display: flex;
4288
+ justify-content: space-between;
4289
+ align-items: center;
4290
+ width: 100%;
4291
+ font-weight: ${({ theme }) => theme.fontWeights.regular};
4292
+ }
4293
+
4262
4294
  svg {
4263
4295
  margin-left: ${({ theme }) => `${theme.spaces[2]}`};
4264
4296
 
@@ -4525,40 +4557,28 @@ const quoteAndCodeHandler = (editor, markdownType) => {
4525
4557
  insertWithoutTextToEdit(editor, markdownType, line, contentLength);
4526
4558
  }
4527
4559
  };
4528
- const CustomIconButton = styled(IconButton)`
4529
- padding: ${({ theme }) => theme.spaces[2]};
4530
-
4531
- svg {
4532
- width: 1.8rem;
4533
- height: 1.8rem;
4534
- }
4535
- `;
4536
- const CustomLinkIconButton = styled(CustomIconButton)`
4537
- svg {
4538
- width: 0.8rem;
4539
- height: 0.8rem;
4540
- }
4541
- `;
4542
4560
  const MainButtons = styled(IconButtonGroup)`
4543
4561
  margin-left: ${({ theme }) => theme.spaces[4]};
4544
4562
  `;
4545
4563
  const MoreButton = styled(IconButton)`
4546
4564
  margin: ${({ theme }) => `0 ${theme.spaces[2]}`};
4547
- padding: ${({ theme }) => theme.spaces[2]};
4548
-
4549
- svg {
4550
- width: 1.8rem;
4551
- height: 1.8rem;
4552
- }
4553
4565
  `;
4554
4566
  const IconButtonGroupMargin = styled(IconButtonGroup)`
4555
4567
  margin-right: ${({ theme }) => `${theme.spaces[2]}`};
4556
4568
  `;
4557
- const ExpandButton = styled(BaseButton)`
4569
+ const ExpandButton = styled(Button)`
4558
4570
  background-color: transparent;
4559
4571
  border: none;
4560
4572
  align-items: center;
4561
4573
 
4574
+ & > span {
4575
+ display: flex;
4576
+ justify-content: space-between;
4577
+ align-items: center;
4578
+ width: 100%;
4579
+ font-weight: ${({ theme }) => theme.fontWeights.regular};
4580
+ }
4581
+
4562
4582
  svg {
4563
4583
  margin-left: ${({ theme }) => `${theme.spaces[2]}`};
4564
4584
  path {
@@ -4570,8 +4590,8 @@ const ExpandButton = styled(BaseButton)`
4570
4590
  `;
4571
4591
  const WysiwygFooter = ({ onToggleExpand }) => {
4572
4592
  const { formatMessage } = useIntl();
4573
- return /* @__PURE__ */ jsx(Box, { padding: 2, background: "neutral100", borderRadius: `0 0 0.4rem 0.4rem`, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", alignItems: "flex-end", children: /* @__PURE__ */ jsxs(ExpandButton, { id: "expand", onClick: onToggleExpand, children: [
4574
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
4593
+ return /* @__PURE__ */ jsx(Box, { padding: 2, background: "neutral100", borderRadius: `0 0 0.4rem 0.4rem`, children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", alignItems: "flex-end", children: /* @__PURE__ */ jsxs(ExpandButton, { id: "expand", onClick: onToggleExpand, variant: "tertiary", size: "M", children: [
4594
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", children: formatMessage({
4575
4595
  id: "components.WysiwygBottomControls.fullscreen",
4576
4596
  defaultMessage: "Expand"
4577
4597
  }) }),
@@ -4607,18 +4627,27 @@ const WysiwygNav = ({
4607
4627
  borderRadius: `0.4rem 0.4rem 0 0`,
4608
4628
  children: [
4609
4629
  /* @__PURE__ */ jsxs(Flex, { children: [
4610
- /* @__PURE__ */ jsx(Field.Root, { children: /* @__PURE__ */ jsxs(SingleSelect, { disabled: true, placeholder: selectPlaceholder, "aria-label": selectPlaceholder, children: [
4611
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "h1", children: "h1" }),
4612
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "h2", children: "h2" }),
4613
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "h3", children: "h3" }),
4614
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "h4", children: "h4" }),
4615
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "h5", children: "h5" }),
4616
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "h6", children: "h6" })
4617
- ] }) }),
4630
+ /* @__PURE__ */ jsx(Field.Root, { children: /* @__PURE__ */ jsxs(
4631
+ SingleSelect,
4632
+ {
4633
+ disabled: true,
4634
+ placeholder: selectPlaceholder,
4635
+ "aria-label": selectPlaceholder,
4636
+ size: "S",
4637
+ children: [
4638
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "h1", children: "h1" }),
4639
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "h2", children: "h2" }),
4640
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "h3", children: "h3" }),
4641
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "h4", children: "h4" }),
4642
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "h5", children: "h5" }),
4643
+ /* @__PURE__ */ jsx(SingleSelectOption, { value: "h6", children: "h6" })
4644
+ ]
4645
+ }
4646
+ ) }),
4618
4647
  /* @__PURE__ */ jsxs(MainButtons, { children: [
4619
- /* @__PURE__ */ jsx(CustomIconButton, { disabled: true, label: "Bold", name: "Bold", children: /* @__PURE__ */ jsx(Bold, {}) }),
4620
- /* @__PURE__ */ jsx(CustomIconButton, { disabled: true, label: "Italic", name: "Italic", children: /* @__PURE__ */ jsx(Italic, {}) }),
4621
- /* @__PURE__ */ jsx(CustomIconButton, { disabled: true, label: "Underline", name: "Underline", children: /* @__PURE__ */ jsx(Underline, {}) })
4648
+ /* @__PURE__ */ jsx(IconButton, { disabled: true, label: "Bold", name: "Bold", children: /* @__PURE__ */ jsx(Bold, {}) }),
4649
+ /* @__PURE__ */ jsx(IconButton, { disabled: true, label: "Italic", name: "Italic", children: /* @__PURE__ */ jsx(Italic, {}) }),
4650
+ /* @__PURE__ */ jsx(IconButton, { disabled: true, label: "Underline", name: "Underline", children: /* @__PURE__ */ jsx(Underline, {}) })
4622
4651
  ] }),
4623
4652
  /* @__PURE__ */ jsx(MoreButton, { disabled: true, label: "More", children: /* @__PURE__ */ jsx(More, {}) })
4624
4653
  ] }),
@@ -4645,6 +4674,7 @@ const WysiwygNav = ({
4645
4674
  placeholder: selectPlaceholder,
4646
4675
  "aria-label": selectPlaceholder,
4647
4676
  onChange: (value) => onActionClick(value, editorRef),
4677
+ size: "S",
4648
4678
  children: [
4649
4679
  /* @__PURE__ */ jsx(SingleSelectOption, { value: "h1", children: "h1" }),
4650
4680
  /* @__PURE__ */ jsx(SingleSelectOption, { value: "h2", children: "h2" }),
@@ -4656,17 +4686,9 @@ const WysiwygNav = ({
4656
4686
  }
4657
4687
  ) }),
4658
4688
  /* @__PURE__ */ jsxs(MainButtons, { children: [
4689
+ /* @__PURE__ */ jsx(IconButton, { onClick: () => onActionClick("Bold", editorRef), label: "Bold", name: "Bold", children: /* @__PURE__ */ jsx(Bold, {}) }),
4659
4690
  /* @__PURE__ */ jsx(
4660
- CustomIconButton,
4661
- {
4662
- onClick: () => onActionClick("Bold", editorRef),
4663
- label: "Bold",
4664
- name: "Bold",
4665
- children: /* @__PURE__ */ jsx(Bold, {})
4666
- }
4667
- ),
4668
- /* @__PURE__ */ jsx(
4669
- CustomIconButton,
4691
+ IconButton,
4670
4692
  {
4671
4693
  onClick: () => onActionClick("Italic", editorRef),
4672
4694
  label: "Italic",
@@ -4675,7 +4697,7 @@ const WysiwygNav = ({
4675
4697
  }
4676
4698
  ),
4677
4699
  /* @__PURE__ */ jsx(
4678
- CustomIconButton,
4700
+ IconButton,
4679
4701
  {
4680
4702
  onClick: () => onActionClick("Underline", editorRef),
4681
4703
  label: "Underline",
@@ -4689,7 +4711,7 @@ const WysiwygNav = ({
4689
4711
  /* @__PURE__ */ jsx(Popover.Content, { sideOffset: 12, children: /* @__PURE__ */ jsxs(Flex, { padding: 2, children: [
4690
4712
  /* @__PURE__ */ jsxs(IconButtonGroupMargin, { children: [
4691
4713
  /* @__PURE__ */ jsx(
4692
- CustomIconButton,
4714
+ IconButton,
4693
4715
  {
4694
4716
  onClick: () => onActionClick("Strikethrough", editorRef, handleTogglePopover),
4695
4717
  label: "Strikethrough",
@@ -4698,7 +4720,7 @@ const WysiwygNav = ({
4698
4720
  }
4699
4721
  ),
4700
4722
  /* @__PURE__ */ jsx(
4701
- CustomIconButton,
4723
+ IconButton,
4702
4724
  {
4703
4725
  onClick: () => onActionClick("BulletList", editorRef, handleTogglePopover),
4704
4726
  label: "BulletList",
@@ -4707,7 +4729,7 @@ const WysiwygNav = ({
4707
4729
  }
4708
4730
  ),
4709
4731
  /* @__PURE__ */ jsx(
4710
- CustomIconButton,
4732
+ IconButton,
4711
4733
  {
4712
4734
  onClick: () => onActionClick("NumberList", editorRef, handleTogglePopover),
4713
4735
  label: "NumberList",
@@ -4718,7 +4740,7 @@ const WysiwygNav = ({
4718
4740
  ] }),
4719
4741
  /* @__PURE__ */ jsxs(IconButtonGroup, { children: [
4720
4742
  /* @__PURE__ */ jsx(
4721
- CustomIconButton,
4743
+ IconButton,
4722
4744
  {
4723
4745
  onClick: () => onActionClick("Code", editorRef, handleTogglePopover),
4724
4746
  label: "Code",
@@ -4727,7 +4749,7 @@ const WysiwygNav = ({
4727
4749
  }
4728
4750
  ),
4729
4751
  /* @__PURE__ */ jsx(
4730
- CustomIconButton,
4752
+ IconButton,
4731
4753
  {
4732
4754
  onClick: () => {
4733
4755
  handleTogglePopover();
@@ -4739,7 +4761,7 @@ const WysiwygNav = ({
4739
4761
  }
4740
4762
  ),
4741
4763
  /* @__PURE__ */ jsx(
4742
- CustomLinkIconButton,
4764
+ IconButton,
4743
4765
  {
4744
4766
  onClick: () => onActionClick("Link", editorRef, handleTogglePopover),
4745
4767
  label: "Link",
@@ -4748,7 +4770,7 @@ const WysiwygNav = ({
4748
4770
  }
4749
4771
  ),
4750
4772
  /* @__PURE__ */ jsx(
4751
- CustomIconButton,
4773
+ IconButton,
4752
4774
  {
4753
4775
  onClick: () => onActionClick("Quote", editorRef, handleTogglePopover),
4754
4776
  label: "Quote",
@@ -4885,15 +4907,19 @@ const Wysiwyg = React.forwardRef(
4885
4907
  );
4886
4908
  const MemoizedWysiwyg = React.memo(Wysiwyg);
4887
4909
  const InputRenderer = ({ visible, hint: providedHint, ...props }) => {
4888
- const { id } = useDoc();
4910
+ const { id, document: document2, collectionType } = useDoc();
4889
4911
  const isFormDisabled = useForm("InputRenderer", (state) => state.disabled);
4890
4912
  const isInDynamicZone = useDynamicZone("isInDynamicZone", (state) => state.isInDynamicZone);
4891
4913
  const canCreateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canCreateFields);
4892
4914
  const canReadFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canReadFields);
4893
4915
  const canUpdateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUpdateFields);
4894
4916
  const canUserAction = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUserAction);
4895
- const editableFields = id ? canUpdateFields : canCreateFields;
4896
- const readableFields = id ? canReadFields : canCreateFields;
4917
+ let idToCheck = id;
4918
+ if (collectionType === SINGLE_TYPES) {
4919
+ idToCheck = document2?.documentId;
4920
+ }
4921
+ const editableFields = idToCheck ? canUpdateFields : canCreateFields;
4922
+ const readableFields = idToCheck ? canReadFields : canCreateFields;
4897
4923
  const canUserReadField = canUserAction(props.name, readableFields, props.type);
4898
4924
  const canUserEditField = canUserAction(props.name, editableFields, props.type);
4899
4925
  const fields = useStrapiApp("InputRenderer", (app) => app.fields);
@@ -4904,6 +4930,7 @@ const InputRenderer = ({ visible, hint: providedHint, ...props }) => {
4904
4930
  const {
4905
4931
  edit: { components }
4906
4932
  } = useDocLayout();
4933
+ const field = useField(props.name);
4907
4934
  if (!visible) {
4908
4935
  return null;
4909
4936
  }
@@ -4914,553 +4941,645 @@ const InputRenderer = ({ visible, hint: providedHint, ...props }) => {
4914
4941
  if (attributeHasCustomFieldProperty(props.attribute)) {
4915
4942
  const CustomInput = lazyComponentStore[props.attribute.customField];
4916
4943
  if (CustomInput) {
4917
- return /* @__PURE__ */ jsx(CustomInput, { ...props, hint, disabled: fieldIsDisabled });
4944
+ return /* @__PURE__ */ jsx(CustomInput, { ...props, ...field, hint, disabled: fieldIsDisabled });
4945
+ }
4946
+ return /* @__PURE__ */ jsx(
4947
+ InputRenderer$1,
4948
+ {
4949
+ ...props,
4950
+ hint,
4951
+ type: props.attribute.customField,
4952
+ disabled: fieldIsDisabled
4953
+ }
4954
+ );
4955
+ }
4956
+ const addedInputTypes = Object.keys(fields);
4957
+ if (!attributeHasCustomFieldProperty(props.attribute) && addedInputTypes.includes(props.type)) {
4958
+ const CustomInput = fields[props.type];
4959
+ return /* @__PURE__ */ jsx(CustomInput, { ...props, hint, disabled: fieldIsDisabled });
4960
+ }
4961
+ switch (props.type) {
4962
+ case "blocks":
4963
+ return /* @__PURE__ */ jsx(MemoizedBlocksInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4964
+ case "component":
4965
+ return /* @__PURE__ */ jsx(
4966
+ MemoizedComponentInput,
4967
+ {
4968
+ ...props,
4969
+ hint,
4970
+ layout: components[props.attribute.component].layout,
4971
+ disabled: fieldIsDisabled,
4972
+ children: (inputProps) => /* @__PURE__ */ jsx(InputRenderer, { ...inputProps })
4973
+ }
4974
+ );
4975
+ case "dynamiczone":
4976
+ return /* @__PURE__ */ jsx(DynamicZone, { ...props, hint, disabled: fieldIsDisabled });
4977
+ case "relation":
4978
+ return /* @__PURE__ */ jsx(MemoizedRelationsField, { ...props, hint, disabled: fieldIsDisabled });
4979
+ case "richtext":
4980
+ return /* @__PURE__ */ jsx(MemoizedWysiwyg, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4981
+ case "uid":
4982
+ return /* @__PURE__ */ jsx(MemoizedUIDInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4983
+ case "enumeration":
4984
+ return /* @__PURE__ */ jsx(
4985
+ InputRenderer$1,
4986
+ {
4987
+ ...props,
4988
+ hint,
4989
+ options: props.attribute.enum.map((value) => ({ value })),
4990
+ type: props.customField ? "custom-field" : props.type,
4991
+ disabled: fieldIsDisabled
4992
+ }
4993
+ );
4994
+ default:
4995
+ const { unique: _unique, mainField: _mainField, ...restProps } = props;
4996
+ return /* @__PURE__ */ jsx(
4997
+ InputRenderer$1,
4998
+ {
4999
+ ...restProps,
5000
+ hint,
5001
+ type: props.customField ? "custom-field" : props.type,
5002
+ disabled: fieldIsDisabled
5003
+ }
5004
+ );
5005
+ }
5006
+ };
5007
+ const attributeHasCustomFieldProperty = (attribute) => "customField" in attribute && typeof attribute.customField === "string";
5008
+ const useFieldHint = (hint = void 0, attribute) => {
5009
+ const { formatMessage } = useIntl();
5010
+ const { maximum, minimum } = getMinMax(attribute);
5011
+ if (!maximum && !minimum) {
5012
+ return hint;
5013
+ }
5014
+ const units = !["biginteger", "integer", "number", "dynamiczone", "component"].includes(
5015
+ attribute.type
5016
+ ) ? formatMessage(
5017
+ {
5018
+ id: "content-manager.form.Input.hint.character.unit",
5019
+ defaultMessage: "{maxValue, plural, one { character} other { characters}}"
5020
+ },
5021
+ {
5022
+ maxValue: Math.max(minimum || 0, maximum || 0)
5023
+ }
5024
+ ) : null;
5025
+ const hasMinAndMax = typeof minimum === "number" && typeof maximum === "number";
5026
+ return formatMessage(
5027
+ {
5028
+ id: "content-manager.form.Input.hint.text",
5029
+ defaultMessage: "{min, select, undefined {} other {min. {min}}}{divider}{max, select, undefined {} other {max. {max}}}{unit}{br}{description}"
5030
+ },
5031
+ {
5032
+ min: minimum,
5033
+ max: maximum,
5034
+ description: hint,
5035
+ unit: units,
5036
+ divider: hasMinAndMax ? formatMessage({
5037
+ id: "content-manager.form.Input.hint.minMaxDivider",
5038
+ defaultMessage: " / "
5039
+ }) : null,
5040
+ br: /* @__PURE__ */ jsx("br", {})
5041
+ }
5042
+ );
5043
+ };
5044
+ const getMinMax = (attribute) => {
5045
+ if ("min" in attribute || "max" in attribute) {
5046
+ return {
5047
+ maximum: !Number.isNaN(Number(attribute.max)) ? Number(attribute.max) : void 0,
5048
+ minimum: !Number.isNaN(Number(attribute.min)) ? Number(attribute.min) : void 0
5049
+ };
5050
+ } else if ("maxLength" in attribute || "minLength" in attribute) {
5051
+ return { maximum: attribute.maxLength, minimum: attribute.minLength };
5052
+ } else {
5053
+ return { maximum: void 0, minimum: void 0 };
5054
+ }
5055
+ };
5056
+ const MemoizedInputRenderer = memo(InputRenderer);
5057
+ const RESPONSIVE_CONTAINER_BREAKPOINTS = {
5058
+ sm: "27.5rem"
5059
+ // 440px
5060
+ };
5061
+ const ResponsiveGridRoot = styled(Grid$1.Root)`
5062
+ container-type: inline-size;
5063
+ `;
5064
+ const ResponsiveGridItem = styled(Grid$1.Item)`
5065
+ grid-column: span 12;
5066
+
5067
+ @container (min-width: ${RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
5068
+ ${({ col }) => col && `grid-column: span ${col};`}
5069
+ }
5070
+ `;
5071
+ const FormLayout = ({ layout }) => {
5072
+ const { formatMessage } = useIntl();
5073
+ const { model } = useDoc();
5074
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((panel, index) => {
5075
+ if (panel.some((row) => row.some((field) => field.type === "dynamiczone"))) {
5076
+ const [row] = panel;
5077
+ const [field] = row;
5078
+ const fieldWithTranslatedLabel = {
5079
+ ...field,
5080
+ label: formatMessage({
5081
+ id: `content-manager.content-types.${model}.${field.name}`,
5082
+ defaultMessage: field.label
5083
+ })
5084
+ };
5085
+ return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: /* @__PURE__ */ jsx(Grid$1.Item, { col: 12, s: 12, xs: 12, direction: "column", alignItems: "stretch", children: /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel }) }) }, field.name);
5086
+ }
5087
+ return /* @__PURE__ */ jsx(
5088
+ Box,
5089
+ {
5090
+ hasRadius: true,
5091
+ background: "neutral0",
5092
+ shadow: "tableShadow",
5093
+ paddingLeft: 6,
5094
+ paddingRight: 6,
5095
+ paddingTop: 6,
5096
+ paddingBottom: 6,
5097
+ borderColor: "neutral150",
5098
+ children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: panel.map((row, gridRowIndex) => /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
5099
+ const fieldWithTranslatedLabel = {
5100
+ ...field,
5101
+ label: formatMessage({
5102
+ id: `content-manager.content-types.${model}.${field.name}`,
5103
+ defaultMessage: field.label
5104
+ })
5105
+ };
5106
+ return /* @__PURE__ */ jsx(
5107
+ ResponsiveGridItem,
5108
+ {
5109
+ col: size,
5110
+ s: 12,
5111
+ xs: 12,
5112
+ direction: "column",
5113
+ alignItems: "stretch",
5114
+ children: /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel })
5115
+ },
5116
+ field.name
5117
+ );
5118
+ }) }, gridRowIndex)) })
5119
+ },
5120
+ index
5121
+ );
5122
+ }) });
5123
+ };
5124
+ const NonRepeatableComponent = ({
5125
+ attribute,
5126
+ name: name2,
5127
+ children,
5128
+ layout
5129
+ }) => {
5130
+ const { formatMessage } = useIntl();
5131
+ const { value } = useField(name2);
5132
+ const level = useComponent("NonRepeatableComponent", (state) => state.level);
5133
+ const isNested = level > 0;
5134
+ return /* @__PURE__ */ jsx(ComponentProvider, { id: value?.id, uid: attribute.component, level: level + 1, type: "component", children: /* @__PURE__ */ jsx(
5135
+ Box,
5136
+ {
5137
+ background: "neutral100",
5138
+ paddingLeft: 6,
5139
+ paddingRight: 6,
5140
+ paddingTop: 6,
5141
+ paddingBottom: 6,
5142
+ hasRadius: isNested,
5143
+ borderColor: isNested ? "neutral200" : void 0,
5144
+ children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((row, index) => {
5145
+ return /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
5146
+ const completeFieldName = `${name2}.${field.name}`;
5147
+ const translatedLabel = formatMessage({
5148
+ id: `content-manager.components.${attribute.component}.${field.name}`,
5149
+ defaultMessage: field.label
5150
+ });
5151
+ return /* @__PURE__ */ jsx(
5152
+ ResponsiveGridItem,
5153
+ {
5154
+ col: size,
5155
+ s: 12,
5156
+ xs: 12,
5157
+ direction: "column",
5158
+ alignItems: "stretch",
5159
+ children: children({ ...field, label: translatedLabel, name: completeFieldName })
5160
+ },
5161
+ completeFieldName
5162
+ );
5163
+ }) }, index);
5164
+ }) })
5165
+ }
5166
+ ) });
5167
+ };
5168
+ const RepeatableComponent = ({
5169
+ attribute,
5170
+ disabled,
5171
+ name: name2,
5172
+ mainField,
5173
+ children,
5174
+ layout
5175
+ }) => {
5176
+ const { toggleNotification } = useNotification();
5177
+ const { formatMessage } = useIntl();
5178
+ const { search: searchString } = useLocation();
5179
+ const search = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
5180
+ const { components } = useDoc();
5181
+ const {
5182
+ value = [],
5183
+ error,
5184
+ rawError
5185
+ } = useField(name2);
5186
+ const addFieldRow = useForm("RepeatableComponent", (state) => state.addFieldRow);
5187
+ const moveFieldRow = useForm("RepeatableComponent", (state) => state.moveFieldRow);
5188
+ const removeFieldRow = useForm("RepeatableComponent", (state) => state.removeFieldRow);
5189
+ const { max = Infinity } = attribute;
5190
+ const [collapseToOpen, setCollapseToOpen] = React.useState("");
5191
+ const [liveText, setLiveText] = React.useState("");
5192
+ React.useEffect(() => {
5193
+ const hasNestedErrors = rawError && Array.isArray(rawError) && rawError.length > 0;
5194
+ const hasNestedValue = value && Array.isArray(value) && value.length > 0;
5195
+ if (hasNestedErrors && hasNestedValue) {
5196
+ const errorOpenItems = rawError.map((_, idx) => {
5197
+ return value[idx] ? value[idx].__temp_key__ : null;
5198
+ }).filter((value2) => !!value2);
5199
+ if (errorOpenItems && errorOpenItems.length > 0) {
5200
+ setCollapseToOpen((collapseToOpen2) => {
5201
+ if (!errorOpenItems.includes(collapseToOpen2)) {
5202
+ return errorOpenItems[0];
5203
+ }
5204
+ return collapseToOpen2;
5205
+ });
5206
+ }
4918
5207
  }
4919
- return /* @__PURE__ */ jsx(
4920
- InputRenderer$1,
4921
- {
4922
- ...props,
4923
- hint,
4924
- type: props.attribute.customField,
4925
- disabled: fieldIsDisabled
5208
+ }, [rawError, value]);
5209
+ const componentTmpKeyWithFocussedField = React.useMemo(() => {
5210
+ if (search.has("field")) {
5211
+ const fieldParam = search.get("field");
5212
+ if (!fieldParam) {
5213
+ return void 0;
4926
5214
  }
5215
+ const [, path] = fieldParam.split(`${name2}.`);
5216
+ if (getIn(value, path, void 0) !== void 0) {
5217
+ const [subpath] = path.split(".");
5218
+ return getIn(value, subpath, void 0)?.__temp_key__;
5219
+ }
5220
+ }
5221
+ return void 0;
5222
+ }, [search, name2, value]);
5223
+ const prevValue = usePrev(value);
5224
+ React.useEffect(() => {
5225
+ if (prevValue && prevValue.length < value.length) {
5226
+ setCollapseToOpen(value[value.length - 1].__temp_key__);
5227
+ }
5228
+ }, [value, prevValue]);
5229
+ React.useEffect(() => {
5230
+ if (typeof componentTmpKeyWithFocussedField === "string") {
5231
+ setCollapseToOpen(componentTmpKeyWithFocussedField);
5232
+ }
5233
+ }, [componentTmpKeyWithFocussedField]);
5234
+ const toggleCollapses = () => {
5235
+ setCollapseToOpen("");
5236
+ };
5237
+ const handleClick = () => {
5238
+ if (value.length < max) {
5239
+ const schema = components[attribute.component];
5240
+ const form = createDefaultForm(schema, components);
5241
+ const data = transformDocument(schema, components)(form);
5242
+ addFieldRow(name2, data);
5243
+ } else if (value.length >= max) {
5244
+ toggleNotification({
5245
+ type: "info",
5246
+ message: formatMessage({
5247
+ id: getTranslation("components.notification.info.maximum-requirement")
5248
+ })
5249
+ });
5250
+ }
5251
+ };
5252
+ const handleMoveComponentField = (newIndex, currentIndex) => {
5253
+ setLiveText(
5254
+ formatMessage(
5255
+ {
5256
+ id: getTranslation("dnd.reorder"),
5257
+ defaultMessage: "{item}, moved. New position in list: {position}."
5258
+ },
5259
+ {
5260
+ item: `${name2}.${currentIndex}`,
5261
+ position: getItemPos(newIndex)
5262
+ }
5263
+ )
4927
5264
  );
4928
- }
4929
- const addedInputTypes = Object.keys(fields);
4930
- if (!attributeHasCustomFieldProperty(props.attribute) && addedInputTypes.includes(props.type)) {
4931
- const CustomInput = fields[props.type];
4932
- return /* @__PURE__ */ jsx(CustomInput, { ...props, hint, disabled: fieldIsDisabled });
4933
- }
4934
- switch (props.type) {
4935
- case "blocks":
4936
- return /* @__PURE__ */ jsx(MemoizedBlocksInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4937
- case "component":
4938
- return /* @__PURE__ */ jsx(
4939
- MemoizedComponentInput,
5265
+ moveFieldRow(name2, currentIndex, newIndex);
5266
+ };
5267
+ const handleValueChange = (key) => {
5268
+ setCollapseToOpen(key);
5269
+ };
5270
+ const getItemPos = (index) => `${index + 1} of ${value.length}`;
5271
+ const handleCancel = (index) => {
5272
+ setLiveText(
5273
+ formatMessage(
4940
5274
  {
4941
- ...props,
4942
- hint,
4943
- layout: components[props.attribute.component].layout,
4944
- disabled: fieldIsDisabled,
4945
- children: (inputProps) => /* @__PURE__ */ jsx(InputRenderer, { ...inputProps })
5275
+ id: getTranslation("dnd.cancel-item"),
5276
+ defaultMessage: "{item}, dropped. Re-order cancelled."
5277
+ },
5278
+ {
5279
+ item: `${name2}.${index}`
4946
5280
  }
4947
- );
4948
- case "dynamiczone":
4949
- return /* @__PURE__ */ jsx(DynamicZone, { ...props, hint, disabled: fieldIsDisabled });
4950
- case "relation":
4951
- return /* @__PURE__ */ jsx(MemoizedRelationsField, { ...props, hint, disabled: fieldIsDisabled });
4952
- case "richtext":
4953
- return /* @__PURE__ */ jsx(MemoizedWysiwyg, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4954
- case "uid":
4955
- return /* @__PURE__ */ jsx(MemoizedUIDInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4956
- case "enumeration":
4957
- return /* @__PURE__ */ jsx(
4958
- InputRenderer$1,
5281
+ )
5282
+ );
5283
+ };
5284
+ const handleGrabItem = (index) => {
5285
+ setLiveText(
5286
+ formatMessage(
4959
5287
  {
4960
- ...props,
4961
- hint,
4962
- options: props.attribute.enum.map((value) => ({ value })),
4963
- type: props.customField ? "custom-field" : props.type,
4964
- disabled: fieldIsDisabled
5288
+ id: getTranslation("dnd.grab-item"),
5289
+ defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
5290
+ },
5291
+ {
5292
+ item: `${name2}.${index}`,
5293
+ position: getItemPos(index)
4965
5294
  }
4966
- );
4967
- default:
4968
- const { unique: _unique, mainField: _mainField, ...restProps } = props;
4969
- return /* @__PURE__ */ jsx(
4970
- InputRenderer$1,
5295
+ )
5296
+ );
5297
+ };
5298
+ const handleDropItem = (index) => {
5299
+ setLiveText(
5300
+ formatMessage(
4971
5301
  {
4972
- ...restProps,
4973
- hint,
4974
- type: props.customField ? "custom-field" : props.type,
4975
- disabled: fieldIsDisabled
5302
+ id: getTranslation("dnd.drop-item"),
5303
+ defaultMessage: `{item}, dropped. Final position in list: {position}.`
5304
+ },
5305
+ {
5306
+ item: `${name2}.${index}`,
5307
+ position: getItemPos(index)
4976
5308
  }
4977
- );
5309
+ )
5310
+ );
5311
+ };
5312
+ const ariaDescriptionId = React.useId();
5313
+ const level = useComponent("RepeatableComponent", (state) => state.level);
5314
+ if (value.length === 0) {
5315
+ return /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleClick });
4978
5316
  }
5317
+ return /* @__PURE__ */ jsxs(Box, { hasRadius: true, children: [
5318
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
5319
+ id: getTranslation("dnd.instructions"),
5320
+ defaultMessage: `Press spacebar to grab and re-order`
5321
+ }) }),
5322
+ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
5323
+ /* @__PURE__ */ jsxs(
5324
+ AccordionRoot,
5325
+ {
5326
+ $error: error,
5327
+ value: collapseToOpen,
5328
+ onValueChange: handleValueChange,
5329
+ "aria-describedby": ariaDescriptionId,
5330
+ children: [
5331
+ value.map(({ __temp_key__: key, id }, index) => {
5332
+ const nameWithIndex = `${name2}.${index}`;
5333
+ return /* @__PURE__ */ jsx(
5334
+ ComponentProvider,
5335
+ {
5336
+ id,
5337
+ uid: attribute.component,
5338
+ level: level + 1,
5339
+ type: "repeatable",
5340
+ children: /* @__PURE__ */ jsx(
5341
+ Component,
5342
+ {
5343
+ disabled,
5344
+ name: nameWithIndex,
5345
+ attribute,
5346
+ index,
5347
+ mainField,
5348
+ onMoveItem: handleMoveComponentField,
5349
+ onDeleteComponent: () => {
5350
+ removeFieldRow(name2, index);
5351
+ toggleCollapses();
5352
+ },
5353
+ toggleCollapses,
5354
+ onCancel: handleCancel,
5355
+ onDropItem: handleDropItem,
5356
+ onGrabItem: handleGrabItem,
5357
+ __temp_key__: key,
5358
+ children: layout.map((row, index2) => {
5359
+ return /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
5360
+ const completeFieldName = `${nameWithIndex}.${field.name}`;
5361
+ const translatedLabel = formatMessage({
5362
+ id: `content-manager.components.${attribute.component}.${field.name}`,
5363
+ defaultMessage: field.label
5364
+ });
5365
+ return /* @__PURE__ */ jsx(
5366
+ ResponsiveGridItem,
5367
+ {
5368
+ col: size,
5369
+ s: 12,
5370
+ xs: 12,
5371
+ direction: "column",
5372
+ alignItems: "stretch",
5373
+ children: children({
5374
+ ...field,
5375
+ label: translatedLabel,
5376
+ name: completeFieldName
5377
+ })
5378
+ },
5379
+ completeFieldName
5380
+ );
5381
+ }) }, index2);
5382
+ })
5383
+ }
5384
+ )
5385
+ },
5386
+ key
5387
+ );
5388
+ }),
5389
+ /* @__PURE__ */ jsx(TextButtonCustom, { disabled, onClick: handleClick, startIcon: /* @__PURE__ */ jsx(Plus, {}), children: formatMessage({
5390
+ id: getTranslation("containers.EditView.add.new-entry"),
5391
+ defaultMessage: "Add an entry"
5392
+ }) })
5393
+ ]
5394
+ }
5395
+ )
5396
+ ] });
4979
5397
  };
4980
- const attributeHasCustomFieldProperty = (attribute) => "customField" in attribute && typeof attribute.customField === "string";
4981
- const useFieldHint = (hint = void 0, attribute) => {
4982
- const { formatMessage } = useIntl();
4983
- const { maximum, minimum } = getMinMax(attribute);
4984
- if (!maximum && !minimum) {
4985
- return hint;
4986
- }
4987
- const units = !["biginteger", "integer", "number"].includes(attribute.type) ? formatMessage(
4988
- {
4989
- id: "content-manager.form.Input.hint.character.unit",
4990
- defaultMessage: "{maxValue, plural, one { character} other { characters}}"
4991
- },
4992
- {
4993
- maxValue: Math.max(minimum || 0, maximum || 0)
4994
- }
4995
- ) : null;
4996
- const hasMinAndMax = typeof minimum === "number" && typeof maximum === "number";
4997
- return formatMessage(
4998
- {
4999
- id: "content-manager.form.Input.hint.text",
5000
- defaultMessage: "{min, select, undefined {} other {min. {min}}}{divider}{max, select, undefined {} other {max. {max}}}{unit}{br}{description}"
5001
- },
5002
- {
5003
- min: minimum,
5004
- max: maximum,
5005
- description: hint,
5006
- unit: units,
5007
- divider: hasMinAndMax ? formatMessage({
5008
- id: "content-manager.form.Input.hint.minMaxDivider",
5009
- defaultMessage: " / "
5010
- }) : null,
5011
- br: /* @__PURE__ */ jsx("br", {})
5398
+ const AccordionRoot = styled(Accordion.Root)`
5399
+ border: 1px solid
5400
+ ${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
5401
+ `;
5402
+ const TextButtonCustom = styled(TextButton)`
5403
+ width: 100%;
5404
+ display: flex;
5405
+ justify-content: center;
5406
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
5407
+ padding-inline: ${(props) => props.theme.spaces[6]};
5408
+ padding-block: ${(props) => props.theme.spaces[3]};
5409
+
5410
+ &:not([disabled]) {
5411
+ cursor: pointer;
5412
+
5413
+ &:hover {
5414
+ background-color: ${(props) => props.theme.colors.primary100};
5012
5415
  }
5013
- );
5014
- };
5015
- const getMinMax = (attribute) => {
5016
- if ("min" in attribute || "max" in attribute) {
5017
- return {
5018
- maximum: !Number.isNaN(Number(attribute.max)) ? Number(attribute.max) : void 0,
5019
- minimum: !Number.isNaN(Number(attribute.min)) ? Number(attribute.min) : void 0
5020
- };
5021
- } else if ("maxLength" in attribute || "minLength" in attribute) {
5022
- return { maximum: attribute.maxLength, minimum: attribute.minLength };
5023
- } else {
5024
- return { maximum: void 0, minimum: void 0 };
5025
5416
  }
5026
- };
5027
- const MemoizedInputRenderer = memo(InputRenderer);
5028
- const DynamicComponent = ({
5029
- componentUid,
5417
+
5418
+ span {
5419
+ font-weight: 600;
5420
+ font-size: 1.4rem;
5421
+ line-height: 2.4rem;
5422
+ }
5423
+
5424
+ @media (prefers-reduced-motion: no-preference) {
5425
+ transition: background-color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
5426
+ }
5427
+ `;
5428
+ const Component = ({
5030
5429
  disabled,
5031
5430
  index,
5032
5431
  name: name2,
5033
- onRemoveComponentClick,
5034
- onMoveComponent,
5035
- onGrabItem,
5036
- onDropItem,
5037
- onCancel,
5038
- dynamicComponentsByCategory = {},
5039
- onAddComponent
5432
+ mainField = {
5433
+ name: "id",
5434
+ type: "integer"
5435
+ },
5436
+ children,
5437
+ onDeleteComponent,
5438
+ toggleCollapses,
5439
+ __temp_key__,
5440
+ ...dragProps
5040
5441
  }) => {
5041
5442
  const { formatMessage } = useIntl();
5042
- const formValues = useForm("DynamicComponent", (state) => state.values);
5043
- const {
5044
- edit: { components }
5045
- } = useDocLayout();
5046
- const title = React.useMemo(() => {
5047
- const { mainField } = components[componentUid]?.settings ?? { mainField: "id" };
5048
- const mainFieldValue = getIn(formValues, `${name2}.${index}.${mainField}`);
5049
- const displayedValue = mainField === "id" || !mainFieldValue ? "" : String(mainFieldValue).trim();
5050
- const mainValue = displayedValue.length > 0 ? `- ${displayedValue}` : displayedValue;
5051
- return mainValue;
5052
- }, [componentUid, components, formValues, name2, index]);
5053
- const { icon, displayName } = React.useMemo(() => {
5054
- const [category] = componentUid.split(".");
5055
- const { icon: icon2, displayName: displayName2 } = (dynamicComponentsByCategory[category] ?? []).find(
5056
- (component) => component.uid === componentUid
5057
- ) ?? { icon: null, displayName: null };
5058
- return { icon: icon2, displayName: displayName2 };
5059
- }, [componentUid, dynamicComponentsByCategory]);
5443
+ const displayValue = useForm("RepeatableComponent", (state) => {
5444
+ return getIn(state.values, [...name2.split("."), mainField.name]);
5445
+ });
5446
+ const accordionRef = React.useRef(null);
5447
+ const componentKey = name2.split(".").slice(0, -1).join(".");
5060
5448
  const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
5061
- type: `${ItemTypes.DYNAMIC_ZONE}_${name2}`,
5449
+ type: `${ItemTypes.COMPONENT}_${componentKey}`,
5062
5450
  index,
5063
5451
  item: {
5064
5452
  index,
5065
- displayedValue: `${displayName} ${title}`,
5066
- icon
5453
+ displayedValue: displayValue
5067
5454
  },
5068
- onMoveItem: onMoveComponent,
5069
- onDropItem,
5070
- onGrabItem,
5071
- onCancel
5455
+ onStart() {
5456
+ toggleCollapses();
5457
+ },
5458
+ ...dragProps
5072
5459
  });
5073
5460
  React.useEffect(() => {
5074
5461
  dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
5075
5462
  }, [dragPreviewRef, index]);
5076
- const composedBoxRefs = useComposedRefs(boxRef, dropRef);
5077
- const accordionActions = disabled ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
5078
- /* @__PURE__ */ jsx(
5079
- IconButton,
5080
- {
5081
- borderWidth: 0,
5082
- label: formatMessage(
5463
+ const composedAccordionRefs = useComposedRefs(accordionRef, dragRef);
5464
+ const composedBoxRefs = useComposedRefs(
5465
+ boxRef,
5466
+ dropRef
5467
+ );
5468
+ return /* @__PURE__ */ jsx(Fragment, { children: isDragging ? /* @__PURE__ */ jsx(Preview, {}) : /* @__PURE__ */ jsxs(Accordion.Item, { ref: composedBoxRefs, value: __temp_key__, children: [
5469
+ /* @__PURE__ */ jsxs(Accordion.Header, { children: [
5470
+ /* @__PURE__ */ jsx(Accordion.Trigger, { children: displayValue }),
5471
+ /* @__PURE__ */ jsxs(Accordion.Actions, { children: [
5472
+ /* @__PURE__ */ jsx(
5473
+ IconButton,
5083
5474
  {
5084
- id: getTranslation("components.DynamicZone.delete-label"),
5085
- defaultMessage: "Delete {name}"
5086
- },
5087
- { name: title }
5475
+ variant: "ghost",
5476
+ onClick: onDeleteComponent,
5477
+ label: formatMessage({
5478
+ id: getTranslation("containers.Edit.delete"),
5479
+ defaultMessage: "Delete"
5480
+ }),
5481
+ children: /* @__PURE__ */ jsx(Trash, {})
5482
+ }
5088
5483
  ),
5089
- onClick: onRemoveComponentClick,
5090
- children: /* @__PURE__ */ jsx(Trash, {})
5091
- }
5092
- ),
5093
- /* @__PURE__ */ jsx(
5094
- IconButton,
5095
- {
5096
- borderWidth: 0,
5097
- onClick: (e) => e.stopPropagation(),
5098
- "data-handler-id": handlerId,
5099
- ref: dragRef,
5100
- label: formatMessage({
5101
- id: getTranslation("components.DragHandle-label"),
5102
- defaultMessage: "Drag"
5103
- }),
5104
- onKeyDown: handleKeyDown,
5105
- children: /* @__PURE__ */ jsx(Drag, {})
5106
- }
5107
- ),
5108
- /* @__PURE__ */ jsxs(Menu.Root, { children: [
5109
- /* @__PURE__ */ jsxs(Menu.Trigger, { size: "S", endIcon: null, paddingLeft: 2, paddingRight: 2, children: [
5110
- /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
5111
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage({
5112
- id: getTranslation("components.DynamicZone.more-actions"),
5113
- defaultMessage: "More actions"
5114
- }) })
5115
- ] }),
5116
- /* @__PURE__ */ jsxs(Menu.Content, { children: [
5117
- /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
5118
- /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
5119
- id: getTranslation("components.DynamicZone.add-item-above"),
5120
- defaultMessage: "Add component above"
5121
- }) }),
5122
- /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
5123
- /* @__PURE__ */ jsx(Menu.Label, { children: category }),
5124
- components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index), children: displayName2 }, componentUid))
5125
- ] }, category)) })
5126
- ] }),
5127
- /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
5128
- /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
5129
- id: getTranslation("components.DynamicZone.add-item-below"),
5130
- defaultMessage: "Add component below"
5131
- }) }),
5132
- /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
5133
- /* @__PURE__ */ jsx(Menu.Label, { children: category }),
5134
- components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index + 1), children: displayName2 }, componentUid))
5135
- ] }, category)) })
5136
- ] })
5137
- ] })
5138
- ] })
5139
- ] });
5140
- const accordionTitle = title ? `${displayName} ${title}` : displayName;
5141
- const accordionValue = React.useId();
5142
- return /* @__PURE__ */ jsxs(ComponentContainer, { tag: "li", width: "100%", children: [
5143
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Rectangle, { background: "neutral200" }) }),
5144
- /* @__PURE__ */ jsx(StyledBox, { ref: composedBoxRefs, hasRadius: true, children: isDragging ? /* @__PURE__ */ jsx(Preview, {}) : /* @__PURE__ */ jsx(Accordion.Root, { children: /* @__PURE__ */ jsxs(Accordion.Item, { value: accordionValue, children: [
5145
- /* @__PURE__ */ jsxs(Accordion.Header, { children: [
5146
5484
  /* @__PURE__ */ jsx(
5147
- Accordion.Trigger,
5485
+ IconButton,
5148
5486
  {
5149
- icon: icon && COMPONENT_ICONS[icon] ? COMPONENT_ICONS[icon] : COMPONENT_ICONS.dashboard,
5150
- children: accordionTitle
5487
+ ref: composedAccordionRefs,
5488
+ variant: "ghost",
5489
+ onClick: (e) => e.stopPropagation(),
5490
+ "data-handler-id": handlerId,
5491
+ label: formatMessage({
5492
+ id: getTranslation("components.DragHandle-label"),
5493
+ defaultMessage: "Drag"
5494
+ }),
5495
+ onKeyDown: handleKeyDown,
5496
+ children: /* @__PURE__ */ jsx(Drag, {})
5151
5497
  }
5152
- ),
5153
- /* @__PURE__ */ jsx(Accordion.Actions, { children: accordionActions })
5154
- ] }),
5155
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(AccordionContentRadius, { background: "neutral0", children: /* @__PURE__ */ jsx(Box, { paddingLeft: 6, paddingRight: 6, paddingTop: 6, paddingBottom: 6, children: components[componentUid]?.layout?.map((row, rowInd) => /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
5156
- const fieldName = `${name2}.${index}.${field.name}`;
5157
- return /* @__PURE__ */ jsx(Grid$1.Item, { col: size, s: 12, xs: 12, children: /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...field, name: fieldName }) }, fieldName);
5158
- }) }, rowInd)) }) }) })
5159
- ] }) }) })
5160
- ] });
5161
- };
5162
- const StyledBox = styled(Box)`
5163
- > div:first-child {
5164
- box-shadow: ${({ theme }) => theme.shadows.tableShadow};
5165
- }
5166
- `;
5167
- const AccordionContentRadius = styled(Box)`
5168
- border-radius: 0 0 ${({ theme }) => theme.spaces[1]} ${({ theme }) => theme.spaces[1]};
5169
- `;
5170
- const Rectangle = styled(Box)`
5171
- width: ${({ theme }) => theme.spaces[2]};
5172
- height: ${({ theme }) => theme.spaces[4]};
5173
- `;
5174
- const Preview = styled.span`
5175
- display: block;
5176
- background-color: ${({ theme }) => theme.colors.primary100};
5177
- outline: 1px dashed ${({ theme }) => theme.colors.primary500};
5178
- outline-offset: -1px;
5179
- padding: ${({ theme }) => theme.spaces[6]};
5180
- `;
5181
- const ComponentContainer = styled(Box)`
5182
- list-style: none;
5183
- padding: 0;
5184
- margin: 0;
5185
- `;
5186
- const DynamicZoneLabel = ({
5187
- hint,
5188
- label,
5189
- labelAction,
5190
- name: name2,
5191
- numberOfComponents = 0,
5192
- required
5193
- }) => {
5194
- return /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
5195
- Box,
5196
- {
5197
- paddingTop: 3,
5198
- paddingBottom: 3,
5199
- paddingRight: 4,
5200
- paddingLeft: 4,
5201
- borderRadius: "26px",
5202
- background: "neutral0",
5203
- shadow: "filterShadow",
5204
- color: "neutral500",
5205
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", justifyContent: "center", children: [
5206
- /* @__PURE__ */ jsxs(Flex, { maxWidth: "35.6rem", children: [
5207
- /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", ellipsis: true, children: [
5208
- label || name2,
5209
- " "
5210
- ] }),
5211
- /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", children: [
5212
- "(",
5213
- numberOfComponents,
5214
- ")"
5215
- ] }),
5216
- required && /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: "*" }),
5217
- labelAction && /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: labelAction })
5218
- ] }),
5219
- hint && /* @__PURE__ */ jsx(Box, { paddingTop: 1, maxWidth: "35.6rem", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", ellipsis: true, children: hint }) })
5498
+ )
5220
5499
  ] })
5221
- }
5222
- ) });
5500
+ ] }),
5501
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(
5502
+ Flex,
5503
+ {
5504
+ direction: "column",
5505
+ alignItems: "stretch",
5506
+ background: "neutral100",
5507
+ padding: 6,
5508
+ gap: 6,
5509
+ children
5510
+ }
5511
+ ) })
5512
+ ] }) });
5513
+ };
5514
+ const Preview = () => {
5515
+ return /* @__PURE__ */ jsx(StyledSpan, { tag: "span", padding: 6, background: "primary100" });
5223
5516
  };
5224
- const [DynamicZoneProvider, useDynamicZone] = createContext(
5225
- "DynamicZone",
5226
- {
5227
- isInDynamicZone: false
5228
- }
5229
- );
5230
- const DynamicZone = ({
5231
- attribute,
5232
- disabled: disabledProp,
5233
- hint,
5517
+ const StyledSpan = styled(Box)`
5518
+ display: block;
5519
+ outline: 1px dashed ${({ theme }) => theme.colors.primary500};
5520
+ outline-offset: -1px;
5521
+ `;
5522
+ const ComponentInput = ({
5234
5523
  label,
5235
- labelAction,
5524
+ required,
5236
5525
  name: name2,
5237
- required = false
5526
+ attribute,
5527
+ disabled,
5528
+ labelAction,
5529
+ ...props
5238
5530
  }) => {
5239
- const { max = Infinity, min = -Infinity } = attribute ?? {};
5240
- const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false);
5241
- const [liveText, setLiveText] = React.useState("");
5242
- const { components, isLoading } = useDoc();
5243
- const disabled = disabledProp || isLoading;
5244
- const { addFieldRow, removeFieldRow, moveFieldRow } = useForm(
5245
- "DynamicZone",
5246
- ({ addFieldRow: addFieldRow2, removeFieldRow: removeFieldRow2, moveFieldRow: moveFieldRow2 }) => ({
5247
- addFieldRow: addFieldRow2,
5248
- removeFieldRow: removeFieldRow2,
5249
- moveFieldRow: moveFieldRow2
5250
- })
5251
- );
5252
- const { value = [], error } = useField(name2);
5253
- const dynamicComponentsByCategory = React.useMemo(() => {
5254
- return attribute.components.reduce((acc, componentUid) => {
5255
- const { category, info } = components[componentUid] ?? { info: {} };
5256
- const component = { uid: componentUid, displayName: info.displayName, icon: info.icon };
5257
- if (!acc[category]) {
5258
- acc[category] = [];
5259
- }
5260
- acc[category] = [...acc[category], component];
5261
- return acc;
5262
- }, {});
5263
- }, [attribute.components, components]);
5264
5531
  const { formatMessage } = useIntl();
5265
- const { toggleNotification } = useNotification();
5266
- const dynamicDisplayedComponentsLength = value.length;
5267
- const handleAddComponent = (uid, position) => {
5268
- setAddComponentIsOpen(false);
5269
- const schema = components[uid];
5532
+ const field = useField(name2);
5533
+ const showResetComponent = !attribute.repeatable && field.value && !disabled;
5534
+ const { components } = useDoc();
5535
+ const handleInitialisationClick = () => {
5536
+ const schema = components[attribute.component];
5270
5537
  const form = createDefaultForm(schema, components);
5271
- const transformations = pipe$1(transformDocument(schema, components), (data2) => ({
5272
- ...data2,
5273
- __component: uid
5274
- }));
5275
- const data = transformations(form);
5276
- addFieldRow(name2, data, position);
5277
- };
5278
- const handleClickOpenPicker = () => {
5279
- if (dynamicDisplayedComponentsLength < max) {
5280
- setAddComponentIsOpen((prev) => !prev);
5281
- } else {
5282
- toggleNotification({
5283
- type: "info",
5284
- message: formatMessage({
5285
- id: getTranslation("components.notification.info.maximum-requirement")
5286
- })
5287
- });
5288
- }
5289
- };
5290
- const handleMoveComponent = (newIndex, currentIndex) => {
5291
- setLiveText(
5292
- formatMessage(
5293
- {
5294
- id: getTranslation("dnd.reorder"),
5295
- defaultMessage: "{item}, moved. New position in list: {position}."
5296
- },
5297
- {
5298
- item: `${name2}.${currentIndex}`,
5299
- position: getItemPos(newIndex)
5300
- }
5301
- )
5302
- );
5303
- moveFieldRow(name2, currentIndex, newIndex);
5304
- };
5305
- const getItemPos = (index) => `${index + 1} of ${value.length}`;
5306
- const handleCancel = (index) => {
5307
- setLiveText(
5308
- formatMessage(
5309
- {
5310
- id: getTranslation("dnd.cancel-item"),
5311
- defaultMessage: "{item}, dropped. Re-order cancelled."
5312
- },
5313
- {
5314
- item: `${name2}.${index}`
5315
- }
5316
- )
5317
- );
5318
- };
5319
- const handleGrabItem = (index) => {
5320
- setLiveText(
5321
- formatMessage(
5322
- {
5323
- id: getTranslation("dnd.grab-item"),
5324
- defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
5325
- },
5326
- {
5327
- item: `${name2}.${index}`,
5328
- position: getItemPos(index)
5329
- }
5330
- )
5331
- );
5538
+ const data = transformDocument(schema, components)(form);
5539
+ field.onChange(name2, data);
5332
5540
  };
5333
- const handleDropItem = (index) => {
5334
- setLiveText(
5335
- formatMessage(
5336
- {
5337
- id: getTranslation("dnd.drop-item"),
5338
- defaultMessage: `{item}, dropped. Final position in list: {position}.`
5339
- },
5541
+ return /* @__PURE__ */ jsxs(Field.Root, { error: field.error, required, children: [
5542
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
5543
+ /* @__PURE__ */ jsxs(Field.Label, { action: labelAction, children: [
5544
+ label,
5545
+ attribute.repeatable && /* @__PURE__ */ jsxs(Fragment, { children: [
5546
+ " (",
5547
+ Array.isArray(field.value) ? field.value.length : 0,
5548
+ ")"
5549
+ ] })
5550
+ ] }),
5551
+ showResetComponent && /* @__PURE__ */ jsx(
5552
+ IconButton,
5340
5553
  {
5341
- item: `${name2}.${index}`,
5342
- position: getItemPos(index)
5554
+ label: formatMessage({
5555
+ id: getTranslation("components.reset-entry"),
5556
+ defaultMessage: "Reset Entry"
5557
+ }),
5558
+ variant: "ghost",
5559
+ onClick: () => {
5560
+ field.onChange(name2, null);
5561
+ },
5562
+ children: /* @__PURE__ */ jsx(Trash, {})
5343
5563
  }
5344
5564
  )
5345
- );
5346
- };
5347
- const handleRemoveComponent = (name22, currentIndex) => () => {
5348
- removeFieldRow(name22, currentIndex);
5349
- };
5350
- const hasError = error !== void 0 || dynamicDisplayedComponentsLength < min || dynamicDisplayedComponentsLength > max;
5351
- const renderButtonLabel = () => {
5352
- if (addComponentIsOpen) {
5353
- return formatMessage({ id: "app.utils.close-label", defaultMessage: "Close" });
5354
- }
5355
- if (hasError && dynamicDisplayedComponentsLength > max) {
5356
- return formatMessage(
5357
- {
5358
- id: getTranslation(`components.DynamicZone.extra-components`),
5359
- defaultMessage: "There {number, plural, =0 {are # extra components} one {is # extra component} other {are # extra components}}"
5360
- },
5361
- {
5362
- number: dynamicDisplayedComponentsLength - max
5363
- }
5364
- );
5365
- }
5366
- if (hasError && dynamicDisplayedComponentsLength < min) {
5367
- return formatMessage(
5368
- {
5369
- id: getTranslation(`components.DynamicZone.missing-components`),
5370
- defaultMessage: "There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}"
5371
- },
5372
- { number: min - dynamicDisplayedComponentsLength }
5373
- );
5374
- }
5375
- return formatMessage(
5376
- {
5377
- id: getTranslation("components.DynamicZone.add-component"),
5378
- defaultMessage: "Add a component to {componentName}"
5379
- },
5380
- { componentName: label || name2 }
5381
- );
5382
- };
5383
- const level = useComponent("DynamicZone", (state) => state.level);
5384
- const ariaDescriptionId = React.useId();
5385
- return /* @__PURE__ */ jsx(DynamicZoneProvider, { isInDynamicZone: true, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
5386
- dynamicDisplayedComponentsLength > 0 && /* @__PURE__ */ jsxs(Box, { children: [
5387
- /* @__PURE__ */ jsx(
5388
- DynamicZoneLabel,
5389
- {
5390
- hint,
5391
- label,
5392
- labelAction,
5393
- name: name2,
5394
- numberOfComponents: dynamicDisplayedComponentsLength,
5395
- required
5396
- }
5397
- ),
5398
- /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
5399
- id: getTranslation("dnd.instructions"),
5400
- defaultMessage: `Press spacebar to grab and re-order`
5401
- }) }),
5402
- /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
5403
- /* @__PURE__ */ jsx("ol", { "aria-describedby": ariaDescriptionId, children: value.map((field, index) => /* @__PURE__ */ jsx(
5404
- ComponentProvider,
5405
- {
5406
- level: level + 1,
5407
- uid: field.__component,
5408
- id: field.id,
5409
- type: "dynamiczone",
5410
- children: /* @__PURE__ */ jsx(
5411
- DynamicComponent,
5412
- {
5413
- disabled,
5414
- name: name2,
5415
- index,
5416
- componentUid: field.__component,
5417
- onMoveComponent: handleMoveComponent,
5418
- onRemoveComponentClick: handleRemoveComponent(name2, index),
5419
- onCancel: handleCancel,
5420
- onDropItem: handleDropItem,
5421
- onGrabItem: handleGrabItem,
5422
- onAddComponent: handleAddComponent,
5423
- dynamicComponentsByCategory
5424
- }
5425
- )
5426
- },
5427
- field.__temp_key__
5428
- )) })
5429
5565
  ] }),
5430
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
5431
- AddComponentButton,
5432
- {
5433
- hasError,
5434
- isDisabled: disabled,
5435
- isOpen: addComponentIsOpen,
5436
- onClick: handleClickOpenPicker,
5437
- children: renderButtonLabel()
5438
- }
5439
- ) }),
5440
- /* @__PURE__ */ jsx(
5441
- ComponentPicker,
5442
- {
5443
- dynamicComponentsByCategory,
5444
- isOpen: addComponentIsOpen,
5445
- onClickAddComponent: handleAddComponent
5446
- }
5447
- )
5448
- ] }) });
5566
+ !attribute.repeatable && !field.value && /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleInitialisationClick }),
5567
+ !attribute.repeatable && field.value ? /* @__PURE__ */ jsx(NonRepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }) : null,
5568
+ attribute.repeatable && /* @__PURE__ */ jsx(RepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }),
5569
+ /* @__PURE__ */ jsx(Field.Error, {})
5570
+ ] });
5449
5571
  };
5572
+ const MemoizedComponentInput = React.memo(ComponentInput);
5450
5573
  export {
5451
5574
  DynamicZone as D,
5452
- MemoizedInputRenderer as M,
5575
+ FormLayout as F,
5576
+ MemoizedUIDInput as M,
5453
5577
  NotAllowedInput as N,
5454
5578
  useDynamicZone as a,
5455
5579
  useFieldHint as b,
5456
- createDefaultForm as c,
5457
- MemoizedUIDInput as d,
5458
- MemoizedWysiwyg as e,
5459
- MemoizedComponentInput as f,
5460
- MemoizedBlocksInput as g,
5461
- prepareTempKeys as p,
5462
- removeFieldsThatDontExistOnSchema as r,
5463
- transformDocument as t,
5580
+ MemoizedWysiwyg as c,
5581
+ MemoizedComponentInput as d,
5582
+ MemoizedBlocksInput as e,
5464
5583
  useLazyComponents as u
5465
5584
  };
5466
- //# sourceMappingURL=Field-dha5VnIQ.mjs.map
5585
+ //# sourceMappingURL=Input-CZ1YvjHR.mjs.map