@strapi/content-manager 0.0.0-next.68883a121b7f22cc4ba74b40e02159d567c34e84 → 0.0.0-next.6a38f974ec7350286f5c323503fb1e90c54da7ca

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 (149) hide show
  1. package/dist/admin/components/Widgets.js +15 -10
  2. package/dist/admin/components/Widgets.js.map +1 -1
  3. package/dist/admin/components/Widgets.mjs +16 -11
  4. package/dist/admin/components/Widgets.mjs.map +1 -1
  5. package/dist/admin/hooks/useDocumentActions.js +0 -3
  6. package/dist/admin/hooks/useDocumentActions.js.map +1 -1
  7. package/dist/admin/hooks/useDocumentActions.mjs +1 -4
  8. package/dist/admin/hooks/useDocumentActions.mjs.map +1 -1
  9. package/dist/admin/index.js +43 -24
  10. package/dist/admin/index.js.map +1 -1
  11. package/dist/admin/index.mjs +44 -25
  12. package/dist/admin/index.mjs.map +1 -1
  13. package/dist/admin/layout.js +1 -27
  14. package/dist/admin/layout.js.map +1 -1
  15. package/dist/admin/layout.mjs +2 -9
  16. package/dist/admin/layout.mjs.map +1 -1
  17. package/dist/admin/pages/EditView/EditViewPage.js +13 -20
  18. package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
  19. package/dist/admin/pages/EditView/EditViewPage.mjs +14 -21
  20. package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
  21. package/dist/admin/pages/EditView/components/Blocker.js +18 -0
  22. package/dist/admin/pages/EditView/components/Blocker.js.map +1 -0
  23. package/dist/admin/pages/EditView/components/Blocker.mjs +16 -0
  24. package/dist/admin/pages/EditView/components/Blocker.mjs.map +1 -0
  25. package/dist/admin/pages/EditView/components/DocumentActions.js +18 -3
  26. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  27. package/dist/admin/pages/EditView/components/DocumentActions.mjs +19 -4
  28. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  29. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +4 -1
  30. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  31. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +4 -1
  32. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  33. package/dist/admin/pages/EditView/components/InputRenderer.js +15 -5
  34. package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
  35. package/dist/admin/pages/EditView/components/InputRenderer.mjs +15 -5
  36. package/dist/admin/pages/EditView/components/InputRenderer.mjs.map +1 -1
  37. package/dist/admin/pages/EditView/utils/data.js +33 -8
  38. package/dist/admin/pages/EditView/utils/data.js.map +1 -1
  39. package/dist/admin/pages/EditView/utils/data.mjs +33 -8
  40. package/dist/admin/pages/EditView/utils/data.mjs.map +1 -1
  41. package/dist/admin/pages/ListView/ListViewPage.js +152 -143
  42. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  43. package/dist/admin/pages/ListView/ListViewPage.mjs +153 -144
  44. package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
  45. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js +12 -2
  46. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.js.map +1 -1
  47. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs +12 -2
  48. package/dist/admin/pages/ListView/components/BulkActions/PublishAction.mjs.map +1 -1
  49. package/dist/admin/pages/ListView/components/Filters.js +3 -1
  50. package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
  51. package/dist/admin/pages/ListView/components/Filters.mjs +3 -1
  52. package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
  53. package/dist/admin/preview/components/InputPopover.js +73 -0
  54. package/dist/admin/preview/components/InputPopover.js.map +1 -0
  55. package/dist/admin/preview/components/InputPopover.mjs +70 -0
  56. package/dist/admin/preview/components/InputPopover.mjs.map +1 -0
  57. package/dist/admin/preview/components/PreviewSidePanel.js +31 -4
  58. package/dist/admin/preview/components/PreviewSidePanel.js.map +1 -1
  59. package/dist/admin/preview/components/PreviewSidePanel.mjs +32 -5
  60. package/dist/admin/preview/components/PreviewSidePanel.mjs.map +1 -1
  61. package/dist/admin/preview/hooks/usePreviewInputManager.js +67 -0
  62. package/dist/admin/preview/hooks/usePreviewInputManager.js.map +1 -0
  63. package/dist/admin/preview/hooks/usePreviewInputManager.mjs +46 -0
  64. package/dist/admin/preview/hooks/usePreviewInputManager.mjs.map +1 -0
  65. package/dist/admin/preview/pages/Preview.js +170 -68
  66. package/dist/admin/preview/pages/Preview.js.map +1 -1
  67. package/dist/admin/preview/pages/Preview.mjs +172 -70
  68. package/dist/admin/preview/pages/Preview.mjs.map +1 -1
  69. package/dist/admin/preview/utils/constants.js +22 -0
  70. package/dist/admin/preview/utils/constants.js.map +1 -0
  71. package/dist/admin/preview/utils/constants.mjs +19 -0
  72. package/dist/admin/preview/utils/constants.mjs.map +1 -0
  73. package/dist/admin/preview/utils/getSendMessage.js +22 -0
  74. package/dist/admin/preview/utils/getSendMessage.js.map +1 -0
  75. package/dist/admin/preview/utils/getSendMessage.mjs +20 -0
  76. package/dist/admin/preview/utils/getSendMessage.mjs.map +1 -0
  77. package/dist/admin/preview/utils/previewScript.js +296 -0
  78. package/dist/admin/preview/utils/previewScript.js.map +1 -0
  79. package/dist/admin/preview/utils/previewScript.mjs +294 -0
  80. package/dist/admin/preview/utils/previewScript.mjs.map +1 -0
  81. package/dist/admin/services/api.js +2 -1
  82. package/dist/admin/services/api.js.map +1 -1
  83. package/dist/admin/services/api.mjs +2 -1
  84. package/dist/admin/services/api.mjs.map +1 -1
  85. package/dist/admin/services/documents.js +22 -12
  86. package/dist/admin/services/documents.js.map +1 -1
  87. package/dist/admin/services/documents.mjs +22 -12
  88. package/dist/admin/services/documents.mjs.map +1 -1
  89. package/dist/admin/services/homepage.js +2 -11
  90. package/dist/admin/services/homepage.js.map +1 -1
  91. package/dist/admin/services/homepage.mjs +3 -11
  92. package/dist/admin/services/homepage.mjs.map +1 -1
  93. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  94. package/dist/admin/src/pages/EditView/components/Blocker.d.ts +5 -0
  95. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +1 -1
  96. package/dist/admin/src/preview/components/InputPopover.d.ts +6 -0
  97. package/dist/admin/src/preview/hooks/usePreviewInputManager.d.ts +4 -0
  98. package/dist/admin/src/preview/pages/Preview.d.ts +8 -0
  99. package/dist/admin/src/preview/services/preview.d.ts +1 -1
  100. package/dist/admin/src/preview/utils/constants.d.ts +20 -0
  101. package/dist/admin/src/preview/utils/getSendMessage.d.ts +11 -0
  102. package/dist/admin/src/preview/utils/previewScript.d.ts +22 -0
  103. package/dist/admin/src/services/api.d.ts +1 -1
  104. package/dist/admin/src/services/components.d.ts +2 -2
  105. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  106. package/dist/admin/src/services/documents.d.ts +16 -16
  107. package/dist/admin/src/services/homepage.d.ts +2 -6
  108. package/dist/admin/src/services/init.d.ts +1 -1
  109. package/dist/admin/src/services/relations.d.ts +2 -2
  110. package/dist/admin/src/services/uid.d.ts +3 -3
  111. package/dist/admin/src/utils/api.d.ts +1 -1
  112. package/dist/admin/translations/en.json.js +4 -0
  113. package/dist/admin/translations/en.json.js.map +1 -1
  114. package/dist/admin/translations/en.json.mjs +4 -0
  115. package/dist/admin/translations/en.json.mjs.map +1 -1
  116. package/dist/admin/utils/api.js +1 -1
  117. package/dist/admin/utils/api.js.map +1 -1
  118. package/dist/admin/utils/api.mjs +1 -1
  119. package/dist/admin/utils/api.mjs.map +1 -1
  120. package/dist/admin/utils/validation.js +2 -1
  121. package/dist/admin/utils/validation.js.map +1 -1
  122. package/dist/admin/utils/validation.mjs +2 -1
  123. package/dist/admin/utils/validation.mjs.map +1 -1
  124. package/dist/server/history/services/lifecycles.js +20 -19
  125. package/dist/server/history/services/lifecycles.js.map +1 -1
  126. package/dist/server/history/services/lifecycles.mjs +20 -19
  127. package/dist/server/history/services/lifecycles.mjs.map +1 -1
  128. package/dist/server/homepage/services/homepage.js +3 -3
  129. package/dist/server/homepage/services/homepage.js.map +1 -1
  130. package/dist/server/homepage/services/homepage.mjs +3 -3
  131. package/dist/server/homepage/services/homepage.mjs.map +1 -1
  132. package/dist/server/preview/services/preview-config.js +5 -1
  133. package/dist/server/preview/services/preview-config.js.map +1 -1
  134. package/dist/server/preview/services/preview-config.mjs +5 -1
  135. package/dist/server/preview/services/preview-config.mjs.map +1 -1
  136. package/dist/server/preview/services/preview.js +4 -0
  137. package/dist/server/preview/services/preview.js.map +1 -1
  138. package/dist/server/preview/services/preview.mjs +4 -0
  139. package/dist/server/preview/services/preview.mjs.map +1 -1
  140. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  141. package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
  142. package/dist/server/src/preview/services/index.d.ts +1 -0
  143. package/dist/server/src/preview/services/index.d.ts.map +1 -1
  144. package/dist/server/src/preview/services/preview-config.d.ts +1 -0
  145. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -1
  146. package/dist/server/src/preview/services/preview.d.ts.map +1 -1
  147. package/dist/server/src/preview/utils.d.ts +1 -0
  148. package/dist/server/src/preview/utils.d.ts.map +1 -1
  149. package/package.json +5 -6
@@ -0,0 +1,296 @@
1
+ 'use strict';
2
+
3
+ // NOTE: This override is for the properties on _user's site_, it's not about Strapi Admin.
4
+ /**
5
+ * previewScript will be injected into the preview iframe after being stringified.
6
+ * Therefore it CANNOT use any imports, or refer to any variables outside of its own scope.
7
+ * It's why many functions are defined within previewScript, it's the only way to avoid going full spaghetti.
8
+ * To get a better overview of everything previewScript does, go to the orchestration part at its end.
9
+ */ const previewScript = (shouldRun = true)=>{
10
+ /* -----------------------------------------------------------------------------------------------
11
+ * Params
12
+ * ---------------------------------------------------------------------------------------------*/ const HIGHLIGHT_PADDING = 2; // in pixels
13
+ const HIGHLIGHT_HOVER_COLOR = window.STRAPI_HIGHLIGHT_HOVER_COLOR ?? '#4945ff'; // dark primary500
14
+ const HIGHLIGHT_ACTIVE_COLOR = window.STRAPI_HIGHLIGHT_ACTIVE_COLOR ?? '#7b79ff'; // dark primary600
15
+ const SOURCE_ATTRIBUTE = 'data-strapi-source';
16
+ const OVERLAY_ID = 'strapi-preview-overlay';
17
+ const INTERNAL_EVENTS = {
18
+ STRAPI_FIELD_FOCUS: 'strapiFieldFocus',
19
+ STRAPI_FIELD_BLUR: 'strapiFieldBlur',
20
+ STRAPI_FIELD_CHANGE: 'strapiFieldChange',
21
+ STRAPI_FIELD_FOCUS_INTENT: 'strapiFieldFocusIntent'
22
+ };
23
+ /**
24
+ * Calling the function in no-run mode lets us retrieve the constants from other files and keep
25
+ * a single source of truth for them. It's the only way to do this because this script can't
26
+ * refer to any variables outside of its own scope, because it's stringified before it's run.
27
+ */ if (!shouldRun) {
28
+ return {
29
+ INTERNAL_EVENTS
30
+ };
31
+ }
32
+ /* -----------------------------------------------------------------------------------------------
33
+ * Utils
34
+ * ---------------------------------------------------------------------------------------------*/ const sendMessage = (type, payload)=>{
35
+ window.parent.postMessage({
36
+ type,
37
+ payload
38
+ }, '*');
39
+ };
40
+ /* -----------------------------------------------------------------------------------------------
41
+ * Functionality pieces
42
+ * ---------------------------------------------------------------------------------------------*/ const createOverlaySystem = ()=>{
43
+ // Clean up before creating a new overlay so we can safely call previewScript multiple times
44
+ window.__strapi_previewCleanup?.();
45
+ document.getElementById(OVERLAY_ID)?.remove();
46
+ const overlay = document.createElement('div');
47
+ overlay.id = OVERLAY_ID;
48
+ overlay.style.cssText = `
49
+ position: fixed;
50
+ top: 0;
51
+ left: 0;
52
+ width: 100%;
53
+ height: 100%;
54
+ pointer-events: none;
55
+ z-index: 9999;
56
+ `;
57
+ window.document.body.appendChild(overlay);
58
+ return overlay;
59
+ };
60
+ const createHighlightManager = (overlay)=>{
61
+ const elements = window.document.querySelectorAll(`[${SOURCE_ATTRIBUTE}]`);
62
+ const eventListeners = [];
63
+ const highlights = [];
64
+ const focusedHighlights = [];
65
+ let focusedField = null;
66
+ const drawHighlight = (target, highlight)=>{
67
+ if (!highlight) return;
68
+ const rect = target.getBoundingClientRect();
69
+ highlight.style.width = `${rect.width + HIGHLIGHT_PADDING * 2}px`;
70
+ highlight.style.height = `${rect.height + HIGHLIGHT_PADDING * 2}px`;
71
+ highlight.style.transform = `translate(${rect.left - HIGHLIGHT_PADDING}px, ${rect.top - HIGHLIGHT_PADDING}px)`;
72
+ };
73
+ const updateAllHighlights = ()=>{
74
+ highlights.forEach((highlight, index)=>{
75
+ const element = elements[index];
76
+ if (element && highlight) {
77
+ drawHighlight(element, highlight);
78
+ }
79
+ });
80
+ };
81
+ elements.forEach((element)=>{
82
+ if (element instanceof HTMLElement) {
83
+ const highlight = document.createElement('div');
84
+ highlight.style.cssText = `
85
+ position: absolute;
86
+ outline: 2px solid transparent;
87
+ pointer-events: none;
88
+ border-radius: 2px;
89
+ background-color: transparent;
90
+ will-change: transform;
91
+ transition: outline-color 0.1s ease-in-out;
92
+ `;
93
+ // Move hover detection to the underlying element
94
+ const mouseEnterHandler = ()=>{
95
+ if (!highlightManager.focusedHighlights.includes(highlight)) {
96
+ highlight.style.outlineColor = HIGHLIGHT_HOVER_COLOR;
97
+ }
98
+ };
99
+ const mouseLeaveHandler = ()=>{
100
+ if (!highlightManager.focusedHighlights.includes(highlight)) {
101
+ highlight.style.outlineColor = 'transparent';
102
+ }
103
+ };
104
+ const doubleClickHandler = ()=>{
105
+ const sourceAttribute = element.getAttribute(SOURCE_ATTRIBUTE);
106
+ if (sourceAttribute) {
107
+ const rect = element.getBoundingClientRect();
108
+ sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT, {
109
+ path: sourceAttribute,
110
+ position: {
111
+ top: rect.top,
112
+ left: rect.left,
113
+ right: rect.right,
114
+ bottom: rect.bottom,
115
+ width: rect.width,
116
+ height: rect.height
117
+ }
118
+ });
119
+ }
120
+ };
121
+ const mouseDownHandler = (event)=>{
122
+ // Prevent default multi click to select behavior
123
+ if (event.detail >= 2) {
124
+ event.preventDefault();
125
+ }
126
+ };
127
+ element.addEventListener('mouseenter', mouseEnterHandler);
128
+ element.addEventListener('mouseleave', mouseLeaveHandler);
129
+ element.addEventListener('dblclick', doubleClickHandler);
130
+ element.addEventListener('mousedown', mouseDownHandler);
131
+ // Store event listeners for cleanup
132
+ eventListeners.push({
133
+ element,
134
+ type: 'mouseenter',
135
+ handler: mouseEnterHandler
136
+ }, {
137
+ element,
138
+ type: 'mouseleave',
139
+ handler: mouseLeaveHandler
140
+ }, {
141
+ element,
142
+ type: 'dblclick',
143
+ handler: doubleClickHandler
144
+ }, {
145
+ element,
146
+ type: 'mousedown',
147
+ handler: mouseDownHandler
148
+ });
149
+ highlights.push(highlight);
150
+ overlay.appendChild(highlight);
151
+ drawHighlight(element, highlight);
152
+ }
153
+ });
154
+ return {
155
+ elements,
156
+ updateAllHighlights,
157
+ eventListeners,
158
+ highlights,
159
+ focusedHighlights,
160
+ setFocusedField: (field)=>{
161
+ focusedField = field;
162
+ },
163
+ getFocusedField: ()=>focusedField
164
+ };
165
+ };
166
+ const setupObservers = (highlightManager)=>{
167
+ const resizeObserver = new ResizeObserver(()=>{
168
+ highlightManager.updateAllHighlights();
169
+ });
170
+ highlightManager.elements.forEach((element)=>{
171
+ resizeObserver.observe(element);
172
+ });
173
+ resizeObserver.observe(document.documentElement);
174
+ const updateOnScroll = ()=>{
175
+ highlightManager.updateAllHighlights();
176
+ };
177
+ const scrollableElements = new Set();
178
+ scrollableElements.add(window);
179
+ // Find all scrollable ancestors for all tracked elements
180
+ highlightManager.elements.forEach((element)=>{
181
+ let parent = element.parentElement;
182
+ while(parent){
183
+ const computedStyle = window.getComputedStyle(parent);
184
+ const overflow = computedStyle.overflow + computedStyle.overflowX + computedStyle.overflowY;
185
+ if (overflow.includes('scroll') || overflow.includes('auto')) {
186
+ scrollableElements.add(parent);
187
+ }
188
+ parent = parent.parentElement;
189
+ }
190
+ });
191
+ // Add scroll listeners to all scrollable elements
192
+ scrollableElements.forEach((element)=>{
193
+ if (element === window) {
194
+ window.addEventListener('scroll', updateOnScroll);
195
+ window.addEventListener('resize', updateOnScroll);
196
+ } else {
197
+ element.addEventListener('scroll', updateOnScroll);
198
+ }
199
+ });
200
+ return {
201
+ resizeObserver,
202
+ updateOnScroll,
203
+ scrollableElements
204
+ };
205
+ };
206
+ const setupEventHandlers = (highlightManager)=>{
207
+ const handleMessage = (event)=>{
208
+ if (!event.data?.type) return;
209
+ // The user typed in an input, reflect the change in the preview
210
+ if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_CHANGE) {
211
+ const { field, value } = event.data.payload;
212
+ if (!field) return;
213
+ const matchingElements = document.querySelectorAll(`[${SOURCE_ATTRIBUTE}="${field}"]`);
214
+ matchingElements.forEach((element)=>{
215
+ if (element instanceof HTMLElement) {
216
+ element.textContent = value || '';
217
+ }
218
+ });
219
+ return;
220
+ }
221
+ // The user focused a new input, update the highlights in the preview
222
+ if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS) {
223
+ const { field } = event.data.payload;
224
+ if (!field) return;
225
+ // Clear existing focused highlights
226
+ highlightManager.focusedHighlights.forEach((highlight)=>{
227
+ highlight.style.outlineColor = 'transparent';
228
+ });
229
+ highlightManager.focusedHighlights.length = 0;
230
+ // Set new focused field and highlight matching elements
231
+ highlightManager.setFocusedField(field);
232
+ const matchingElements = document.querySelectorAll(`[${SOURCE_ATTRIBUTE}="${field}"]`);
233
+ matchingElements.forEach((element)=>{
234
+ const highlight = highlightManager.highlights[Array.from(highlightManager.elements).indexOf(element)];
235
+ if (highlight) {
236
+ highlight.style.outlineColor = HIGHLIGHT_ACTIVE_COLOR;
237
+ highlight.style.outlineWidth = '3px';
238
+ highlightManager.focusedHighlights.push(highlight);
239
+ }
240
+ });
241
+ return;
242
+ }
243
+ // The user is no longer focusing an input, remove the highlights
244
+ if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_BLUR) {
245
+ const { field } = event.data.payload;
246
+ if (field !== highlightManager.getFocusedField()) return;
247
+ highlightManager.focusedHighlights.forEach((highlight)=>{
248
+ highlight.style.outlineColor = 'transparent';
249
+ highlight.style.outlineWidth = '2px';
250
+ });
251
+ highlightManager.focusedHighlights.length = 0;
252
+ highlightManager.setFocusedField(null);
253
+ }
254
+ };
255
+ window.addEventListener('message', handleMessage);
256
+ // Add the message handler to the cleanup list
257
+ const messageEventListener = {
258
+ element: window,
259
+ type: 'message',
260
+ handler: handleMessage
261
+ };
262
+ return [
263
+ ...highlightManager.eventListeners,
264
+ messageEventListener
265
+ ];
266
+ };
267
+ const createCleanupSystem = (overlay, observers, eventHandlers)=>{
268
+ window.__strapi_previewCleanup = ()=>{
269
+ observers.resizeObserver.disconnect();
270
+ // Remove all scroll listeners
271
+ observers.scrollableElements.forEach((element)=>{
272
+ if (element === window) {
273
+ window.removeEventListener('scroll', observers.updateOnScroll);
274
+ window.removeEventListener('resize', observers.updateOnScroll);
275
+ } else {
276
+ element.removeEventListener('scroll', observers.updateOnScroll);
277
+ }
278
+ });
279
+ // Remove highlight event listeners
280
+ eventHandlers.forEach(({ element, type, handler })=>{
281
+ element.removeEventListener(type, handler);
282
+ });
283
+ overlay.remove();
284
+ };
285
+ };
286
+ /* -----------------------------------------------------------------------------------------------
287
+ * Orchestration
288
+ * ---------------------------------------------------------------------------------------------*/ const overlay = createOverlaySystem();
289
+ const highlightManager = createHighlightManager(overlay);
290
+ const observers = setupObservers(highlightManager);
291
+ const eventHandlers = setupEventHandlers(highlightManager);
292
+ createCleanupSystem(overlay, observers, eventHandlers);
293
+ };
294
+
295
+ exports.previewScript = previewScript;
296
+ //# sourceMappingURL=previewScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"previewScript.js","sources":["../../../../admin/src/preview/utils/previewScript.ts"],"sourcesContent":["// NOTE: This override is for the properties on _user's site_, it's not about Strapi Admin.\ndeclare global {\n interface Window {\n __strapi_previewCleanup?: () => void;\n STRAPI_HIGHLIGHT_HOVER_COLOR?: string;\n STRAPI_HIGHLIGHT_ACTIVE_COLOR?: string;\n }\n}\n\n/**\n * previewScript will be injected into the preview iframe after being stringified.\n * Therefore it CANNOT use any imports, or refer to any variables outside of its own scope.\n * It's why many functions are defined within previewScript, it's the only way to avoid going full spaghetti.\n * To get a better overview of everything previewScript does, go to the orchestration part at its end.\n */\nconst previewScript = (shouldRun = true) => {\n /* -----------------------------------------------------------------------------------------------\n * Params\n * ---------------------------------------------------------------------------------------------*/\n const HIGHLIGHT_PADDING = 2; // in pixels\n const HIGHLIGHT_HOVER_COLOR = window.STRAPI_HIGHLIGHT_HOVER_COLOR ?? '#4945ff'; // dark primary500\n const HIGHLIGHT_ACTIVE_COLOR = window.STRAPI_HIGHLIGHT_ACTIVE_COLOR ?? '#7b79ff'; // dark primary600\n\n const SOURCE_ATTRIBUTE = 'data-strapi-source';\n const OVERLAY_ID = 'strapi-preview-overlay';\n const INTERNAL_EVENTS = {\n STRAPI_FIELD_FOCUS: 'strapiFieldFocus',\n STRAPI_FIELD_BLUR: 'strapiFieldBlur',\n STRAPI_FIELD_CHANGE: 'strapiFieldChange',\n STRAPI_FIELD_FOCUS_INTENT: 'strapiFieldFocusIntent',\n } as const;\n\n /**\n * Calling the function in no-run mode lets us retrieve the constants from other files and keep\n * a single source of truth for them. It's the only way to do this because this script can't\n * refer to any variables outside of its own scope, because it's stringified before it's run.\n */\n if (!shouldRun) {\n return { INTERNAL_EVENTS };\n }\n\n /* -----------------------------------------------------------------------------------------------\n * Utils\n * ---------------------------------------------------------------------------------------------*/\n\n const sendMessage = (\n type: (typeof INTERNAL_EVENTS)[keyof typeof INTERNAL_EVENTS],\n payload: unknown\n ) => {\n window.parent.postMessage({ type, payload }, '*');\n };\n\n /* -----------------------------------------------------------------------------------------------\n * Functionality pieces\n * ---------------------------------------------------------------------------------------------*/\n\n const createOverlaySystem = () => {\n // Clean up before creating a new overlay so we can safely call previewScript multiple times\n window.__strapi_previewCleanup?.();\n document.getElementById(OVERLAY_ID)?.remove();\n\n const overlay = document.createElement('div');\n overlay.id = OVERLAY_ID;\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 9999;\n `;\n\n window.document.body.appendChild(overlay);\n return overlay;\n };\n\n type EventListenersList = Array<{\n element: HTMLElement | Window;\n type: keyof HTMLElementEventMap | 'message';\n handler: EventListener;\n }>;\n\n const createHighlightManager = (overlay: HTMLElement) => {\n const elements = window.document.querySelectorAll(`[${SOURCE_ATTRIBUTE}]`);\n const eventListeners: EventListenersList = [];\n const highlights: HTMLElement[] = [];\n const focusedHighlights: HTMLElement[] = [];\n let focusedField: string | null = null;\n\n const drawHighlight = (target: Element, highlight: HTMLElement) => {\n if (!highlight) return;\n\n const rect = target.getBoundingClientRect();\n highlight.style.width = `${rect.width + HIGHLIGHT_PADDING * 2}px`;\n highlight.style.height = `${rect.height + HIGHLIGHT_PADDING * 2}px`;\n highlight.style.transform = `translate(${rect.left - HIGHLIGHT_PADDING}px, ${rect.top - HIGHLIGHT_PADDING}px)`;\n };\n\n const updateAllHighlights = () => {\n highlights.forEach((highlight, index) => {\n const element = elements[index];\n if (element && highlight) {\n drawHighlight(element, highlight);\n }\n });\n };\n\n elements.forEach((element) => {\n if (element instanceof HTMLElement) {\n const highlight = document.createElement('div');\n highlight.style.cssText = `\n position: absolute;\n outline: 2px solid transparent;\n pointer-events: none;\n border-radius: 2px;\n background-color: transparent;\n will-change: transform;\n transition: outline-color 0.1s ease-in-out;\n `;\n\n // Move hover detection to the underlying element\n const mouseEnterHandler = () => {\n if (!highlightManager.focusedHighlights.includes(highlight)) {\n highlight.style.outlineColor = HIGHLIGHT_HOVER_COLOR;\n }\n };\n const mouseLeaveHandler = () => {\n if (!highlightManager.focusedHighlights.includes(highlight)) {\n highlight.style.outlineColor = 'transparent';\n }\n };\n const doubleClickHandler = () => {\n const sourceAttribute = element.getAttribute(SOURCE_ATTRIBUTE);\n if (sourceAttribute) {\n const rect = element.getBoundingClientRect();\n sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT, {\n path: sourceAttribute,\n position: {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n },\n });\n }\n };\n const mouseDownHandler = (event: MouseEvent) => {\n // Prevent default multi click to select behavior\n if (event.detail >= 2) {\n event.preventDefault();\n }\n };\n\n element.addEventListener('mouseenter', mouseEnterHandler);\n element.addEventListener('mouseleave', mouseLeaveHandler);\n element.addEventListener('dblclick', doubleClickHandler);\n element.addEventListener('mousedown', mouseDownHandler);\n\n // Store event listeners for cleanup\n eventListeners.push(\n { element, type: 'mouseenter', handler: mouseEnterHandler },\n { element, type: 'mouseleave', handler: mouseLeaveHandler },\n { element, type: 'dblclick', handler: doubleClickHandler },\n { element, type: 'mousedown', handler: mouseDownHandler as EventListener }\n );\n\n highlights.push(highlight);\n overlay.appendChild(highlight);\n\n drawHighlight(element, highlight);\n }\n });\n\n return {\n elements,\n updateAllHighlights,\n eventListeners,\n highlights,\n focusedHighlights,\n setFocusedField: (field: string | null) => {\n focusedField = field;\n },\n getFocusedField: () => focusedField,\n };\n };\n\n type HighlightManager = ReturnType<typeof createHighlightManager>;\n\n const setupObservers = (highlightManager: HighlightManager) => {\n const resizeObserver = new ResizeObserver(() => {\n highlightManager.updateAllHighlights();\n });\n\n highlightManager.elements.forEach((element: Element) => {\n resizeObserver.observe(element);\n });\n\n resizeObserver.observe(document.documentElement);\n\n const updateOnScroll = () => {\n highlightManager.updateAllHighlights();\n };\n\n const scrollableElements = new Set<Element | Window>();\n scrollableElements.add(window);\n\n // Find all scrollable ancestors for all tracked elements\n highlightManager.elements.forEach((element) => {\n let parent = element.parentElement;\n while (parent) {\n const computedStyle = window.getComputedStyle(parent);\n const overflow = computedStyle.overflow + computedStyle.overflowX + computedStyle.overflowY;\n\n if (overflow.includes('scroll') || overflow.includes('auto')) {\n scrollableElements.add(parent);\n }\n\n parent = parent.parentElement;\n }\n });\n\n // Add scroll listeners to all scrollable elements\n scrollableElements.forEach((element) => {\n if (element === window) {\n window.addEventListener('scroll', updateOnScroll);\n window.addEventListener('resize', updateOnScroll);\n } else {\n element.addEventListener('scroll', updateOnScroll);\n }\n });\n\n return {\n resizeObserver,\n updateOnScroll,\n scrollableElements,\n };\n };\n\n const setupEventHandlers = (highlightManager: HighlightManager) => {\n const handleMessage = (event: MessageEvent) => {\n if (!event.data?.type) return;\n\n // The user typed in an input, reflect the change in the preview\n if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_CHANGE) {\n const { field, value } = event.data.payload;\n if (!field) return;\n\n const matchingElements = document.querySelectorAll(`[${SOURCE_ATTRIBUTE}=\"${field}\"]`);\n matchingElements.forEach((element) => {\n if (element instanceof HTMLElement) {\n element.textContent = value || '';\n }\n });\n return;\n }\n\n // The user focused a new input, update the highlights in the preview\n if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS) {\n const { field } = event.data.payload;\n if (!field) return;\n\n // Clear existing focused highlights\n highlightManager.focusedHighlights.forEach((highlight: HTMLElement) => {\n highlight.style.outlineColor = 'transparent';\n });\n highlightManager.focusedHighlights.length = 0;\n\n // Set new focused field and highlight matching elements\n highlightManager.setFocusedField(field);\n const matchingElements = document.querySelectorAll(`[${SOURCE_ATTRIBUTE}=\"${field}\"]`);\n matchingElements.forEach((element) => {\n const highlight =\n highlightManager.highlights[Array.from(highlightManager.elements).indexOf(element)];\n if (highlight) {\n highlight.style.outlineColor = HIGHLIGHT_ACTIVE_COLOR;\n highlight.style.outlineWidth = '3px';\n highlightManager.focusedHighlights.push(highlight);\n }\n });\n return;\n }\n\n // The user is no longer focusing an input, remove the highlights\n if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_BLUR) {\n const { field } = event.data.payload;\n if (field !== highlightManager.getFocusedField()) return;\n\n highlightManager.focusedHighlights.forEach((highlight: HTMLElement) => {\n highlight.style.outlineColor = 'transparent';\n highlight.style.outlineWidth = '2px';\n });\n highlightManager.focusedHighlights.length = 0;\n highlightManager.setFocusedField(null);\n }\n };\n\n window.addEventListener('message', handleMessage);\n\n // Add the message handler to the cleanup list\n const messageEventListener = {\n element: window,\n type: 'message' as keyof HTMLElementEventMap,\n handler: handleMessage as EventListener,\n };\n\n return [...highlightManager.eventListeners, messageEventListener];\n };\n\n const createCleanupSystem = (\n overlay: HTMLElement,\n observers: ReturnType<typeof setupObservers>,\n eventHandlers: EventListenersList\n ) => {\n window.__strapi_previewCleanup = () => {\n observers.resizeObserver.disconnect();\n\n // Remove all scroll listeners\n observers.scrollableElements.forEach((element) => {\n if (element === window) {\n window.removeEventListener('scroll', observers.updateOnScroll);\n window.removeEventListener('resize', observers.updateOnScroll);\n } else {\n (element as Element).removeEventListener('scroll', observers.updateOnScroll);\n }\n });\n\n // Remove highlight event listeners\n eventHandlers.forEach(({ element, type, handler }) => {\n element.removeEventListener(type, handler);\n });\n\n overlay.remove();\n };\n };\n\n /* -----------------------------------------------------------------------------------------------\n * Orchestration\n * ---------------------------------------------------------------------------------------------*/\n\n const overlay = createOverlaySystem();\n const highlightManager = createHighlightManager(overlay);\n const observers = setupObservers(highlightManager);\n const eventHandlers = setupEventHandlers(highlightManager);\n createCleanupSystem(overlay, observers, eventHandlers);\n};\n\nexport { previewScript };\n"],"names":["previewScript","shouldRun","HIGHLIGHT_PADDING","HIGHLIGHT_HOVER_COLOR","window","STRAPI_HIGHLIGHT_HOVER_COLOR","HIGHLIGHT_ACTIVE_COLOR","STRAPI_HIGHLIGHT_ACTIVE_COLOR","SOURCE_ATTRIBUTE","OVERLAY_ID","INTERNAL_EVENTS","STRAPI_FIELD_FOCUS","STRAPI_FIELD_BLUR","STRAPI_FIELD_CHANGE","STRAPI_FIELD_FOCUS_INTENT","sendMessage","type","payload","parent","postMessage","createOverlaySystem","__strapi_previewCleanup","document","getElementById","remove","overlay","createElement","id","style","cssText","body","appendChild","createHighlightManager","elements","querySelectorAll","eventListeners","highlights","focusedHighlights","focusedField","drawHighlight","target","highlight","rect","getBoundingClientRect","width","height","transform","left","top","updateAllHighlights","forEach","index","element","HTMLElement","mouseEnterHandler","highlightManager","includes","outlineColor","mouseLeaveHandler","doubleClickHandler","sourceAttribute","getAttribute","path","position","right","bottom","mouseDownHandler","event","detail","preventDefault","addEventListener","push","handler","setFocusedField","field","getFocusedField","setupObservers","resizeObserver","ResizeObserver","observe","documentElement","updateOnScroll","scrollableElements","Set","add","parentElement","computedStyle","getComputedStyle","overflow","overflowX","overflowY","setupEventHandlers","handleMessage","data","value","matchingElements","textContent","length","Array","from","indexOf","outlineWidth","messageEventListener","createCleanupSystem","observers","eventHandlers","disconnect","removeEventListener"],"mappings":"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"}
@@ -0,0 +1,294 @@
1
+ // NOTE: This override is for the properties on _user's site_, it's not about Strapi Admin.
2
+ /**
3
+ * previewScript will be injected into the preview iframe after being stringified.
4
+ * Therefore it CANNOT use any imports, or refer to any variables outside of its own scope.
5
+ * It's why many functions are defined within previewScript, it's the only way to avoid going full spaghetti.
6
+ * To get a better overview of everything previewScript does, go to the orchestration part at its end.
7
+ */ const previewScript = (shouldRun = true)=>{
8
+ /* -----------------------------------------------------------------------------------------------
9
+ * Params
10
+ * ---------------------------------------------------------------------------------------------*/ const HIGHLIGHT_PADDING = 2; // in pixels
11
+ const HIGHLIGHT_HOVER_COLOR = window.STRAPI_HIGHLIGHT_HOVER_COLOR ?? '#4945ff'; // dark primary500
12
+ const HIGHLIGHT_ACTIVE_COLOR = window.STRAPI_HIGHLIGHT_ACTIVE_COLOR ?? '#7b79ff'; // dark primary600
13
+ const SOURCE_ATTRIBUTE = 'data-strapi-source';
14
+ const OVERLAY_ID = 'strapi-preview-overlay';
15
+ const INTERNAL_EVENTS = {
16
+ STRAPI_FIELD_FOCUS: 'strapiFieldFocus',
17
+ STRAPI_FIELD_BLUR: 'strapiFieldBlur',
18
+ STRAPI_FIELD_CHANGE: 'strapiFieldChange',
19
+ STRAPI_FIELD_FOCUS_INTENT: 'strapiFieldFocusIntent'
20
+ };
21
+ /**
22
+ * Calling the function in no-run mode lets us retrieve the constants from other files and keep
23
+ * a single source of truth for them. It's the only way to do this because this script can't
24
+ * refer to any variables outside of its own scope, because it's stringified before it's run.
25
+ */ if (!shouldRun) {
26
+ return {
27
+ INTERNAL_EVENTS
28
+ };
29
+ }
30
+ /* -----------------------------------------------------------------------------------------------
31
+ * Utils
32
+ * ---------------------------------------------------------------------------------------------*/ const sendMessage = (type, payload)=>{
33
+ window.parent.postMessage({
34
+ type,
35
+ payload
36
+ }, '*');
37
+ };
38
+ /* -----------------------------------------------------------------------------------------------
39
+ * Functionality pieces
40
+ * ---------------------------------------------------------------------------------------------*/ const createOverlaySystem = ()=>{
41
+ // Clean up before creating a new overlay so we can safely call previewScript multiple times
42
+ window.__strapi_previewCleanup?.();
43
+ document.getElementById(OVERLAY_ID)?.remove();
44
+ const overlay = document.createElement('div');
45
+ overlay.id = OVERLAY_ID;
46
+ overlay.style.cssText = `
47
+ position: fixed;
48
+ top: 0;
49
+ left: 0;
50
+ width: 100%;
51
+ height: 100%;
52
+ pointer-events: none;
53
+ z-index: 9999;
54
+ `;
55
+ window.document.body.appendChild(overlay);
56
+ return overlay;
57
+ };
58
+ const createHighlightManager = (overlay)=>{
59
+ const elements = window.document.querySelectorAll(`[${SOURCE_ATTRIBUTE}]`);
60
+ const eventListeners = [];
61
+ const highlights = [];
62
+ const focusedHighlights = [];
63
+ let focusedField = null;
64
+ const drawHighlight = (target, highlight)=>{
65
+ if (!highlight) return;
66
+ const rect = target.getBoundingClientRect();
67
+ highlight.style.width = `${rect.width + HIGHLIGHT_PADDING * 2}px`;
68
+ highlight.style.height = `${rect.height + HIGHLIGHT_PADDING * 2}px`;
69
+ highlight.style.transform = `translate(${rect.left - HIGHLIGHT_PADDING}px, ${rect.top - HIGHLIGHT_PADDING}px)`;
70
+ };
71
+ const updateAllHighlights = ()=>{
72
+ highlights.forEach((highlight, index)=>{
73
+ const element = elements[index];
74
+ if (element && highlight) {
75
+ drawHighlight(element, highlight);
76
+ }
77
+ });
78
+ };
79
+ elements.forEach((element)=>{
80
+ if (element instanceof HTMLElement) {
81
+ const highlight = document.createElement('div');
82
+ highlight.style.cssText = `
83
+ position: absolute;
84
+ outline: 2px solid transparent;
85
+ pointer-events: none;
86
+ border-radius: 2px;
87
+ background-color: transparent;
88
+ will-change: transform;
89
+ transition: outline-color 0.1s ease-in-out;
90
+ `;
91
+ // Move hover detection to the underlying element
92
+ const mouseEnterHandler = ()=>{
93
+ if (!highlightManager.focusedHighlights.includes(highlight)) {
94
+ highlight.style.outlineColor = HIGHLIGHT_HOVER_COLOR;
95
+ }
96
+ };
97
+ const mouseLeaveHandler = ()=>{
98
+ if (!highlightManager.focusedHighlights.includes(highlight)) {
99
+ highlight.style.outlineColor = 'transparent';
100
+ }
101
+ };
102
+ const doubleClickHandler = ()=>{
103
+ const sourceAttribute = element.getAttribute(SOURCE_ATTRIBUTE);
104
+ if (sourceAttribute) {
105
+ const rect = element.getBoundingClientRect();
106
+ sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT, {
107
+ path: sourceAttribute,
108
+ position: {
109
+ top: rect.top,
110
+ left: rect.left,
111
+ right: rect.right,
112
+ bottom: rect.bottom,
113
+ width: rect.width,
114
+ height: rect.height
115
+ }
116
+ });
117
+ }
118
+ };
119
+ const mouseDownHandler = (event)=>{
120
+ // Prevent default multi click to select behavior
121
+ if (event.detail >= 2) {
122
+ event.preventDefault();
123
+ }
124
+ };
125
+ element.addEventListener('mouseenter', mouseEnterHandler);
126
+ element.addEventListener('mouseleave', mouseLeaveHandler);
127
+ element.addEventListener('dblclick', doubleClickHandler);
128
+ element.addEventListener('mousedown', mouseDownHandler);
129
+ // Store event listeners for cleanup
130
+ eventListeners.push({
131
+ element,
132
+ type: 'mouseenter',
133
+ handler: mouseEnterHandler
134
+ }, {
135
+ element,
136
+ type: 'mouseleave',
137
+ handler: mouseLeaveHandler
138
+ }, {
139
+ element,
140
+ type: 'dblclick',
141
+ handler: doubleClickHandler
142
+ }, {
143
+ element,
144
+ type: 'mousedown',
145
+ handler: mouseDownHandler
146
+ });
147
+ highlights.push(highlight);
148
+ overlay.appendChild(highlight);
149
+ drawHighlight(element, highlight);
150
+ }
151
+ });
152
+ return {
153
+ elements,
154
+ updateAllHighlights,
155
+ eventListeners,
156
+ highlights,
157
+ focusedHighlights,
158
+ setFocusedField: (field)=>{
159
+ focusedField = field;
160
+ },
161
+ getFocusedField: ()=>focusedField
162
+ };
163
+ };
164
+ const setupObservers = (highlightManager)=>{
165
+ const resizeObserver = new ResizeObserver(()=>{
166
+ highlightManager.updateAllHighlights();
167
+ });
168
+ highlightManager.elements.forEach((element)=>{
169
+ resizeObserver.observe(element);
170
+ });
171
+ resizeObserver.observe(document.documentElement);
172
+ const updateOnScroll = ()=>{
173
+ highlightManager.updateAllHighlights();
174
+ };
175
+ const scrollableElements = new Set();
176
+ scrollableElements.add(window);
177
+ // Find all scrollable ancestors for all tracked elements
178
+ highlightManager.elements.forEach((element)=>{
179
+ let parent = element.parentElement;
180
+ while(parent){
181
+ const computedStyle = window.getComputedStyle(parent);
182
+ const overflow = computedStyle.overflow + computedStyle.overflowX + computedStyle.overflowY;
183
+ if (overflow.includes('scroll') || overflow.includes('auto')) {
184
+ scrollableElements.add(parent);
185
+ }
186
+ parent = parent.parentElement;
187
+ }
188
+ });
189
+ // Add scroll listeners to all scrollable elements
190
+ scrollableElements.forEach((element)=>{
191
+ if (element === window) {
192
+ window.addEventListener('scroll', updateOnScroll);
193
+ window.addEventListener('resize', updateOnScroll);
194
+ } else {
195
+ element.addEventListener('scroll', updateOnScroll);
196
+ }
197
+ });
198
+ return {
199
+ resizeObserver,
200
+ updateOnScroll,
201
+ scrollableElements
202
+ };
203
+ };
204
+ const setupEventHandlers = (highlightManager)=>{
205
+ const handleMessage = (event)=>{
206
+ if (!event.data?.type) return;
207
+ // The user typed in an input, reflect the change in the preview
208
+ if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_CHANGE) {
209
+ const { field, value } = event.data.payload;
210
+ if (!field) return;
211
+ const matchingElements = document.querySelectorAll(`[${SOURCE_ATTRIBUTE}="${field}"]`);
212
+ matchingElements.forEach((element)=>{
213
+ if (element instanceof HTMLElement) {
214
+ element.textContent = value || '';
215
+ }
216
+ });
217
+ return;
218
+ }
219
+ // The user focused a new input, update the highlights in the preview
220
+ if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS) {
221
+ const { field } = event.data.payload;
222
+ if (!field) return;
223
+ // Clear existing focused highlights
224
+ highlightManager.focusedHighlights.forEach((highlight)=>{
225
+ highlight.style.outlineColor = 'transparent';
226
+ });
227
+ highlightManager.focusedHighlights.length = 0;
228
+ // Set new focused field and highlight matching elements
229
+ highlightManager.setFocusedField(field);
230
+ const matchingElements = document.querySelectorAll(`[${SOURCE_ATTRIBUTE}="${field}"]`);
231
+ matchingElements.forEach((element)=>{
232
+ const highlight = highlightManager.highlights[Array.from(highlightManager.elements).indexOf(element)];
233
+ if (highlight) {
234
+ highlight.style.outlineColor = HIGHLIGHT_ACTIVE_COLOR;
235
+ highlight.style.outlineWidth = '3px';
236
+ highlightManager.focusedHighlights.push(highlight);
237
+ }
238
+ });
239
+ return;
240
+ }
241
+ // The user is no longer focusing an input, remove the highlights
242
+ if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_BLUR) {
243
+ const { field } = event.data.payload;
244
+ if (field !== highlightManager.getFocusedField()) return;
245
+ highlightManager.focusedHighlights.forEach((highlight)=>{
246
+ highlight.style.outlineColor = 'transparent';
247
+ highlight.style.outlineWidth = '2px';
248
+ });
249
+ highlightManager.focusedHighlights.length = 0;
250
+ highlightManager.setFocusedField(null);
251
+ }
252
+ };
253
+ window.addEventListener('message', handleMessage);
254
+ // Add the message handler to the cleanup list
255
+ const messageEventListener = {
256
+ element: window,
257
+ type: 'message',
258
+ handler: handleMessage
259
+ };
260
+ return [
261
+ ...highlightManager.eventListeners,
262
+ messageEventListener
263
+ ];
264
+ };
265
+ const createCleanupSystem = (overlay, observers, eventHandlers)=>{
266
+ window.__strapi_previewCleanup = ()=>{
267
+ observers.resizeObserver.disconnect();
268
+ // Remove all scroll listeners
269
+ observers.scrollableElements.forEach((element)=>{
270
+ if (element === window) {
271
+ window.removeEventListener('scroll', observers.updateOnScroll);
272
+ window.removeEventListener('resize', observers.updateOnScroll);
273
+ } else {
274
+ element.removeEventListener('scroll', observers.updateOnScroll);
275
+ }
276
+ });
277
+ // Remove highlight event listeners
278
+ eventHandlers.forEach(({ element, type, handler })=>{
279
+ element.removeEventListener(type, handler);
280
+ });
281
+ overlay.remove();
282
+ };
283
+ };
284
+ /* -----------------------------------------------------------------------------------------------
285
+ * Orchestration
286
+ * ---------------------------------------------------------------------------------------------*/ const overlay = createOverlaySystem();
287
+ const highlightManager = createHighlightManager(overlay);
288
+ const observers = setupObservers(highlightManager);
289
+ const eventHandlers = setupEventHandlers(highlightManager);
290
+ createCleanupSystem(overlay, observers, eventHandlers);
291
+ };
292
+
293
+ export { previewScript };
294
+ //# sourceMappingURL=previewScript.mjs.map