@strapi/content-manager 5.53.0 → 5.55.0

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 (138) hide show
  1. package/dist/admin/components/ActionsDrawer.js +17 -6
  2. package/dist/admin/components/ActionsDrawer.js.map +1 -1
  3. package/dist/admin/components/ActionsDrawer.mjs +19 -8
  4. package/dist/admin/components/ActionsDrawer.mjs.map +1 -1
  5. package/dist/admin/components/LeftMenu.js +131 -52
  6. package/dist/admin/components/LeftMenu.js.map +1 -1
  7. package/dist/admin/components/LeftMenu.mjs +133 -54
  8. package/dist/admin/components/LeftMenu.mjs.map +1 -1
  9. package/dist/admin/history/components/VersionsList.js +37 -43
  10. package/dist/admin/history/components/VersionsList.js.map +1 -1
  11. package/dist/admin/history/components/VersionsList.mjs +37 -43
  12. package/dist/admin/history/components/VersionsList.mjs.map +1 -1
  13. package/dist/admin/hooks/useContentManagerInitData.js +3 -2
  14. package/dist/admin/hooks/useContentManagerInitData.js.map +1 -1
  15. package/dist/admin/hooks/useContentManagerInitData.mjs +3 -2
  16. package/dist/admin/hooks/useContentManagerInitData.mjs.map +1 -1
  17. package/dist/admin/hooks/useDocumentActions.js +3 -1
  18. package/dist/admin/hooks/useDocumentActions.js.map +1 -1
  19. package/dist/admin/hooks/useDocumentActions.mjs +4 -2
  20. package/dist/admin/hooks/useDocumentActions.mjs.map +1 -1
  21. package/dist/admin/layout.js +2 -4
  22. package/dist/admin/layout.js.map +1 -1
  23. package/dist/admin/layout.mjs +2 -4
  24. package/dist/admin/layout.mjs.map +1 -1
  25. package/dist/admin/modules/app.js +3 -1
  26. package/dist/admin/modules/app.js.map +1 -1
  27. package/dist/admin/modules/app.mjs +3 -1
  28. package/dist/admin/modules/app.mjs.map +1 -1
  29. package/dist/admin/pages/EditView/EditViewPage.js +15 -20
  30. package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
  31. package/dist/admin/pages/EditView/EditViewPage.mjs +15 -20
  32. package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
  33. package/dist/admin/pages/EditView/components/DocumentActions.js +2 -0
  34. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  35. package/dist/admin/pages/EditView/components/DocumentActions.mjs +2 -0
  36. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  37. package/dist/admin/pages/EditView/components/EditorToolbarObserver.js +74 -7
  38. package/dist/admin/pages/EditView/components/EditorToolbarObserver.js.map +1 -1
  39. package/dist/admin/pages/EditView/components/EditorToolbarObserver.mjs +74 -7
  40. package/dist/admin/pages/EditView/components/EditorToolbarObserver.mjs.map +1 -1
  41. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +7 -2
  42. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
  43. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +7 -2
  44. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
  45. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.js +59 -2
  46. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.js.map +1 -1
  47. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.mjs +60 -3
  48. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.mjs.map +1 -1
  49. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.js +4 -1
  50. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.js.map +1 -1
  51. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.mjs +4 -1
  52. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.mjs.map +1 -1
  53. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js +4 -1
  54. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js.map +1 -1
  55. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.mjs +4 -1
  56. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.mjs.map +1 -1
  57. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.js +2 -1
  58. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.js.map +1 -1
  59. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.mjs +2 -1
  60. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.mjs.map +1 -1
  61. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +58 -1
  62. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
  63. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +58 -2
  64. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
  65. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/WysiwygNav.js +25 -2
  66. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/WysiwygNav.js.map +1 -1
  67. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/WysiwygNav.mjs +5 -2
  68. package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/WysiwygNav.mjs.map +1 -1
  69. package/dist/admin/pages/EditView/components/InputRenderer.js +5 -1
  70. package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
  71. package/dist/admin/pages/EditView/components/InputRenderer.mjs +6 -2
  72. package/dist/admin/pages/EditView/components/InputRenderer.mjs.map +1 -1
  73. package/dist/admin/pages/ListView/ListViewPage.js +1 -0
  74. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  75. package/dist/admin/pages/ListView/ListViewPage.mjs +1 -0
  76. package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
  77. package/dist/admin/preview/components/InputPopover.js +64 -46
  78. package/dist/admin/preview/components/InputPopover.js.map +1 -1
  79. package/dist/admin/preview/components/InputPopover.mjs +66 -49
  80. package/dist/admin/preview/components/InputPopover.mjs.map +1 -1
  81. package/dist/admin/preview/hooks/usePreviewInputManager.js +23 -7
  82. package/dist/admin/preview/hooks/usePreviewInputManager.js.map +1 -1
  83. package/dist/admin/preview/hooks/usePreviewInputManager.mjs +25 -9
  84. package/dist/admin/preview/hooks/usePreviewInputManager.mjs.map +1 -1
  85. package/dist/admin/preview/pages/Preview.js +19 -0
  86. package/dist/admin/preview/pages/Preview.js.map +1 -1
  87. package/dist/admin/preview/pages/Preview.mjs +20 -1
  88. package/dist/admin/preview/pages/Preview.mjs.map +1 -1
  89. package/dist/admin/preview/utils/constants.js +9 -3
  90. package/dist/admin/preview/utils/constants.js.map +1 -1
  91. package/dist/admin/preview/utils/constants.mjs +9 -3
  92. package/dist/admin/preview/utils/constants.mjs.map +1 -1
  93. package/dist/admin/src/components/ActionsDrawer.d.ts +1 -0
  94. package/dist/admin/src/modules/app.d.ts +2 -0
  95. package/dist/admin/src/pages/EditView/components/EditorToolbarObserver.d.ts +2 -1
  96. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.d.ts +5 -1
  97. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.d.ts +5 -0
  98. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +5 -0
  99. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.d.ts +2 -1
  100. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/RelationModal.d.ts +14 -1
  101. package/dist/admin/src/preview/components/InputPopover.d.ts +2 -1
  102. package/dist/admin/src/preview/pages/Preview.d.ts +1 -0
  103. package/dist/admin/src/preview/utils/constants.d.ts +8 -1
  104. package/dist/admin/src/services/init.d.ts +1 -0
  105. package/dist/admin/src/utils/contentStructure.d.ts +59 -0
  106. package/dist/admin/utils/contentStructure.js +136 -0
  107. package/dist/admin/utils/contentStructure.js.map +1 -0
  108. package/dist/admin/utils/contentStructure.mjs +130 -0
  109. package/dist/admin/utils/contentStructure.mjs.map +1 -0
  110. package/dist/server/controllers/init.js +7 -2
  111. package/dist/server/controllers/init.js.map +1 -1
  112. package/dist/server/controllers/init.mjs +7 -2
  113. package/dist/server/controllers/init.mjs.map +1 -1
  114. package/dist/server/preview/controllers/previewScript.js +548 -22
  115. package/dist/server/services/content-structure.js +53 -0
  116. package/dist/server/services/content-structure.js.map +1 -0
  117. package/dist/server/services/content-structure.mjs +51 -0
  118. package/dist/server/services/content-structure.mjs.map +1 -0
  119. package/dist/server/services/index.js +2 -0
  120. package/dist/server/services/index.js.map +1 -1
  121. package/dist/server/services/index.mjs +2 -0
  122. package/dist/server/services/index.mjs.map +1 -1
  123. package/dist/server/src/controllers/index.d.ts +1 -1
  124. package/dist/server/src/controllers/init.d.ts +1 -1
  125. package/dist/server/src/controllers/init.d.ts.map +1 -1
  126. package/dist/server/src/index.d.ts +6 -1
  127. package/dist/server/src/index.d.ts.map +1 -1
  128. package/dist/server/src/services/content-structure.d.ts +8 -0
  129. package/dist/server/src/services/content-structure.d.ts.map +1 -0
  130. package/dist/server/src/services/index.d.ts +5 -0
  131. package/dist/server/src/services/index.d.ts.map +1 -1
  132. package/dist/server/src/utils/index.d.ts +2 -0
  133. package/dist/server/src/utils/index.d.ts.map +1 -1
  134. package/dist/server/utils/index.js.map +1 -1
  135. package/dist/server/utils/index.mjs.map +1 -1
  136. package/dist/shared/contracts/init.d.ts +2 -0
  137. package/dist/shared/contracts/init.d.ts.map +1 -1
  138. package/package.json +5 -5
@@ -33,9 +33,12 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
33
33
  const [InputPopoverProvider, useInputPopoverContext] = strapiAdmin.createContext('InputPopover');
34
34
  function useHasInputPopoverParent() {
35
35
  const context = useInputPopoverContext('useHasInputPopoverParent', ()=>true, false);
36
- // useContext will return undefined if the called is not wrapped in the provider
37
36
  return context !== undefined;
38
37
  }
38
+ function usePreviewPopoverBlockIndex() {
39
+ const blockIndex = useInputPopoverContext('usePreviewPopoverBlockIndex', (ctx)=>ctx.blockIndex, false);
40
+ return blockIndex ?? null;
41
+ }
39
42
  /* -------------------------------------------------------------------------------------------------
40
43
  * InputPopover
41
44
  * -----------------------------------------------------------------------------------------------*/ const InputPopover = ({ documentResponse })=>{
@@ -89,13 +92,21 @@ function useHasInputPopoverParent() {
89
92
  document
90
93
  });
91
94
  // We're able to handle the field, set it in context so the popover can pick it up
95
+ const resolvedBlockIndex = typeof event.data.payload.blockIndex === 'number' && event.data.payload.blockIndex >= 0 ? event.data.payload.blockIndex : null;
92
96
  setPopoverField({
93
97
  ...fieldMetaData,
94
98
  position: event.data.payload.position,
95
- attribute
99
+ attribute,
100
+ blockIndex: resolvedBlockIndex
96
101
  });
97
102
  } catch (error) {
98
103
  if (error instanceof fieldUtils.PreviewFieldError) {
104
+ // Relation fields can't be inline-edited. Silently ignore rather than showing
105
+ // a notification — the user may have double-clicked a relation element by
106
+ // accident, and showing an error is confusing when no action is needed.
107
+ if (error.messageKey === 'RELATIONS_NOT_HANDLED') {
108
+ return;
109
+ }
99
110
  const { type, message } = constants.PREVIEW_ERROR_MESSAGES[error.messageKey];
100
111
  toggleNotification({
101
112
  type,
@@ -118,6 +129,9 @@ function useHasInputPopoverParent() {
118
129
  })
119
130
  });
120
131
  }
132
+ if (event.data?.type === constants.INTERNAL_EVENTS.STRAPI_IFRAME_CLICK) {
133
+ setPopoverField(null);
134
+ }
121
135
  };
122
136
  window.addEventListener('message', handleMessage);
123
137
  return ()=>{
@@ -136,58 +150,62 @@ function useHasInputPopoverParent() {
136
150
  return null;
137
151
  }
138
152
  const iframeRect = iframeRef.current.getBoundingClientRect();
139
- return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
140
- children: [
141
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
142
- position: 'fixed',
143
- top: iframeRect.top + 'px',
144
- left: iframeRect.left + 'px',
145
- width: iframeRect.width + 'px',
146
- height: iframeRect.height + 'px',
147
- zIndex: 4,
148
- onClick: ()=>iframeRef.current?.focus()
149
- }),
150
- /*#__PURE__*/ jsxRuntime.jsx(InputPopoverProvider, {
151
- children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Popover.Root, {
152
- open: true,
153
- onOpenChange: (open)=>!open && setPopoverField(null),
154
- children: [
155
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Popover.Trigger, {
156
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
157
- position: "fixed",
158
- width: popoverField.position.width + 'px',
159
- height: popoverField.position.height + 'px',
160
- top: 0,
161
- left: 0,
162
- transform: `translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`
163
- })
164
- }),
165
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Popover.Content, {
166
- sideOffset: 4,
153
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
154
+ children: /*#__PURE__*/ jsxRuntime.jsx(InputPopoverProvider, {
155
+ blockIndex: popoverField.blockIndex,
156
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Popover.Root, {
157
+ open: true,
158
+ onOpenChange: (open)=>!open && setPopoverField(null),
159
+ children: [
160
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Popover.Trigger, {
161
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
162
+ position: "fixed",
163
+ width: popoverField.position.width + 'px',
164
+ height: popoverField.position.height + 'px',
165
+ top: 0,
166
+ left: 0,
167
+ transform: `translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`
168
+ })
169
+ }),
170
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Popover.Content, {
171
+ sideOffset: 4,
172
+ collisionPadding: {
173
+ top: 8,
174
+ bottom: 8,
175
+ left: 4,
176
+ right: 4
177
+ },
178
+ style: {
179
+ zIndex: 5
180
+ },
181
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
182
+ direction: "column",
183
+ alignItems: "stretch",
184
+ padding: 4,
185
+ width: "400px",
167
186
  style: {
168
- zIndex: 5
187
+ maxHeight: 'var(--radix-popover-content-available-height)',
188
+ overflow: 'hidden',
189
+ minHeight: 0
169
190
  },
170
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
171
- padding: 4,
172
- width: "400px",
173
- children: /*#__PURE__*/ jsxRuntime.jsx(InputRenderer.InputRenderer, {
174
- document: documentResponse,
175
- attribute: popoverField.attribute,
176
- // TODO: retrieve the proper label from the layout
177
- label: popoverField.path,
178
- name: popoverField.path,
179
- type: popoverField.attribute.type,
180
- visible: true
181
- })
191
+ children: /*#__PURE__*/ jsxRuntime.jsx(InputRenderer.InputRenderer, {
192
+ document: documentResponse,
193
+ attribute: popoverField.attribute,
194
+ // TODO: retrieve the proper label from the layout
195
+ label: popoverField.path,
196
+ name: popoverField.path,
197
+ type: popoverField.attribute.type,
198
+ visible: true
182
199
  })
183
200
  })
184
- ]
185
- })
201
+ })
202
+ ]
186
203
  })
187
- ]
204
+ })
188
205
  });
189
206
  };
190
207
 
191
208
  exports.InputPopover = InputPopover;
192
209
  exports.useHasInputPopoverParent = useHasInputPopoverParent;
210
+ exports.usePreviewPopoverBlockIndex = usePreviewPopoverBlockIndex;
193
211
  //# sourceMappingURL=InputPopover.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InputPopover.js","sources":["../../../../admin/src/preview/components/InputPopover.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { createContext, useNotification } from '@strapi/admin/strapi-admin';\nimport { Box, Popover } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { type UseDocument } from '../../hooks/useDocument';\nimport { InputRenderer } from '../../pages/EditView/components/InputRenderer';\nimport { usePreviewContext } from '../pages/Preview';\nimport { INTERNAL_EVENTS, PREVIEW_ERROR_MESSAGES } from '../utils/constants';\nimport {\n parseFieldMetaData,\n getAttributeSchemaFromPath,\n PreviewFieldError,\n} from '../utils/fieldUtils';\n\n/* -------------------------------------------------------------------------------------------------\n * Context utils\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * No need for actual data in the context. It's just to let children check if they're rendered\n * inside of a preview InputPopover without relying on prop drilling.\n */\ninterface InputPopoverContextValue {}\n\nconst [InputPopoverProvider, useInputPopoverContext] =\n createContext<InputPopoverContextValue>('InputPopover');\n\nfunction useHasInputPopoverParent() {\n const context = useInputPopoverContext('useHasInputPopoverParent', () => true, false);\n\n // useContext will return undefined if the called is not wrapped in the provider\n return context !== undefined;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * InputPopover\n * -----------------------------------------------------------------------------------------------*/\n\nconst InputPopover = ({ documentResponse }: { documentResponse: ReturnType<UseDocument> }) => {\n const iframeRef = usePreviewContext('InputPopover', (state) => state.iframeRef);\n const popoverField = usePreviewContext('InputPopover', (state) => state.popoverField);\n const setPopoverField = usePreviewContext('InputPopover', (state) => state.setPopoverField);\n const document = usePreviewContext('InputPopover', (state) => state.document);\n const schema = usePreviewContext('InputPopover', (state) => state.schema);\n const components = usePreviewContext('InputPopover', (state) => state.components);\n\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n\n React.useEffect(() => {\n /**\n * We receive window events sent from the user's preview via the injected script.\n * We listen to the ones here that target a specific field.\n */\n const handleMessage = (event: MessageEvent) => {\n // Only listen to events from the preview iframe\n if (iframeRef.current) {\n const previewOrigin = new URL(iframeRef.current?.src).origin;\n if (event.origin !== previewOrigin) {\n return;\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT) {\n const fieldMetaData = parseFieldMetaData(event.data.payload.path);\n\n if (!fieldMetaData) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.INCOMPLETE_STRAPI_SOURCE;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n /**\n * Ignore (for now) content that comes from separate API requests than the one for the\n * current document. This doesn't do anything about fields that may come from relations to\n * the current document however.\n */\n if (fieldMetaData.documentId !== document.documentId) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.DIFFERENT_DOCUMENT;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n try {\n const attribute = getAttributeSchemaFromPath({\n path: fieldMetaData.path,\n components,\n schema,\n document,\n });\n\n // We're able to handle the field, set it in context so the popover can pick it up\n setPopoverField({ ...fieldMetaData, position: event.data.payload.position, attribute });\n } catch (error) {\n if (error instanceof PreviewFieldError) {\n const { type, message } = PREVIEW_ERROR_MESSAGES[error.messageKey];\n toggleNotification({ type, message: formatMessage(message) });\n } else if (error instanceof Error) {\n toggleNotification({ type: 'danger', message: error.message });\n }\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_SINGLE_CLICK_HINT) {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: 'content-manager.preview.info.single-click-hint',\n defaultMessage: 'Double click to edit',\n }),\n });\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n return () => {\n window.removeEventListener('message', handleMessage);\n };\n }, [components, document, iframeRef, schema, setPopoverField, toggleNotification, formatMessage]);\n if (!popoverField || !iframeRef.current) {\n return null;\n }\n\n const iframeRect = iframeRef.current.getBoundingClientRect();\n\n return (\n <>\n {/**\n * Overlay an empty div on top of the iframe while the popover is open so it can\n * intercept clicks. Without it, we wouldn't be able to close the popover by clicking outside,\n * because the click would be detected by the iframe window, not by the admin.\n **/}\n <Box\n position={'fixed'}\n top={iframeRect.top + 'px'}\n left={iframeRect.left + 'px'}\n width={iframeRect.width + 'px'}\n height={iframeRect.height + 'px'}\n zIndex={4}\n onClick={() => iframeRef.current?.focus()}\n />\n <InputPopoverProvider>\n <Popover.Root open={true} onOpenChange={(open) => !open && setPopoverField(null)}>\n <Popover.Trigger>\n <Box\n position=\"fixed\"\n width={popoverField.position.width + 'px'}\n height={popoverField.position.height + 'px'}\n top={0}\n left={0}\n transform={`translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`}\n />\n </Popover.Trigger>\n <Popover.Content sideOffset={4} style={{ zIndex: 5 }}>\n <Box padding={4} width=\"400px\">\n {/* @ts-expect-error the types of `attribute` clash for some reason */}\n <InputRenderer\n document={documentResponse}\n attribute={popoverField.attribute}\n // TODO: retrieve the proper label from the layout\n label={popoverField.path}\n name={popoverField.path}\n type={popoverField.attribute.type}\n visible={true}\n />\n </Box>\n </Popover.Content>\n </Popover.Root>\n </InputPopoverProvider>\n </>\n );\n};\n\nexport { InputPopover, useHasInputPopoverParent };\n"],"names":["InputPopoverProvider","useInputPopoverContext","createContext","useHasInputPopoverParent","context","undefined","InputPopover","documentResponse","iframeRef","usePreviewContext","state","popoverField","setPopoverField","document","schema","components","toggleNotification","useNotification","formatMessage","useIntl","React","useEffect","handleMessage","event","current","previewOrigin","URL","src","origin","data","type","INTERNAL_EVENTS","STRAPI_FIELD_FOCUS_INTENT","fieldMetaData","parseFieldMetaData","payload","path","message","PREVIEW_ERROR_MESSAGES","INCOMPLETE_STRAPI_SOURCE","documentId","DIFFERENT_DOCUMENT","attribute","getAttributeSchemaFromPath","position","error","PreviewFieldError","messageKey","Error","STRAPI_FIELD_SINGLE_CLICK_HINT","id","defaultMessage","window","addEventListener","removeEventListener","iframeRect","getBoundingClientRect","_jsxs","_Fragment","_jsx","Box","top","left","width","height","zIndex","onClick","focus","Popover","Root","open","onOpenChange","Trigger","transform","Content","sideOffset","style","padding","InputRenderer","label","name","visible"],"mappings":"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"}
1
+ {"version":3,"file":"InputPopover.js","sources":["../../../../admin/src/preview/components/InputPopover.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { createContext, useNotification } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, Popover } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { type UseDocument } from '../../hooks/useDocument';\nimport { InputRenderer } from '../../pages/EditView/components/InputRenderer';\nimport { usePreviewContext } from '../pages/Preview';\nimport { INTERNAL_EVENTS, PREVIEW_ERROR_MESSAGES } from '../utils/constants';\nimport {\n parseFieldMetaData,\n getAttributeSchemaFromPath,\n PreviewFieldError,\n} from '../utils/fieldUtils';\n\n/* -------------------------------------------------------------------------------------------------\n * Context utils\n * -----------------------------------------------------------------------------------------------*/\n\ninterface InputPopoverContextValue {\n blockIndex: number | null;\n}\n\nconst [InputPopoverProvider, useInputPopoverContext] =\n createContext<InputPopoverContextValue>('InputPopover');\n\nfunction useHasInputPopoverParent() {\n const context = useInputPopoverContext('useHasInputPopoverParent', () => true, false);\n return context !== undefined;\n}\n\nfunction usePreviewPopoverBlockIndex() {\n const blockIndex = useInputPopoverContext(\n 'usePreviewPopoverBlockIndex',\n (ctx) => ctx.blockIndex,\n false\n );\n return blockIndex ?? null;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * InputPopover\n * -----------------------------------------------------------------------------------------------*/\n\nconst InputPopover = ({ documentResponse }: { documentResponse: ReturnType<UseDocument> }) => {\n const iframeRef = usePreviewContext('InputPopover', (state) => state.iframeRef);\n const popoverField = usePreviewContext('InputPopover', (state) => state.popoverField);\n const setPopoverField = usePreviewContext('InputPopover', (state) => state.setPopoverField);\n const document = usePreviewContext('InputPopover', (state) => state.document);\n const schema = usePreviewContext('InputPopover', (state) => state.schema);\n const components = usePreviewContext('InputPopover', (state) => state.components);\n\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n\n React.useEffect(() => {\n /**\n * We receive window events sent from the user's preview via the injected script.\n * We listen to the ones here that target a specific field.\n */\n const handleMessage = (event: MessageEvent) => {\n // Only listen to events from the preview iframe\n if (iframeRef.current) {\n const previewOrigin = new URL(iframeRef.current?.src).origin;\n if (event.origin !== previewOrigin) {\n return;\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT) {\n const fieldMetaData = parseFieldMetaData(event.data.payload.path);\n\n if (!fieldMetaData) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.INCOMPLETE_STRAPI_SOURCE;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n /**\n * Ignore (for now) content that comes from separate API requests than the one for the\n * current document. This doesn't do anything about fields that may come from relations to\n * the current document however.\n */\n if (fieldMetaData.documentId !== document.documentId) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.DIFFERENT_DOCUMENT;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n try {\n const attribute = getAttributeSchemaFromPath({\n path: fieldMetaData.path,\n components,\n schema,\n document,\n });\n\n // We're able to handle the field, set it in context so the popover can pick it up\n const resolvedBlockIndex =\n typeof event.data.payload.blockIndex === 'number' && event.data.payload.blockIndex >= 0\n ? event.data.payload.blockIndex\n : null;\n setPopoverField({\n ...fieldMetaData,\n position: event.data.payload.position,\n attribute,\n blockIndex: resolvedBlockIndex,\n });\n } catch (error) {\n if (error instanceof PreviewFieldError) {\n // Relation fields can't be inline-edited. Silently ignore rather than showing\n // a notification — the user may have double-clicked a relation element by\n // accident, and showing an error is confusing when no action is needed.\n if (error.messageKey === 'RELATIONS_NOT_HANDLED') {\n return;\n }\n const { type, message } = PREVIEW_ERROR_MESSAGES[error.messageKey];\n toggleNotification({ type, message: formatMessage(message) });\n } else if (error instanceof Error) {\n toggleNotification({ type: 'danger', message: error.message });\n }\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_SINGLE_CLICK_HINT) {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: 'content-manager.preview.info.single-click-hint',\n defaultMessage: 'Double click to edit',\n }),\n });\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_IFRAME_CLICK) {\n setPopoverField(null);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n return () => {\n window.removeEventListener('message', handleMessage);\n };\n }, [components, document, iframeRef, schema, setPopoverField, toggleNotification, formatMessage]);\n if (!popoverField || !iframeRef.current) {\n return null;\n }\n\n const iframeRect = iframeRef.current.getBoundingClientRect();\n\n return (\n <>\n <InputPopoverProvider blockIndex={popoverField.blockIndex}>\n <Popover.Root open={true} onOpenChange={(open) => !open && setPopoverField(null)}>\n <Popover.Trigger>\n <Box\n position=\"fixed\"\n width={popoverField.position.width + 'px'}\n height={popoverField.position.height + 'px'}\n top={0}\n left={0}\n transform={`translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`}\n />\n </Popover.Trigger>\n <Popover.Content\n sideOffset={4}\n collisionPadding={{ top: 8, bottom: 8, left: 4, right: 4 }}\n style={{ zIndex: 5 }}\n >\n <Flex\n direction=\"column\"\n alignItems=\"stretch\"\n padding={4}\n width=\"400px\"\n style={{\n maxHeight: 'var(--radix-popover-content-available-height)',\n overflow: 'hidden',\n minHeight: 0,\n }}\n >\n {/* @ts-expect-error the types of `attribute` clash for some reason */}\n <InputRenderer\n document={documentResponse}\n attribute={popoverField.attribute}\n // TODO: retrieve the proper label from the layout\n label={popoverField.path}\n name={popoverField.path}\n type={popoverField.attribute.type}\n visible={true}\n />\n </Flex>\n </Popover.Content>\n </Popover.Root>\n </InputPopoverProvider>\n </>\n );\n};\n\nexport { InputPopover, useHasInputPopoverParent, usePreviewPopoverBlockIndex };\n"],"names":["InputPopoverProvider","useInputPopoverContext","createContext","useHasInputPopoverParent","context","undefined","usePreviewPopoverBlockIndex","blockIndex","ctx","InputPopover","documentResponse","iframeRef","usePreviewContext","state","popoverField","setPopoverField","document","schema","components","toggleNotification","useNotification","formatMessage","useIntl","React","useEffect","handleMessage","event","current","previewOrigin","URL","src","origin","data","type","INTERNAL_EVENTS","STRAPI_FIELD_FOCUS_INTENT","fieldMetaData","parseFieldMetaData","payload","path","message","PREVIEW_ERROR_MESSAGES","INCOMPLETE_STRAPI_SOURCE","documentId","DIFFERENT_DOCUMENT","attribute","getAttributeSchemaFromPath","resolvedBlockIndex","position","error","PreviewFieldError","messageKey","Error","STRAPI_FIELD_SINGLE_CLICK_HINT","id","defaultMessage","STRAPI_IFRAME_CLICK","window","addEventListener","removeEventListener","iframeRect","getBoundingClientRect","_jsx","_Fragment","_jsxs","Popover","Root","open","onOpenChange","Trigger","Box","width","height","top","left","transform","Content","sideOffset","collisionPadding","bottom","right","style","zIndex","Flex","direction","alignItems","padding","maxHeight","overflow","minHeight","InputRenderer","label","name","visible"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
1
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { createContext, useNotification } from '@strapi/admin/strapi-admin';
4
- import { Box, Popover } from '@strapi/design-system';
4
+ import { Popover, Box, Flex } from '@strapi/design-system';
5
5
  import { useIntl } from 'react-intl';
6
6
  import { InputRenderer as MemoizedInputRenderer } from '../../pages/EditView/components/InputRenderer.mjs';
7
7
  import { usePreviewContext } from '../pages/Preview.mjs';
@@ -11,9 +11,12 @@ import { parseFieldMetaData, getAttributeSchemaFromPath, PreviewFieldError } fro
11
11
  const [InputPopoverProvider, useInputPopoverContext] = createContext('InputPopover');
12
12
  function useHasInputPopoverParent() {
13
13
  const context = useInputPopoverContext('useHasInputPopoverParent', ()=>true, false);
14
- // useContext will return undefined if the called is not wrapped in the provider
15
14
  return context !== undefined;
16
15
  }
16
+ function usePreviewPopoverBlockIndex() {
17
+ const blockIndex = useInputPopoverContext('usePreviewPopoverBlockIndex', (ctx)=>ctx.blockIndex, false);
18
+ return blockIndex ?? null;
19
+ }
17
20
  /* -------------------------------------------------------------------------------------------------
18
21
  * InputPopover
19
22
  * -----------------------------------------------------------------------------------------------*/ const InputPopover = ({ documentResponse })=>{
@@ -67,13 +70,21 @@ function useHasInputPopoverParent() {
67
70
  document
68
71
  });
69
72
  // We're able to handle the field, set it in context so the popover can pick it up
73
+ const resolvedBlockIndex = typeof event.data.payload.blockIndex === 'number' && event.data.payload.blockIndex >= 0 ? event.data.payload.blockIndex : null;
70
74
  setPopoverField({
71
75
  ...fieldMetaData,
72
76
  position: event.data.payload.position,
73
- attribute
77
+ attribute,
78
+ blockIndex: resolvedBlockIndex
74
79
  });
75
80
  } catch (error) {
76
81
  if (error instanceof PreviewFieldError) {
82
+ // Relation fields can't be inline-edited. Silently ignore rather than showing
83
+ // a notification — the user may have double-clicked a relation element by
84
+ // accident, and showing an error is confusing when no action is needed.
85
+ if (error.messageKey === 'RELATIONS_NOT_HANDLED') {
86
+ return;
87
+ }
77
88
  const { type, message } = PREVIEW_ERROR_MESSAGES[error.messageKey];
78
89
  toggleNotification({
79
90
  type,
@@ -96,6 +107,9 @@ function useHasInputPopoverParent() {
96
107
  })
97
108
  });
98
109
  }
110
+ if (event.data?.type === INTERNAL_EVENTS.STRAPI_IFRAME_CLICK) {
111
+ setPopoverField(null);
112
+ }
99
113
  };
100
114
  window.addEventListener('message', handleMessage);
101
115
  return ()=>{
@@ -114,57 +128,60 @@ function useHasInputPopoverParent() {
114
128
  return null;
115
129
  }
116
130
  const iframeRect = iframeRef.current.getBoundingClientRect();
117
- return /*#__PURE__*/ jsxs(Fragment, {
118
- children: [
119
- /*#__PURE__*/ jsx(Box, {
120
- position: 'fixed',
121
- top: iframeRect.top + 'px',
122
- left: iframeRect.left + 'px',
123
- width: iframeRect.width + 'px',
124
- height: iframeRect.height + 'px',
125
- zIndex: 4,
126
- onClick: ()=>iframeRef.current?.focus()
127
- }),
128
- /*#__PURE__*/ jsx(InputPopoverProvider, {
129
- children: /*#__PURE__*/ jsxs(Popover.Root, {
130
- open: true,
131
- onOpenChange: (open)=>!open && setPopoverField(null),
132
- children: [
133
- /*#__PURE__*/ jsx(Popover.Trigger, {
134
- children: /*#__PURE__*/ jsx(Box, {
135
- position: "fixed",
136
- width: popoverField.position.width + 'px',
137
- height: popoverField.position.height + 'px',
138
- top: 0,
139
- left: 0,
140
- transform: `translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`
141
- })
142
- }),
143
- /*#__PURE__*/ jsx(Popover.Content, {
144
- sideOffset: 4,
131
+ return /*#__PURE__*/ jsx(Fragment, {
132
+ children: /*#__PURE__*/ jsx(InputPopoverProvider, {
133
+ blockIndex: popoverField.blockIndex,
134
+ children: /*#__PURE__*/ jsxs(Popover.Root, {
135
+ open: true,
136
+ onOpenChange: (open)=>!open && setPopoverField(null),
137
+ children: [
138
+ /*#__PURE__*/ jsx(Popover.Trigger, {
139
+ children: /*#__PURE__*/ jsx(Box, {
140
+ position: "fixed",
141
+ width: popoverField.position.width + 'px',
142
+ height: popoverField.position.height + 'px',
143
+ top: 0,
144
+ left: 0,
145
+ transform: `translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`
146
+ })
147
+ }),
148
+ /*#__PURE__*/ jsx(Popover.Content, {
149
+ sideOffset: 4,
150
+ collisionPadding: {
151
+ top: 8,
152
+ bottom: 8,
153
+ left: 4,
154
+ right: 4
155
+ },
156
+ style: {
157
+ zIndex: 5
158
+ },
159
+ children: /*#__PURE__*/ jsx(Flex, {
160
+ direction: "column",
161
+ alignItems: "stretch",
162
+ padding: 4,
163
+ width: "400px",
145
164
  style: {
146
- zIndex: 5
165
+ maxHeight: 'var(--radix-popover-content-available-height)',
166
+ overflow: 'hidden',
167
+ minHeight: 0
147
168
  },
148
- children: /*#__PURE__*/ jsx(Box, {
149
- padding: 4,
150
- width: "400px",
151
- children: /*#__PURE__*/ jsx(MemoizedInputRenderer, {
152
- document: documentResponse,
153
- attribute: popoverField.attribute,
154
- // TODO: retrieve the proper label from the layout
155
- label: popoverField.path,
156
- name: popoverField.path,
157
- type: popoverField.attribute.type,
158
- visible: true
159
- })
169
+ children: /*#__PURE__*/ jsx(MemoizedInputRenderer, {
170
+ document: documentResponse,
171
+ attribute: popoverField.attribute,
172
+ // TODO: retrieve the proper label from the layout
173
+ label: popoverField.path,
174
+ name: popoverField.path,
175
+ type: popoverField.attribute.type,
176
+ visible: true
160
177
  })
161
178
  })
162
- ]
163
- })
179
+ })
180
+ ]
164
181
  })
165
- ]
182
+ })
166
183
  });
167
184
  };
168
185
 
169
- export { InputPopover, useHasInputPopoverParent };
186
+ export { InputPopover, useHasInputPopoverParent, usePreviewPopoverBlockIndex };
170
187
  //# sourceMappingURL=InputPopover.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"InputPopover.mjs","sources":["../../../../admin/src/preview/components/InputPopover.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { createContext, useNotification } from '@strapi/admin/strapi-admin';\nimport { Box, Popover } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { type UseDocument } from '../../hooks/useDocument';\nimport { InputRenderer } from '../../pages/EditView/components/InputRenderer';\nimport { usePreviewContext } from '../pages/Preview';\nimport { INTERNAL_EVENTS, PREVIEW_ERROR_MESSAGES } from '../utils/constants';\nimport {\n parseFieldMetaData,\n getAttributeSchemaFromPath,\n PreviewFieldError,\n} from '../utils/fieldUtils';\n\n/* -------------------------------------------------------------------------------------------------\n * Context utils\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * No need for actual data in the context. It's just to let children check if they're rendered\n * inside of a preview InputPopover without relying on prop drilling.\n */\ninterface InputPopoverContextValue {}\n\nconst [InputPopoverProvider, useInputPopoverContext] =\n createContext<InputPopoverContextValue>('InputPopover');\n\nfunction useHasInputPopoverParent() {\n const context = useInputPopoverContext('useHasInputPopoverParent', () => true, false);\n\n // useContext will return undefined if the called is not wrapped in the provider\n return context !== undefined;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * InputPopover\n * -----------------------------------------------------------------------------------------------*/\n\nconst InputPopover = ({ documentResponse }: { documentResponse: ReturnType<UseDocument> }) => {\n const iframeRef = usePreviewContext('InputPopover', (state) => state.iframeRef);\n const popoverField = usePreviewContext('InputPopover', (state) => state.popoverField);\n const setPopoverField = usePreviewContext('InputPopover', (state) => state.setPopoverField);\n const document = usePreviewContext('InputPopover', (state) => state.document);\n const schema = usePreviewContext('InputPopover', (state) => state.schema);\n const components = usePreviewContext('InputPopover', (state) => state.components);\n\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n\n React.useEffect(() => {\n /**\n * We receive window events sent from the user's preview via the injected script.\n * We listen to the ones here that target a specific field.\n */\n const handleMessage = (event: MessageEvent) => {\n // Only listen to events from the preview iframe\n if (iframeRef.current) {\n const previewOrigin = new URL(iframeRef.current?.src).origin;\n if (event.origin !== previewOrigin) {\n return;\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT) {\n const fieldMetaData = parseFieldMetaData(event.data.payload.path);\n\n if (!fieldMetaData) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.INCOMPLETE_STRAPI_SOURCE;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n /**\n * Ignore (for now) content that comes from separate API requests than the one for the\n * current document. This doesn't do anything about fields that may come from relations to\n * the current document however.\n */\n if (fieldMetaData.documentId !== document.documentId) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.DIFFERENT_DOCUMENT;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n try {\n const attribute = getAttributeSchemaFromPath({\n path: fieldMetaData.path,\n components,\n schema,\n document,\n });\n\n // We're able to handle the field, set it in context so the popover can pick it up\n setPopoverField({ ...fieldMetaData, position: event.data.payload.position, attribute });\n } catch (error) {\n if (error instanceof PreviewFieldError) {\n const { type, message } = PREVIEW_ERROR_MESSAGES[error.messageKey];\n toggleNotification({ type, message: formatMessage(message) });\n } else if (error instanceof Error) {\n toggleNotification({ type: 'danger', message: error.message });\n }\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_SINGLE_CLICK_HINT) {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: 'content-manager.preview.info.single-click-hint',\n defaultMessage: 'Double click to edit',\n }),\n });\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n return () => {\n window.removeEventListener('message', handleMessage);\n };\n }, [components, document, iframeRef, schema, setPopoverField, toggleNotification, formatMessage]);\n if (!popoverField || !iframeRef.current) {\n return null;\n }\n\n const iframeRect = iframeRef.current.getBoundingClientRect();\n\n return (\n <>\n {/**\n * Overlay an empty div on top of the iframe while the popover is open so it can\n * intercept clicks. Without it, we wouldn't be able to close the popover by clicking outside,\n * because the click would be detected by the iframe window, not by the admin.\n **/}\n <Box\n position={'fixed'}\n top={iframeRect.top + 'px'}\n left={iframeRect.left + 'px'}\n width={iframeRect.width + 'px'}\n height={iframeRect.height + 'px'}\n zIndex={4}\n onClick={() => iframeRef.current?.focus()}\n />\n <InputPopoverProvider>\n <Popover.Root open={true} onOpenChange={(open) => !open && setPopoverField(null)}>\n <Popover.Trigger>\n <Box\n position=\"fixed\"\n width={popoverField.position.width + 'px'}\n height={popoverField.position.height + 'px'}\n top={0}\n left={0}\n transform={`translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`}\n />\n </Popover.Trigger>\n <Popover.Content sideOffset={4} style={{ zIndex: 5 }}>\n <Box padding={4} width=\"400px\">\n {/* @ts-expect-error the types of `attribute` clash for some reason */}\n <InputRenderer\n document={documentResponse}\n attribute={popoverField.attribute}\n // TODO: retrieve the proper label from the layout\n label={popoverField.path}\n name={popoverField.path}\n type={popoverField.attribute.type}\n visible={true}\n />\n </Box>\n </Popover.Content>\n </Popover.Root>\n </InputPopoverProvider>\n </>\n );\n};\n\nexport { InputPopover, useHasInputPopoverParent };\n"],"names":["InputPopoverProvider","useInputPopoverContext","createContext","useHasInputPopoverParent","context","undefined","InputPopover","documentResponse","iframeRef","usePreviewContext","state","popoverField","setPopoverField","document","schema","components","toggleNotification","useNotification","formatMessage","useIntl","React","useEffect","handleMessage","event","current","previewOrigin","URL","src","origin","data","type","INTERNAL_EVENTS","STRAPI_FIELD_FOCUS_INTENT","fieldMetaData","parseFieldMetaData","payload","path","message","PREVIEW_ERROR_MESSAGES","INCOMPLETE_STRAPI_SOURCE","documentId","DIFFERENT_DOCUMENT","attribute","getAttributeSchemaFromPath","position","error","PreviewFieldError","messageKey","Error","STRAPI_FIELD_SINGLE_CLICK_HINT","id","defaultMessage","window","addEventListener","removeEventListener","iframeRect","getBoundingClientRect","_jsxs","_Fragment","_jsx","Box","top","left","width","height","zIndex","onClick","focus","Popover","Root","open","onOpenChange","Trigger","transform","Content","sideOffset","style","padding","InputRenderer","label","name","visible"],"mappings":";;;;;;;;;;AA0BA,MAAM,CAACA,oBAAAA,EAAsBC,sBAAAA,CAAuB,GAClDC,aAAAA,CAAwC,cAAA,CAAA;AAE1C,SAASC,wBAAAA,GAAAA;AACP,IAAA,MAAMC,OAAAA,GAAUH,sBAAAA,CAAuB,0BAAA,EAA4B,IAAM,IAAA,EAAM,KAAA,CAAA;;AAG/E,IAAA,OAAOG,OAAAA,KAAYC,SAAAA;AACrB;AAEA;;AAEkG,qGAElG,MAAMC,YAAAA,GAAe,CAAC,EAAEC,gBAAgB,EAAiD,GAAA;AACvF,IAAA,MAAMC,YAAYC,iBAAAA,CAAkB,cAAA,EAAgB,CAACC,KAAAA,GAAUA,MAAMF,SAAS,CAAA;AAC9E,IAAA,MAAMG,eAAeF,iBAAAA,CAAkB,cAAA,EAAgB,CAACC,KAAAA,GAAUA,MAAMC,YAAY,CAAA;AACpF,IAAA,MAAMC,kBAAkBH,iBAAAA,CAAkB,cAAA,EAAgB,CAACC,KAAAA,GAAUA,MAAME,eAAe,CAAA;AAC1F,IAAA,MAAMC,WAAWJ,iBAAAA,CAAkB,cAAA,EAAgB,CAACC,KAAAA,GAAUA,MAAMG,QAAQ,CAAA;AAC5E,IAAA,MAAMC,SAASL,iBAAAA,CAAkB,cAAA,EAAgB,CAACC,KAAAA,GAAUA,MAAMI,MAAM,CAAA;AACxE,IAAA,MAAMC,aAAaN,iBAAAA,CAAkB,cAAA,EAAgB,CAACC,KAAAA,GAAUA,MAAMK,UAAU,CAAA;IAEhF,MAAM,EAAEC,kBAAkB,EAAE,GAAGC,eAAAA,EAAAA;IAC/B,MAAM,EAAEC,aAAa,EAAE,GAAGC,OAAAA,EAAAA;AAE1BC,IAAAA,KAAAA,CAAMC,SAAS,CAAC,IAAA;AACd;;;QAIA,MAAMC,gBAAgB,CAACC,KAAAA,GAAAA;;YAErB,IAAIf,SAAAA,CAAUgB,OAAO,EAAE;AACrB,gBAAA,MAAMC,gBAAgB,IAAIC,GAAAA,CAAIlB,UAAUgB,OAAO,EAAEG,KAAKC,MAAM;gBAC5D,IAAIL,KAAAA,CAAMK,MAAM,KAAKH,aAAAA,EAAe;AAClC,oBAAA;AACF,gBAAA;AACF,YAAA;AAEA,YAAA,IAAIF,MAAMM,IAAI,EAAEC,IAAAA,KAASC,eAAAA,CAAgBC,yBAAyB,EAAE;AAClE,gBAAA,MAAMC,gBAAgBC,kBAAAA,CAAmBX,KAAAA,CAAMM,IAAI,CAACM,OAAO,CAACC,IAAI,CAAA;AAEhE,gBAAA,IAAI,CAACH,aAAAA,EAAe;AAClB,oBAAA,MAAM,EAAEH,IAAI,EAAEO,OAAO,EAAE,GAAGC,uBAAuBC,wBAAwB;oBACzEvB,kBAAAA,CAAmB;AAAEc,wBAAAA,IAAAA;AAAMO,wBAAAA,OAAAA,EAASnB,aAAAA,CAAcmB,OAAAA;AAAS,qBAAA,CAAA;AAC3D,oBAAA;AACF,gBAAA;AAEA;;;;AAIC,YACD,IAAIJ,aAAAA,CAAcO,UAAU,KAAK3B,QAAAA,CAAS2B,UAAU,EAAE;AACpD,oBAAA,MAAM,EAAEV,IAAI,EAAEO,OAAO,EAAE,GAAGC,uBAAuBG,kBAAkB;oBACnEzB,kBAAAA,CAAmB;AAAEc,wBAAAA,IAAAA;AAAMO,wBAAAA,OAAAA,EAASnB,aAAAA,CAAcmB,OAAAA;AAAS,qBAAA,CAAA;AAC3D,oBAAA;AACF,gBAAA;gBAEA,IAAI;AACF,oBAAA,MAAMK,YAAYC,0BAAAA,CAA2B;AAC3CP,wBAAAA,IAAAA,EAAMH,cAAcG,IAAI;AACxBrB,wBAAAA,UAAAA;AACAD,wBAAAA,MAAAA;AACAD,wBAAAA;AACF,qBAAA,CAAA;;oBAGAD,eAAAA,CAAgB;AAAE,wBAAA,GAAGqB,aAAa;AAAEW,wBAAAA,QAAAA,EAAUrB,KAAAA,CAAMM,IAAI,CAACM,OAAO,CAACS,QAAQ;AAAEF,wBAAAA;AAAU,qBAAA,CAAA;AACvF,gBAAA,CAAA,CAAE,OAAOG,KAAAA,EAAO;AACd,oBAAA,IAAIA,iBAAiBC,iBAAAA,EAAmB;wBACtC,MAAM,EAAEhB,IAAI,EAAEO,OAAO,EAAE,GAAGC,sBAAsB,CAACO,KAAAA,CAAME,UAAU,CAAC;wBAClE/B,kBAAAA,CAAmB;AAAEc,4BAAAA,IAAAA;AAAMO,4BAAAA,OAAAA,EAASnB,aAAAA,CAAcmB,OAAAA;AAAS,yBAAA,CAAA;oBAC7D,CAAA,MAAO,IAAIQ,iBAAiBG,KAAAA,EAAO;wBACjChC,kBAAAA,CAAmB;4BAAEc,IAAAA,EAAM,QAAA;AAAUO,4BAAAA,OAAAA,EAASQ,MAAMR;AAAQ,yBAAA,CAAA;AAC9D,oBAAA;AACF,gBAAA;AACF,YAAA;AAEA,YAAA,IAAId,MAAMM,IAAI,EAAEC,IAAAA,KAASC,eAAAA,CAAgBkB,8BAA8B,EAAE;gBACvEjC,kBAAAA,CAAmB;oBACjBc,IAAAA,EAAM,MAAA;AACNO,oBAAAA,OAAAA,EAASnB,aAAAA,CAAc;wBACrBgC,EAAAA,EAAI,gDAAA;wBACJC,cAAAA,EAAgB;AAClB,qBAAA;AACF,iBAAA,CAAA;AACF,YAAA;AACF,QAAA,CAAA;QAEAC,MAAAA,CAAOC,gBAAgB,CAAC,SAAA,EAAW/B,aAAAA,CAAAA;QAEnC,OAAO,IAAA;YACL8B,MAAAA,CAAOE,mBAAmB,CAAC,SAAA,EAAWhC,aAAAA,CAAAA;AACxC,QAAA,CAAA;IACF,CAAA,EAAG;AAACP,QAAAA,UAAAA;AAAYF,QAAAA,QAAAA;AAAUL,QAAAA,SAAAA;AAAWM,QAAAA,MAAAA;AAAQF,QAAAA,eAAAA;AAAiBI,QAAAA,kBAAAA;AAAoBE,QAAAA;AAAc,KAAA,CAAA;AAChG,IAAA,IAAI,CAACP,YAAAA,IAAgB,CAACH,SAAAA,CAAUgB,OAAO,EAAE;QACvC,OAAO,IAAA;AACT,IAAA;AAEA,IAAA,MAAM+B,UAAAA,GAAa/C,SAAAA,CAAUgB,OAAO,CAACgC,qBAAqB,EAAA;IAE1D,qBACEC,IAAA,CAAAC,QAAA,EAAA;;0BAMEC,GAAA,CAACC,GAAAA,EAAAA;gBACChB,QAAAA,EAAU,OAAA;gBACViB,GAAAA,EAAKN,UAAAA,CAAWM,GAAG,GAAG,IAAA;gBACtBC,IAAAA,EAAMP,UAAAA,CAAWO,IAAI,GAAG,IAAA;gBACxBC,KAAAA,EAAOR,UAAAA,CAAWQ,KAAK,GAAG,IAAA;gBAC1BC,MAAAA,EAAQT,UAAAA,CAAWS,MAAM,GAAG,IAAA;gBAC5BC,MAAAA,EAAQ,CAAA;gBACRC,OAAAA,EAAS,IAAM1D,SAAAA,CAAUgB,OAAO,EAAE2C,KAAAA;;0BAEpCR,GAAA,CAAC3D,oBAAAA,EAAAA;wCACCyD,IAAA,CAACW,QAAQC,IAAI,EAAA;oBAACC,IAAAA,EAAM,IAAA;AAAMC,oBAAAA,YAAAA,EAAc,CAACD,IAAAA,GAAS,CAACA,IAAAA,IAAQ1D,eAAAA,CAAgB,IAAA,CAAA;;AACzE,sCAAA+C,GAAA,CAACS,QAAQI,OAAO,EAAA;AACd,4BAAA,QAAA,gBAAAb,GAAA,CAACC,GAAAA,EAAAA;gCACChB,QAAAA,EAAS,OAAA;AACTmB,gCAAAA,KAAAA,EAAOpD,YAAAA,CAAaiC,QAAQ,CAACmB,KAAK,GAAG,IAAA;AACrCC,gCAAAA,MAAAA,EAAQrD,YAAAA,CAAaiC,QAAQ,CAACoB,MAAM,GAAG,IAAA;gCACvCH,GAAAA,EAAK,CAAA;gCACLC,IAAAA,EAAM,CAAA;gCACNW,SAAAA,EAAW,CAAC,UAAU,EAAElB,UAAAA,CAAWO,IAAI,GAAGnD,YAAAA,CAAaiC,QAAQ,CAACkB,IAAI,CAAC,IAAI,EAAEP,UAAAA,CAAWM,GAAG,GAAGlD,YAAAA,CAAaiC,QAAQ,CAACiB,GAAG,CAAC,GAAG;;;AAG7H,sCAAAF,GAAA,CAACS,QAAQM,OAAO,EAAA;4BAACC,UAAAA,EAAY,CAAA;4BAAGC,KAAAA,EAAO;gCAAEX,MAAAA,EAAQ;AAAE,6BAAA;AACjD,4BAAA,QAAA,gBAAAN,GAAA,CAACC,GAAAA,EAAAA;gCAAIiB,OAAAA,EAAS,CAAA;gCAAGd,KAAAA,EAAM,OAAA;AAErB,gCAAA,QAAA,gBAAAJ,GAAA,CAACmB,qBAAAA,EAAAA;oCACCjE,QAAAA,EAAUN,gBAAAA;AACVmC,oCAAAA,SAAAA,EAAW/B,aAAa+B,SAAS;;AAEjCqC,oCAAAA,KAAAA,EAAOpE,aAAayB,IAAI;AACxB4C,oCAAAA,IAAAA,EAAMrE,aAAayB,IAAI;oCACvBN,IAAAA,EAAMnB,YAAAA,CAAa+B,SAAS,CAACZ,IAAI;oCACjCmD,OAAAA,EAAS;;;;;;;;;AAQzB;;;;"}
1
+ {"version":3,"file":"InputPopover.mjs","sources":["../../../../admin/src/preview/components/InputPopover.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { createContext, useNotification } from '@strapi/admin/strapi-admin';\nimport { Box, Flex, Popover } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nimport { type UseDocument } from '../../hooks/useDocument';\nimport { InputRenderer } from '../../pages/EditView/components/InputRenderer';\nimport { usePreviewContext } from '../pages/Preview';\nimport { INTERNAL_EVENTS, PREVIEW_ERROR_MESSAGES } from '../utils/constants';\nimport {\n parseFieldMetaData,\n getAttributeSchemaFromPath,\n PreviewFieldError,\n} from '../utils/fieldUtils';\n\n/* -------------------------------------------------------------------------------------------------\n * Context utils\n * -----------------------------------------------------------------------------------------------*/\n\ninterface InputPopoverContextValue {\n blockIndex: number | null;\n}\n\nconst [InputPopoverProvider, useInputPopoverContext] =\n createContext<InputPopoverContextValue>('InputPopover');\n\nfunction useHasInputPopoverParent() {\n const context = useInputPopoverContext('useHasInputPopoverParent', () => true, false);\n return context !== undefined;\n}\n\nfunction usePreviewPopoverBlockIndex() {\n const blockIndex = useInputPopoverContext(\n 'usePreviewPopoverBlockIndex',\n (ctx) => ctx.blockIndex,\n false\n );\n return blockIndex ?? null;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * InputPopover\n * -----------------------------------------------------------------------------------------------*/\n\nconst InputPopover = ({ documentResponse }: { documentResponse: ReturnType<UseDocument> }) => {\n const iframeRef = usePreviewContext('InputPopover', (state) => state.iframeRef);\n const popoverField = usePreviewContext('InputPopover', (state) => state.popoverField);\n const setPopoverField = usePreviewContext('InputPopover', (state) => state.setPopoverField);\n const document = usePreviewContext('InputPopover', (state) => state.document);\n const schema = usePreviewContext('InputPopover', (state) => state.schema);\n const components = usePreviewContext('InputPopover', (state) => state.components);\n\n const { toggleNotification } = useNotification();\n const { formatMessage } = useIntl();\n\n React.useEffect(() => {\n /**\n * We receive window events sent from the user's preview via the injected script.\n * We listen to the ones here that target a specific field.\n */\n const handleMessage = (event: MessageEvent) => {\n // Only listen to events from the preview iframe\n if (iframeRef.current) {\n const previewOrigin = new URL(iframeRef.current?.src).origin;\n if (event.origin !== previewOrigin) {\n return;\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT) {\n const fieldMetaData = parseFieldMetaData(event.data.payload.path);\n\n if (!fieldMetaData) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.INCOMPLETE_STRAPI_SOURCE;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n /**\n * Ignore (for now) content that comes from separate API requests than the one for the\n * current document. This doesn't do anything about fields that may come from relations to\n * the current document however.\n */\n if (fieldMetaData.documentId !== document.documentId) {\n const { type, message } = PREVIEW_ERROR_MESSAGES.DIFFERENT_DOCUMENT;\n toggleNotification({ type, message: formatMessage(message) });\n return;\n }\n\n try {\n const attribute = getAttributeSchemaFromPath({\n path: fieldMetaData.path,\n components,\n schema,\n document,\n });\n\n // We're able to handle the field, set it in context so the popover can pick it up\n const resolvedBlockIndex =\n typeof event.data.payload.blockIndex === 'number' && event.data.payload.blockIndex >= 0\n ? event.data.payload.blockIndex\n : null;\n setPopoverField({\n ...fieldMetaData,\n position: event.data.payload.position,\n attribute,\n blockIndex: resolvedBlockIndex,\n });\n } catch (error) {\n if (error instanceof PreviewFieldError) {\n // Relation fields can't be inline-edited. Silently ignore rather than showing\n // a notification — the user may have double-clicked a relation element by\n // accident, and showing an error is confusing when no action is needed.\n if (error.messageKey === 'RELATIONS_NOT_HANDLED') {\n return;\n }\n const { type, message } = PREVIEW_ERROR_MESSAGES[error.messageKey];\n toggleNotification({ type, message: formatMessage(message) });\n } else if (error instanceof Error) {\n toggleNotification({ type: 'danger', message: error.message });\n }\n }\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_FIELD_SINGLE_CLICK_HINT) {\n toggleNotification({\n type: 'info',\n message: formatMessage({\n id: 'content-manager.preview.info.single-click-hint',\n defaultMessage: 'Double click to edit',\n }),\n });\n }\n\n if (event.data?.type === INTERNAL_EVENTS.STRAPI_IFRAME_CLICK) {\n setPopoverField(null);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n return () => {\n window.removeEventListener('message', handleMessage);\n };\n }, [components, document, iframeRef, schema, setPopoverField, toggleNotification, formatMessage]);\n if (!popoverField || !iframeRef.current) {\n return null;\n }\n\n const iframeRect = iframeRef.current.getBoundingClientRect();\n\n return (\n <>\n <InputPopoverProvider blockIndex={popoverField.blockIndex}>\n <Popover.Root open={true} onOpenChange={(open) => !open && setPopoverField(null)}>\n <Popover.Trigger>\n <Box\n position=\"fixed\"\n width={popoverField.position.width + 'px'}\n height={popoverField.position.height + 'px'}\n top={0}\n left={0}\n transform={`translate(${iframeRect.left + popoverField.position.left}px, ${iframeRect.top + popoverField.position.top}px)`}\n />\n </Popover.Trigger>\n <Popover.Content\n sideOffset={4}\n collisionPadding={{ top: 8, bottom: 8, left: 4, right: 4 }}\n style={{ zIndex: 5 }}\n >\n <Flex\n direction=\"column\"\n alignItems=\"stretch\"\n padding={4}\n width=\"400px\"\n style={{\n maxHeight: 'var(--radix-popover-content-available-height)',\n overflow: 'hidden',\n minHeight: 0,\n }}\n >\n {/* @ts-expect-error the types of `attribute` clash for some reason */}\n <InputRenderer\n document={documentResponse}\n attribute={popoverField.attribute}\n // TODO: retrieve the proper label from the layout\n label={popoverField.path}\n name={popoverField.path}\n type={popoverField.attribute.type}\n visible={true}\n />\n </Flex>\n </Popover.Content>\n </Popover.Root>\n </InputPopoverProvider>\n </>\n );\n};\n\nexport { InputPopover, useHasInputPopoverParent, usePreviewPopoverBlockIndex };\n"],"names":["InputPopoverProvider","useInputPopoverContext","createContext","useHasInputPopoverParent","context","undefined","usePreviewPopoverBlockIndex","blockIndex","ctx","InputPopover","documentResponse","iframeRef","usePreviewContext","state","popoverField","setPopoverField","document","schema","components","toggleNotification","useNotification","formatMessage","useIntl","React","useEffect","handleMessage","event","current","previewOrigin","URL","src","origin","data","type","INTERNAL_EVENTS","STRAPI_FIELD_FOCUS_INTENT","fieldMetaData","parseFieldMetaData","payload","path","message","PREVIEW_ERROR_MESSAGES","INCOMPLETE_STRAPI_SOURCE","documentId","DIFFERENT_DOCUMENT","attribute","getAttributeSchemaFromPath","resolvedBlockIndex","position","error","PreviewFieldError","messageKey","Error","STRAPI_FIELD_SINGLE_CLICK_HINT","id","defaultMessage","STRAPI_IFRAME_CLICK","window","addEventListener","removeEventListener","iframeRect","getBoundingClientRect","_jsx","_Fragment","_jsxs","Popover","Root","open","onOpenChange","Trigger","Box","width","height","top","left","transform","Content","sideOffset","collisionPadding","bottom","right","style","zIndex","Flex","direction","alignItems","padding","maxHeight","overflow","minHeight","InputRenderer","label","name","visible"],"mappings":"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"}
@@ -33,28 +33,44 @@ function usePreviewInputManager(name, attribute) {
33
33
  const hasInputPopoverParent = InputPopover.useHasInputPopoverParent();
34
34
  const { value } = strapiAdmin.useField(name);
35
35
  const { type } = attribute;
36
+ const isSubmitting = strapiAdmin.useForm('usePreviewInputManager', (state)=>state.isSubmitting);
37
+ const wasSubmittingRef = React__namespace.useRef(isSubmitting);
36
38
  React__namespace.useEffect(()=>{
39
+ const justFinishedSubmitting = wasSubmittingRef.current && !isSubmitting;
40
+ wasSubmittingRef.current = isSubmitting;
37
41
  if (!iframe || !type) {
38
42
  return;
39
43
  }
40
44
  /**
41
45
  * Only send message if the field is not a data structure (component, dynamic zone)
42
46
  * because we already send events for their fields
43
- */ if (![
47
+ */ if ([
44
48
  'component',
45
49
  'dynamiczone'
46
50
  ].includes(type)) {
47
- const sendMessage = getSendMessage.getSendMessage(iframe);
48
- sendMessage(constants.INTERNAL_EVENTS.STRAPI_FIELD_CHANGE, {
49
- field: name,
50
- value
51
- });
51
+ return;
52
+ }
53
+ if (justFinishedSubmitting) {
54
+ // A save just completed. resetForm() (called on the save-success path) re-syncs
55
+ // every field to the server-confirmed value, which looks like a change here even
56
+ // though nothing the user did changed. The previewed frontend already gets the
57
+ // authoritative, correctly-encoded data via the strapiUpdate + revalidate flow
58
+ // triggered by that same save — broadcasting this stale echo would only race
59
+ // against it, reintroducing pre-save (unencoded) content over the fresh fetch.
60
+ return;
52
61
  }
62
+ const sendMessage = getSendMessage.getSendMessage(iframe);
63
+ sendMessage(constants.PUBLIC_EVENTS.STRAPI_FIELD_CHANGE, {
64
+ field: name,
65
+ value,
66
+ type
67
+ });
53
68
  }, [
54
69
  name,
55
70
  value,
56
71
  iframe,
57
- type
72
+ type,
73
+ isSubmitting
58
74
  ]);
59
75
  // Track previous value to detect media deletion
60
76
  const prevValueRef = React__namespace.useRef(value);
@@ -1 +1 @@
1
- {"version":3,"file":"usePreviewInputManager.js","sources":["../../../../admin/src/preview/hooks/usePreviewInputManager.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { useField } from '@strapi/admin/strapi-admin';\nimport { Schema } from '@strapi/types';\n\nimport { useHasInputPopoverParent } from '../components/InputPopover';\nimport { usePreviewContext } from '../pages/Preview';\nimport { INTERNAL_EVENTS } from '../utils/constants';\nimport { getSendMessage } from '../utils/getSendMessage';\n\ntype PreviewInputProps = Pick<\n Required<React.InputHTMLAttributes<HTMLInputElement>>,\n 'onFocus' | 'onBlur'\n>;\n\nexport function usePreviewInputManager(\n name: string,\n attribute: Schema.Attribute.AnyAttribute\n): PreviewInputProps {\n const iframe = usePreviewContext('usePreviewInputManager', (state) => state.iframeRef, false);\n const setPopoverField = usePreviewContext(\n 'usePreviewInputManager',\n (state) => state.setPopoverField,\n false\n );\n const hasInputPopoverParent = useHasInputPopoverParent();\n const { value } = useField(name);\n const { type } = attribute;\n\n React.useEffect(() => {\n if (!iframe || !type) {\n return;\n }\n\n /**\n * Only send message if the field is not a data structure (component, dynamic zone)\n * because we already send events for their fields\n */\n if (!['component', 'dynamiczone'].includes(type)) {\n const sendMessage = getSendMessage(iframe);\n sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_CHANGE, { field: name, value });\n }\n }, [name, value, iframe, type]);\n\n // Track previous value to detect media deletion\n const prevValueRef = React.useRef(value);\n\n React.useEffect(() => {\n // Only run inside popover for media fields\n if (!hasInputPopoverParent || !setPopoverField || type !== 'media') {\n return;\n }\n\n const currentValue = value;\n const previousValue = prevValueRef.current;\n\n // Check if we transitioned from having a value to null/empty\n const hadValue =\n previousValue != null && (Array.isArray(previousValue) ? previousValue.length > 0 : true);\n const hasNoValue =\n currentValue == null || (Array.isArray(currentValue) ? currentValue.length === 0 : false);\n\n if (hadValue && hasNoValue) {\n // Media was deleted, close the popover\n setPopoverField(null);\n }\n\n // Update ref for next comparison\n prevValueRef.current = currentValue;\n }, [value, hasInputPopoverParent, setPopoverField, type]);\n\n const sendMessage = getSendMessage(iframe);\n\n return {\n onFocus: () => {\n if (hasInputPopoverParent) return;\n\n sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_FOCUS, { field: name });\n },\n onBlur: () => {\n if (hasInputPopoverParent) return;\n\n setPopoverField?.(null);\n sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_BLUR, { field: name });\n },\n };\n}\n"],"names":["usePreviewInputManager","name","attribute","iframe","usePreviewContext","state","iframeRef","setPopoverField","hasInputPopoverParent","useHasInputPopoverParent","value","useField","type","React","useEffect","includes","sendMessage","getSendMessage","INTERNAL_EVENTS","STRAPI_FIELD_CHANGE","field","prevValueRef","useRef","currentValue","previousValue","current","hadValue","Array","isArray","length","hasNoValue","onFocus","STRAPI_FIELD_FOCUS","onBlur","STRAPI_FIELD_BLUR"],"mappings":"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"}
1
+ {"version":3,"file":"usePreviewInputManager.js","sources":["../../../../admin/src/preview/hooks/usePreviewInputManager.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { useField, useForm } from '@strapi/admin/strapi-admin';\nimport { Schema } from '@strapi/types';\n\nimport { useHasInputPopoverParent } from '../components/InputPopover';\nimport { usePreviewContext } from '../pages/Preview';\nimport { INTERNAL_EVENTS, PUBLIC_EVENTS } from '../utils/constants';\nimport { getSendMessage } from '../utils/getSendMessage';\n\ntype PreviewInputProps = Pick<\n Required<React.InputHTMLAttributes<HTMLInputElement>>,\n 'onFocus' | 'onBlur'\n>;\n\nexport function usePreviewInputManager(\n name: string,\n attribute: Schema.Attribute.AnyAttribute\n): PreviewInputProps {\n const iframe = usePreviewContext('usePreviewInputManager', (state) => state.iframeRef, false);\n const setPopoverField = usePreviewContext(\n 'usePreviewInputManager',\n (state) => state.setPopoverField,\n false\n );\n const hasInputPopoverParent = useHasInputPopoverParent();\n const { value } = useField(name);\n const { type } = attribute;\n const isSubmitting = useForm('usePreviewInputManager', (state) => state.isSubmitting);\n const wasSubmittingRef = React.useRef(isSubmitting);\n\n React.useEffect(() => {\n const justFinishedSubmitting = wasSubmittingRef.current && !isSubmitting;\n wasSubmittingRef.current = isSubmitting;\n\n if (!iframe || !type) {\n return;\n }\n\n /**\n * Only send message if the field is not a data structure (component, dynamic zone)\n * because we already send events for their fields\n */\n if (['component', 'dynamiczone'].includes(type)) {\n return;\n }\n\n if (justFinishedSubmitting) {\n // A save just completed. resetForm() (called on the save-success path) re-syncs\n // every field to the server-confirmed value, which looks like a change here even\n // though nothing the user did changed. The previewed frontend already gets the\n // authoritative, correctly-encoded data via the strapiUpdate + revalidate flow\n // triggered by that same save — broadcasting this stale echo would only race\n // against it, reintroducing pre-save (unencoded) content over the fresh fetch.\n return;\n }\n\n const sendMessage = getSendMessage(iframe);\n sendMessage(PUBLIC_EVENTS.STRAPI_FIELD_CHANGE, { field: name, value, type });\n }, [name, value, iframe, type, isSubmitting]);\n\n // Track previous value to detect media deletion\n const prevValueRef = React.useRef(value);\n\n React.useEffect(() => {\n // Only run inside popover for media fields\n if (!hasInputPopoverParent || !setPopoverField || type !== 'media') {\n return;\n }\n\n const currentValue = value;\n const previousValue = prevValueRef.current;\n\n // Check if we transitioned from having a value to null/empty\n const hadValue =\n previousValue != null && (Array.isArray(previousValue) ? previousValue.length > 0 : true);\n const hasNoValue =\n currentValue == null || (Array.isArray(currentValue) ? currentValue.length === 0 : false);\n\n if (hadValue && hasNoValue) {\n // Media was deleted, close the popover\n setPopoverField(null);\n }\n\n // Update ref for next comparison\n prevValueRef.current = currentValue;\n }, [value, hasInputPopoverParent, setPopoverField, type]);\n\n const sendMessage = getSendMessage(iframe);\n\n return {\n onFocus: () => {\n if (hasInputPopoverParent) return;\n\n sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_FOCUS, { field: name });\n },\n onBlur: () => {\n if (hasInputPopoverParent) return;\n\n setPopoverField?.(null);\n sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_BLUR, { field: name });\n },\n };\n}\n"],"names":["usePreviewInputManager","name","attribute","iframe","usePreviewContext","state","iframeRef","setPopoverField","hasInputPopoverParent","useHasInputPopoverParent","value","useField","type","isSubmitting","useForm","wasSubmittingRef","React","useRef","useEffect","justFinishedSubmitting","current","includes","sendMessage","getSendMessage","PUBLIC_EVENTS","STRAPI_FIELD_CHANGE","field","prevValueRef","currentValue","previousValue","hadValue","Array","isArray","length","hasNoValue","onFocus","INTERNAL_EVENTS","STRAPI_FIELD_FOCUS","onBlur","STRAPI_FIELD_BLUR"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import { useField } from '@strapi/admin/strapi-admin';
2
+ import { useField, useForm } from '@strapi/admin/strapi-admin';
3
3
  import { useHasInputPopoverParent } from '../components/InputPopover.mjs';
4
4
  import { usePreviewContext } from '../pages/Preview.mjs';
5
- import { INTERNAL_EVENTS } from '../utils/constants.mjs';
5
+ import { PUBLIC_EVENTS, INTERNAL_EVENTS } from '../utils/constants.mjs';
6
6
  import { getSendMessage } from '../utils/getSendMessage.mjs';
7
7
 
8
8
  function usePreviewInputManager(name, attribute) {
@@ -11,28 +11,44 @@ function usePreviewInputManager(name, attribute) {
11
11
  const hasInputPopoverParent = useHasInputPopoverParent();
12
12
  const { value } = useField(name);
13
13
  const { type } = attribute;
14
+ const isSubmitting = useForm('usePreviewInputManager', (state)=>state.isSubmitting);
15
+ const wasSubmittingRef = React.useRef(isSubmitting);
14
16
  React.useEffect(()=>{
17
+ const justFinishedSubmitting = wasSubmittingRef.current && !isSubmitting;
18
+ wasSubmittingRef.current = isSubmitting;
15
19
  if (!iframe || !type) {
16
20
  return;
17
21
  }
18
22
  /**
19
23
  * Only send message if the field is not a data structure (component, dynamic zone)
20
24
  * because we already send events for their fields
21
- */ if (![
25
+ */ if ([
22
26
  'component',
23
27
  'dynamiczone'
24
28
  ].includes(type)) {
25
- const sendMessage = getSendMessage(iframe);
26
- sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_CHANGE, {
27
- field: name,
28
- value
29
- });
29
+ return;
30
30
  }
31
+ if (justFinishedSubmitting) {
32
+ // A save just completed. resetForm() (called on the save-success path) re-syncs
33
+ // every field to the server-confirmed value, which looks like a change here even
34
+ // though nothing the user did changed. The previewed frontend already gets the
35
+ // authoritative, correctly-encoded data via the strapiUpdate + revalidate flow
36
+ // triggered by that same save — broadcasting this stale echo would only race
37
+ // against it, reintroducing pre-save (unencoded) content over the fresh fetch.
38
+ return;
39
+ }
40
+ const sendMessage = getSendMessage(iframe);
41
+ sendMessage(PUBLIC_EVENTS.STRAPI_FIELD_CHANGE, {
42
+ field: name,
43
+ value,
44
+ type
45
+ });
31
46
  }, [
32
47
  name,
33
48
  value,
34
49
  iframe,
35
- type
50
+ type,
51
+ isSubmitting
36
52
  ]);
37
53
  // Track previous value to detect media deletion
38
54
  const prevValueRef = React.useRef(value);