@strapi/content-manager 0.0.0-next.330c50cc41f280d03e0fdb875323ab5133aeebf3 → 0.0.0-next.35ca30daa48c41dc5d8fa1d8312557d733c580da
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.
- package/dist/admin/components/ConfigurationForm/Fields.js +4 -1
- package/dist/admin/components/ConfigurationForm/Fields.js.map +1 -1
- package/dist/admin/components/ConfigurationForm/Fields.mjs +5 -2
- package/dist/admin/components/ConfigurationForm/Fields.mjs.map +1 -1
- package/dist/admin/components/ConfigurationForm/Form.js +1 -1
- package/dist/admin/components/ConfigurationForm/Form.js.map +1 -1
- package/dist/admin/components/ConfigurationForm/Form.mjs +3 -3
- package/dist/admin/components/ConfigurationForm/Form.mjs.map +1 -1
- package/dist/admin/components/DragPreviews/CardDragPreview.js +3 -1
- package/dist/admin/components/DragPreviews/CardDragPreview.js.map +1 -1
- package/dist/admin/components/DragPreviews/CardDragPreview.mjs +3 -1
- package/dist/admin/components/DragPreviews/CardDragPreview.mjs.map +1 -1
- package/dist/admin/components/DragPreviews/ComponentDragPreview.js +3 -1
- package/dist/admin/components/DragPreviews/ComponentDragPreview.js.map +1 -1
- package/dist/admin/components/DragPreviews/ComponentDragPreview.mjs +3 -1
- package/dist/admin/components/DragPreviews/ComponentDragPreview.mjs.map +1 -1
- package/dist/admin/components/DragPreviews/RelationDragPreview.js +3 -1
- package/dist/admin/components/DragPreviews/RelationDragPreview.js.map +1 -1
- package/dist/admin/components/DragPreviews/RelationDragPreview.mjs +3 -1
- package/dist/admin/components/DragPreviews/RelationDragPreview.mjs.map +1 -1
- package/dist/admin/components/LeftMenu.js +89 -49
- package/dist/admin/components/LeftMenu.js.map +1 -1
- package/dist/admin/components/LeftMenu.mjs +91 -51
- package/dist/admin/components/LeftMenu.mjs.map +1 -1
- package/dist/admin/components/Widgets.js +4 -2
- package/dist/admin/components/Widgets.js.map +1 -1
- package/dist/admin/components/Widgets.mjs +4 -2
- package/dist/admin/components/Widgets.mjs.map +1 -1
- package/dist/admin/history/components/VersionHeader.js +1 -0
- package/dist/admin/history/components/VersionHeader.js.map +1 -1
- package/dist/admin/history/components/VersionHeader.mjs +1 -0
- package/dist/admin/history/components/VersionHeader.mjs.map +1 -1
- package/dist/admin/history/components/VersionsList.js +1 -1
- package/dist/admin/history/components/VersionsList.js.map +1 -1
- package/dist/admin/history/components/VersionsList.mjs +1 -1
- package/dist/admin/history/components/VersionsList.mjs.map +1 -1
- package/dist/admin/history/pages/History.js +7 -7
- package/dist/admin/history/pages/History.js.map +1 -1
- package/dist/admin/history/pages/History.mjs +7 -7
- package/dist/admin/history/pages/History.mjs.map +1 -1
- package/dist/admin/layout.js +27 -6
- package/dist/admin/layout.js.map +1 -1
- package/dist/admin/layout.mjs +28 -7
- package/dist/admin/layout.mjs.map +1 -1
- package/dist/admin/pages/EditView/EditViewPage.js +19 -22
- package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
- package/dist/admin/pages/EditView/EditViewPage.mjs +20 -23
- package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/Blocker.js +18 -0
- package/dist/admin/pages/EditView/components/Blocker.js.map +1 -0
- package/dist/admin/pages/EditView/components/Blocker.mjs +16 -0
- package/dist/admin/pages/EditView/components/Blocker.mjs.map +1 -0
- package/dist/admin/pages/EditView/components/DocumentActions.js +16 -1
- package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
- package/dist/admin/pages/EditView/components/DocumentActions.mjs +17 -2
- package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.js +2 -2
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.mjs +2 -2
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/EditorLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs +3 -2
- package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js +1 -2
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs +1 -2
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +3 -2
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +2 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +3 -2
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.js +2 -2
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.mjs +2 -2
- package/dist/admin/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.js +13 -8
- package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormLayout.mjs +14 -8
- package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/Header.js +22 -7
- package/dist/admin/pages/EditView/components/Header.js.map +1 -1
- package/dist/admin/pages/EditView/components/Header.mjs +23 -8
- package/dist/admin/pages/EditView/components/Header.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/InputRenderer.js +20 -7
- package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
- package/dist/admin/pages/EditView/components/InputRenderer.mjs +20 -7
- package/dist/admin/pages/EditView/components/InputRenderer.mjs.map +1 -1
- package/dist/admin/pages/EditView/utils/data.js +27 -8
- package/dist/admin/pages/EditView/utils/data.js.map +1 -1
- package/dist/admin/pages/EditView/utils/data.mjs +27 -8
- package/dist/admin/pages/EditView/utils/data.mjs.map +1 -1
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js +1 -0
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.js.map +1 -1
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs +1 -0
- package/dist/admin/pages/ListConfiguration/ListConfigurationPage.mjs.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.js +8 -8
- package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
- package/dist/admin/pages/ListView/ListViewPage.mjs +8 -8
- package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
- package/dist/admin/preview/components/InputPopover.js +189 -0
- package/dist/admin/preview/components/InputPopover.js.map +1 -0
- package/dist/admin/preview/components/InputPopover.mjs +167 -0
- package/dist/admin/preview/components/InputPopover.mjs.map +1 -0
- package/dist/admin/preview/components/PreviewHeader.js +0 -1
- package/dist/admin/preview/components/PreviewHeader.js.map +1 -1
- package/dist/admin/preview/components/PreviewHeader.mjs +0 -1
- package/dist/admin/preview/components/PreviewHeader.mjs.map +1 -1
- package/dist/admin/preview/hooks/usePreviewInputManager.js +77 -0
- package/dist/admin/preview/hooks/usePreviewInputManager.js.map +1 -0
- package/dist/admin/preview/hooks/usePreviewInputManager.mjs +56 -0
- package/dist/admin/preview/hooks/usePreviewInputManager.mjs.map +1 -0
- package/dist/admin/preview/pages/Preview.js +128 -125
- package/dist/admin/preview/pages/Preview.js.map +1 -1
- package/dist/admin/preview/pages/Preview.mjs +128 -125
- package/dist/admin/preview/pages/Preview.mjs.map +1 -1
- package/dist/admin/preview/utils/constants.js +36 -1
- package/dist/admin/preview/utils/constants.js.map +1 -1
- package/dist/admin/preview/utils/constants.mjs +35 -2
- package/dist/admin/preview/utils/constants.mjs.map +1 -1
- package/dist/admin/preview/utils/fieldUtils.js +107 -0
- package/dist/admin/preview/utils/fieldUtils.js.map +1 -0
- package/dist/admin/preview/utils/fieldUtils.mjs +102 -0
- package/dist/admin/preview/utils/fieldUtils.mjs.map +1 -0
- package/dist/admin/preview/utils/getSendMessage.js +22 -0
- package/dist/admin/preview/utils/getSendMessage.js.map +1 -0
- package/dist/admin/preview/utils/getSendMessage.mjs +20 -0
- package/dist/admin/preview/utils/getSendMessage.mjs.map +1 -0
- package/dist/admin/preview/utils/previewScript.js +423 -92
- package/dist/admin/preview/utils/previewScript.js.map +1 -1
- package/dist/admin/preview/utils/previewScript.mjs +423 -92
- package/dist/admin/preview/utils/previewScript.mjs.map +1 -1
- package/dist/admin/services/documents.js +0 -1
- package/dist/admin/services/documents.js.map +1 -1
- package/dist/admin/services/documents.mjs +0 -1
- package/dist/admin/services/documents.mjs.map +1 -1
- package/dist/admin/src/components/LeftMenu.d.ts +3 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/Blocker.d.ts +5 -0
- package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +0 -3
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +1 -1
- package/dist/admin/src/preview/components/InputPopover.d.ts +6 -0
- package/dist/admin/src/preview/hooks/usePreviewInputManager.d.ts +5 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +12 -0
- package/dist/admin/src/preview/services/preview.d.ts +1 -1
- package/dist/admin/src/preview/utils/constants.d.ts +39 -1
- package/dist/admin/src/preview/utils/fieldUtils.d.ts +22 -0
- package/dist/admin/src/preview/utils/getSendMessage.d.ts +11 -0
- package/dist/admin/src/preview/utils/previewScript.d.ts +7 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +16 -16
- package/dist/admin/src/services/homepage.d.ts +1 -1
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/translations/en.json.js +6 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +6 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/translations/es.json.js +1 -0
- package/dist/admin/translations/es.json.js.map +1 -1
- package/dist/admin/translations/es.json.mjs +1 -0
- package/dist/admin/translations/es.json.mjs.map +1 -1
- package/dist/admin/translations/fr.json.js +1 -0
- package/dist/admin/translations/fr.json.js.map +1 -1
- package/dist/admin/translations/fr.json.mjs +1 -0
- package/dist/admin/translations/fr.json.mjs.map +1 -1
- package/dist/server/controllers/relations.js +6 -4
- package/dist/server/controllers/relations.js.map +1 -1
- package/dist/server/controllers/relations.mjs +6 -4
- package/dist/server/controllers/relations.mjs.map +1 -1
- package/dist/server/homepage/services/homepage.js +1 -1
- package/dist/server/homepage/services/homepage.js.map +1 -1
- package/dist/server/homepage/services/homepage.mjs +1 -1
- package/dist/server/homepage/services/homepage.mjs.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/homepage/services/homepage.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -11,10 +11,18 @@
|
|
|
11
11
|
* Params
|
|
12
12
|
* ---------------------------------------------------------------------------------------------*/ const HIGHLIGHT_PADDING = 2; // in pixels
|
|
13
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 HIGHLIGHT_STYLES_ID = 'strapi-preview-highlight-styles';
|
|
16
|
+
const DOUBLE_CLICK_TIMEOUT = 300; // milliseconds to wait for potential double-click
|
|
17
|
+
const DISABLE_STEGA_DECODING = window.STRAPI_DISABLE_STEGA_DECODING ?? false;
|
|
14
18
|
const SOURCE_ATTRIBUTE = 'data-strapi-source';
|
|
15
19
|
const OVERLAY_ID = 'strapi-preview-overlay';
|
|
16
20
|
const INTERNAL_EVENTS = {
|
|
17
|
-
|
|
21
|
+
STRAPI_FIELD_FOCUS: 'strapiFieldFocus',
|
|
22
|
+
STRAPI_FIELD_BLUR: 'strapiFieldBlur',
|
|
23
|
+
STRAPI_FIELD_CHANGE: 'strapiFieldChange',
|
|
24
|
+
STRAPI_FIELD_FOCUS_INTENT: 'strapiFieldFocusIntent',
|
|
25
|
+
STRAPI_FIELD_SINGLE_CLICK_HINT: 'strapiFieldSingleClickHint'
|
|
18
26
|
};
|
|
19
27
|
/**
|
|
20
28
|
* Calling the function in no-run mode lets us retrieve the constants from other files and keep
|
|
@@ -26,8 +34,111 @@
|
|
|
26
34
|
};
|
|
27
35
|
}
|
|
28
36
|
/* -----------------------------------------------------------------------------------------------
|
|
37
|
+
* Utils
|
|
38
|
+
* ---------------------------------------------------------------------------------------------*/ const sendMessage = (type, payload)=>{
|
|
39
|
+
window.parent.postMessage({
|
|
40
|
+
type,
|
|
41
|
+
payload
|
|
42
|
+
}, '*');
|
|
43
|
+
};
|
|
44
|
+
const getElementsByPath = (path)=>{
|
|
45
|
+
return document.querySelectorAll(`[${SOURCE_ATTRIBUTE}*="path=${path}"]`);
|
|
46
|
+
};
|
|
47
|
+
/* -----------------------------------------------------------------------------------------------
|
|
29
48
|
* Functionality pieces
|
|
30
|
-
* ---------------------------------------------------------------------------------------------*/ const
|
|
49
|
+
* ---------------------------------------------------------------------------------------------*/ const setupStegaDOMObserver = async ()=>{
|
|
50
|
+
if (DISABLE_STEGA_DECODING) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const { vercelStegaDecode: stegaDecode, vercelStegaClean: stegaClean } = await import(// @ts-expect-error it's not a local dependency
|
|
54
|
+
// eslint-disable-next-line import/no-unresolved
|
|
55
|
+
'https://cdn.jsdelivr.net/npm/@vercel/stega@0.1.2/+esm');
|
|
56
|
+
const applyStegaToElement = (element)=>{
|
|
57
|
+
const directTextNodes = Array.from(element.childNodes).filter((node)=>node.nodeType === Node.TEXT_NODE);
|
|
58
|
+
const directTextContent = directTextNodes.map((node)=>node.textContent || '').join('');
|
|
59
|
+
if (directTextContent) {
|
|
60
|
+
try {
|
|
61
|
+
// TODO: check if we can call split instead of decode+clean
|
|
62
|
+
const result = stegaDecode(directTextContent);
|
|
63
|
+
if (result && 'strapiSource' in result) {
|
|
64
|
+
element.setAttribute(SOURCE_ATTRIBUTE, result.strapiSource);
|
|
65
|
+
// Remove encoded part from DOM text content (to avoid breaking links for example)
|
|
66
|
+
directTextNodes.forEach((node)=>{
|
|
67
|
+
if (node.textContent) {
|
|
68
|
+
const cleanedText = stegaClean(node.textContent);
|
|
69
|
+
if (cleanedText !== node.textContent) {
|
|
70
|
+
node.textContent = cleanedText;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
// Process all existing elements
|
|
79
|
+
const allElements = document.querySelectorAll('*');
|
|
80
|
+
Array.from(allElements).forEach(applyStegaToElement);
|
|
81
|
+
// Create observer for new elements and text changes
|
|
82
|
+
const observer = new MutationObserver((mutations)=>{
|
|
83
|
+
mutations.forEach((mutation)=>{
|
|
84
|
+
// Handle added nodes
|
|
85
|
+
if (mutation.type === 'childList') {
|
|
86
|
+
mutation.addedNodes.forEach((node)=>{
|
|
87
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
88
|
+
const element = node;
|
|
89
|
+
// Process the added element
|
|
90
|
+
applyStegaToElement(element);
|
|
91
|
+
// Process all child elements
|
|
92
|
+
const childElements = element.querySelectorAll('*');
|
|
93
|
+
Array.from(childElements).forEach(applyStegaToElement);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Handle text content changes
|
|
98
|
+
if (mutation.type === 'characterData' && mutation.target.parentElement) {
|
|
99
|
+
applyStegaToElement(mutation.target.parentElement);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
observer.observe(document, {
|
|
104
|
+
childList: true,
|
|
105
|
+
subtree: true,
|
|
106
|
+
characterData: true
|
|
107
|
+
});
|
|
108
|
+
return observer;
|
|
109
|
+
};
|
|
110
|
+
const createHighlightStyles = ()=>{
|
|
111
|
+
const existingStyles = document.getElementById(HIGHLIGHT_STYLES_ID);
|
|
112
|
+
// Remove existing styles to avoid duplicates
|
|
113
|
+
if (existingStyles) {
|
|
114
|
+
existingStyles.remove();
|
|
115
|
+
}
|
|
116
|
+
const styleElement = document.createElement('style');
|
|
117
|
+
styleElement.id = HIGHLIGHT_STYLES_ID;
|
|
118
|
+
styleElement.textContent = `
|
|
119
|
+
.strapi-highlight {
|
|
120
|
+
position: absolute;
|
|
121
|
+
outline: 2px solid transparent;
|
|
122
|
+
pointer-events: auto;
|
|
123
|
+
border-radius: 2px;
|
|
124
|
+
background-color: transparent;
|
|
125
|
+
will-change: transform;
|
|
126
|
+
transition: outline-color 0.1s ease-in-out;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.strapi-highlight:hover {
|
|
130
|
+
outline-color: ${HIGHLIGHT_HOVER_COLOR} !important;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.strapi-highlight.strapi-highlight-focused {
|
|
134
|
+
outline-color: ${HIGHLIGHT_ACTIVE_COLOR} !important;
|
|
135
|
+
outline-width: 3px !important;
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
document.head.appendChild(styleElement);
|
|
139
|
+
return styleElement;
|
|
140
|
+
};
|
|
141
|
+
const createOverlaySystem = ()=>{
|
|
31
142
|
// Clean up before creating a new overlay so we can safely call previewScript multiple times
|
|
32
143
|
window.__strapi_previewCleanup?.();
|
|
33
144
|
document.getElementById(OVERLAY_ID)?.remove();
|
|
@@ -46,9 +157,11 @@
|
|
|
46
157
|
return overlay;
|
|
47
158
|
};
|
|
48
159
|
const createHighlightManager = (overlay)=>{
|
|
49
|
-
const
|
|
50
|
-
const highlights = [];
|
|
160
|
+
const elementsToHighlight = new Map();
|
|
51
161
|
const eventListeners = [];
|
|
162
|
+
const focusedHighlights = [];
|
|
163
|
+
const pendingClicks = new Map(); // number is timeout id
|
|
164
|
+
let focusedField = null;
|
|
52
165
|
const drawHighlight = (target, highlight)=>{
|
|
53
166
|
if (!highlight) return;
|
|
54
167
|
const rect = target.getBoundingClientRect();
|
|
@@ -57,90 +170,169 @@
|
|
|
57
170
|
highlight.style.transform = `translate(${rect.left - HIGHLIGHT_PADDING}px, ${rect.top - HIGHLIGHT_PADDING}px)`;
|
|
58
171
|
};
|
|
59
172
|
const updateAllHighlights = ()=>{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
173
|
+
elementsToHighlight.forEach((highlight, element)=>{
|
|
174
|
+
drawHighlight(element, highlight);
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
const createHighlightForElement = (element)=>{
|
|
178
|
+
if (elementsToHighlight.has(element)) {
|
|
179
|
+
// Already has a highlight
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const highlight = document.createElement('div');
|
|
183
|
+
highlight.className = 'strapi-highlight';
|
|
184
|
+
const clickHandler = (event)=>{
|
|
185
|
+
// Skip if this is a re-dispatched event from our delayed handler to avoid infinite loops
|
|
186
|
+
if (event.__strapi_redispatched) {
|
|
187
|
+
return;
|
|
64
188
|
}
|
|
189
|
+
// Prevent the immediate action for interactive elements
|
|
190
|
+
event.preventDefault();
|
|
191
|
+
event.stopPropagation();
|
|
192
|
+
// Clear any existing timeout for this element
|
|
193
|
+
const existingTimeout = pendingClicks.get(element);
|
|
194
|
+
if (existingTimeout) {
|
|
195
|
+
window.clearTimeout(existingTimeout);
|
|
196
|
+
pendingClicks.delete(element);
|
|
197
|
+
}
|
|
198
|
+
// Set up a delayed single-click handler
|
|
199
|
+
const timeout = window.setTimeout(()=>{
|
|
200
|
+
pendingClicks.delete(element);
|
|
201
|
+
// Send single-click hint notification
|
|
202
|
+
sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_SINGLE_CLICK_HINT, null);
|
|
203
|
+
// Re-trigger the click on the underlying element after the double-click timeout
|
|
204
|
+
// Create a new event to dispatch with a marker to prevent re-handling
|
|
205
|
+
const newEvent = new MouseEvent('click', {
|
|
206
|
+
bubbles: true,
|
|
207
|
+
cancelable: true,
|
|
208
|
+
view: window,
|
|
209
|
+
detail: 1,
|
|
210
|
+
button: event.button,
|
|
211
|
+
buttons: event.buttons,
|
|
212
|
+
clientX: event.clientX,
|
|
213
|
+
clientY: event.clientY,
|
|
214
|
+
ctrlKey: event.ctrlKey,
|
|
215
|
+
altKey: event.altKey,
|
|
216
|
+
shiftKey: event.shiftKey,
|
|
217
|
+
metaKey: event.metaKey
|
|
218
|
+
});
|
|
219
|
+
newEvent.__strapi_redispatched = true;
|
|
220
|
+
element.dispatchEvent(newEvent);
|
|
221
|
+
}, DOUBLE_CLICK_TIMEOUT);
|
|
222
|
+
pendingClicks.set(element, timeout);
|
|
223
|
+
};
|
|
224
|
+
const doubleClickHandler = (event)=>{
|
|
225
|
+
// Prevent the default behavior on double-click
|
|
226
|
+
event.preventDefault();
|
|
227
|
+
event.stopPropagation();
|
|
228
|
+
// Clear any pending single-click action
|
|
229
|
+
const existingTimeout = pendingClicks.get(element);
|
|
230
|
+
if (existingTimeout) {
|
|
231
|
+
clearTimeout(existingTimeout);
|
|
232
|
+
pendingClicks.delete(element);
|
|
233
|
+
}
|
|
234
|
+
const sourceAttribute = element.getAttribute(SOURCE_ATTRIBUTE);
|
|
235
|
+
if (sourceAttribute) {
|
|
236
|
+
const rect = element.getBoundingClientRect();
|
|
237
|
+
sendMessage(INTERNAL_EVENTS.STRAPI_FIELD_FOCUS_INTENT, {
|
|
238
|
+
path: sourceAttribute,
|
|
239
|
+
position: {
|
|
240
|
+
top: rect.top,
|
|
241
|
+
left: rect.left,
|
|
242
|
+
right: rect.right,
|
|
243
|
+
bottom: rect.bottom,
|
|
244
|
+
width: rect.width,
|
|
245
|
+
height: rect.height
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const mouseDownHandler = (event)=>{
|
|
251
|
+
// Prevent default multi click to select behavior
|
|
252
|
+
if (event.detail >= 2) {
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
highlight.addEventListener('click', clickHandler);
|
|
257
|
+
highlight.addEventListener('dblclick', doubleClickHandler);
|
|
258
|
+
highlight.addEventListener('mousedown', mouseDownHandler);
|
|
259
|
+
// Store event listeners for cleanup
|
|
260
|
+
eventListeners.push({
|
|
261
|
+
element: highlight,
|
|
262
|
+
type: 'click',
|
|
263
|
+
handler: clickHandler
|
|
264
|
+
}, {
|
|
265
|
+
element: highlight,
|
|
266
|
+
type: 'dblclick',
|
|
267
|
+
handler: doubleClickHandler
|
|
268
|
+
}, {
|
|
269
|
+
element: highlight,
|
|
270
|
+
type: 'mousedown',
|
|
271
|
+
handler: mouseDownHandler
|
|
272
|
+
});
|
|
273
|
+
elementsToHighlight.set(element, highlight);
|
|
274
|
+
overlay.appendChild(highlight);
|
|
275
|
+
drawHighlight(element, highlight);
|
|
276
|
+
};
|
|
277
|
+
const removeHighlightForElement = (element)=>{
|
|
278
|
+
const highlight = elementsToHighlight.get(element);
|
|
279
|
+
if (!highlight) return;
|
|
280
|
+
// Clear any pending click timeout for this element
|
|
281
|
+
const pendingTimeout = pendingClicks.get(element);
|
|
282
|
+
if (pendingTimeout) {
|
|
283
|
+
window.clearTimeout(pendingTimeout);
|
|
284
|
+
pendingClicks.delete(element);
|
|
285
|
+
}
|
|
286
|
+
highlight.remove();
|
|
287
|
+
elementsToHighlight.delete(element);
|
|
288
|
+
// Remove event listeners for this highlight
|
|
289
|
+
const listenersToRemove = eventListeners.filter((listener)=>listener.element === highlight);
|
|
290
|
+
listenersToRemove.forEach(({ element, type, handler })=>{
|
|
291
|
+
element.removeEventListener(type, handler);
|
|
65
292
|
});
|
|
293
|
+
// Mutate eventListeners to remove listeners for this highlight
|
|
294
|
+
eventListeners.splice(0, eventListeners.length, ...eventListeners.filter((listener)=>listener.element !== highlight));
|
|
66
295
|
};
|
|
67
|
-
elements
|
|
296
|
+
// Process all existing elements with source attributes
|
|
297
|
+
const initialElements = window.document.querySelectorAll(`[${SOURCE_ATTRIBUTE}]`);
|
|
298
|
+
Array.from(initialElements).forEach((element)=>{
|
|
68
299
|
if (element instanceof HTMLElement) {
|
|
69
|
-
|
|
70
|
-
highlight.style.cssText = `
|
|
71
|
-
position: absolute;
|
|
72
|
-
outline: 2px solid transparent;
|
|
73
|
-
pointer-events: none;
|
|
74
|
-
border-radius: 2px;
|
|
75
|
-
background-color: transparent;
|
|
76
|
-
will-change: transform;
|
|
77
|
-
transition: outline-color 0.1s ease-in-out;
|
|
78
|
-
`;
|
|
79
|
-
// Move hover detection to the underlying element
|
|
80
|
-
const mouseEnterHandler = ()=>{
|
|
81
|
-
highlight.style.outlineColor = HIGHLIGHT_HOVER_COLOR;
|
|
82
|
-
};
|
|
83
|
-
const mouseLeaveHandler = ()=>{
|
|
84
|
-
highlight.style.outlineColor = 'transparent';
|
|
85
|
-
};
|
|
86
|
-
const doubleClickHandler = ()=>{
|
|
87
|
-
// TODO: handle for real
|
|
88
|
-
// eslint-disable-next-line no-console
|
|
89
|
-
console.log('Double click on highlight', element);
|
|
90
|
-
};
|
|
91
|
-
const mouseDownHandler = (event)=>{
|
|
92
|
-
// Prevent default multi click to select behavior
|
|
93
|
-
if (event.detail >= 2) {
|
|
94
|
-
event.preventDefault();
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
element.addEventListener('mouseenter', mouseEnterHandler);
|
|
98
|
-
element.addEventListener('mouseleave', mouseLeaveHandler);
|
|
99
|
-
element.addEventListener('dblclick', doubleClickHandler);
|
|
100
|
-
element.addEventListener('mousedown', mouseDownHandler);
|
|
101
|
-
// Store event listeners for cleanup
|
|
102
|
-
eventListeners.push({
|
|
103
|
-
element,
|
|
104
|
-
type: 'mouseenter',
|
|
105
|
-
handler: mouseEnterHandler
|
|
106
|
-
}, {
|
|
107
|
-
element,
|
|
108
|
-
type: 'mouseleave',
|
|
109
|
-
handler: mouseLeaveHandler
|
|
110
|
-
}, {
|
|
111
|
-
element,
|
|
112
|
-
type: 'dblclick',
|
|
113
|
-
handler: doubleClickHandler
|
|
114
|
-
}, {
|
|
115
|
-
element,
|
|
116
|
-
type: 'mousedown',
|
|
117
|
-
handler: mouseDownHandler
|
|
118
|
-
});
|
|
119
|
-
highlights.push(highlight);
|
|
120
|
-
overlay.appendChild(highlight);
|
|
121
|
-
drawHighlight(element, highlight);
|
|
300
|
+
createHighlightForElement(element);
|
|
122
301
|
}
|
|
123
302
|
});
|
|
124
303
|
return {
|
|
125
|
-
elements
|
|
304
|
+
get elements () {
|
|
305
|
+
return Array.from(elementsToHighlight.keys());
|
|
306
|
+
},
|
|
307
|
+
get highlights () {
|
|
308
|
+
return Array.from(elementsToHighlight.values());
|
|
309
|
+
},
|
|
126
310
|
updateAllHighlights,
|
|
127
|
-
eventListeners
|
|
311
|
+
eventListeners,
|
|
312
|
+
focusedHighlights,
|
|
313
|
+
createHighlightForElement,
|
|
314
|
+
removeHighlightForElement,
|
|
315
|
+
setFocusedField: (field)=>{
|
|
316
|
+
focusedField = field;
|
|
317
|
+
},
|
|
318
|
+
getFocusedField: ()=>focusedField,
|
|
319
|
+
clearAllPendingClicks: ()=>{
|
|
320
|
+
pendingClicks.forEach((timeout)=>clearTimeout(timeout));
|
|
321
|
+
pendingClicks.clear();
|
|
322
|
+
}
|
|
128
323
|
};
|
|
129
324
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
resizeObserver.observe(element);
|
|
136
|
-
});
|
|
137
|
-
resizeObserver.observe(document.documentElement);
|
|
325
|
+
/**
|
|
326
|
+
* We need to track scroll in all the element parents in order to keep the highlight position
|
|
327
|
+
* in sync with the element position. Listening to window scroll is not enough because the
|
|
328
|
+
* element can be inside one or more scrollable containers.
|
|
329
|
+
*/ const setupScrollManagement = (highlightManager)=>{
|
|
138
330
|
const updateOnScroll = ()=>{
|
|
139
331
|
highlightManager.updateAllHighlights();
|
|
140
332
|
};
|
|
141
333
|
const scrollableElements = new Set();
|
|
142
334
|
scrollableElements.add(window);
|
|
143
|
-
// Find all scrollable ancestors for all tracked elements
|
|
335
|
+
// Find all scrollable ancestors for all tracked elements and set up scroll listeners
|
|
144
336
|
highlightManager.elements.forEach((element)=>{
|
|
145
337
|
let parent = element.parentElement;
|
|
146
338
|
while(parent){
|
|
@@ -161,42 +353,181 @@
|
|
|
161
353
|
element.addEventListener('scroll', updateOnScroll);
|
|
162
354
|
}
|
|
163
355
|
});
|
|
356
|
+
const cleanup = ()=>{
|
|
357
|
+
scrollableElements.forEach((element)=>{
|
|
358
|
+
if (element === window) {
|
|
359
|
+
window.removeEventListener('scroll', updateOnScroll);
|
|
360
|
+
window.removeEventListener('resize', updateOnScroll);
|
|
361
|
+
} else {
|
|
362
|
+
element.removeEventListener('scroll', updateOnScroll);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
return {
|
|
367
|
+
cleanup
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
const setupObservers = (highlightManager, stegaObserver)=>{
|
|
371
|
+
const resizeObserver = new ResizeObserver(()=>{
|
|
372
|
+
highlightManager.updateAllHighlights();
|
|
373
|
+
});
|
|
374
|
+
const observeElementForResize = (element)=>{
|
|
375
|
+
resizeObserver.observe(element);
|
|
376
|
+
};
|
|
377
|
+
// Observe existing elements
|
|
378
|
+
highlightManager.elements.forEach(observeElementForResize);
|
|
379
|
+
resizeObserver.observe(document.documentElement);
|
|
380
|
+
// Create highlight observer to watch for new elements with source attributes
|
|
381
|
+
const highlightObserver = new MutationObserver((mutations)=>{
|
|
382
|
+
mutations.forEach((mutation)=>{
|
|
383
|
+
if (mutation.type === 'attributes' && mutation.attributeName === SOURCE_ATTRIBUTE) {
|
|
384
|
+
const target = mutation.target;
|
|
385
|
+
if (target.hasAttribute(SOURCE_ATTRIBUTE)) {
|
|
386
|
+
highlightManager.createHighlightForElement(target);
|
|
387
|
+
observeElementForResize(target);
|
|
388
|
+
} else {
|
|
389
|
+
highlightManager.removeHighlightForElement(target);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (mutation.type === 'childList') {
|
|
393
|
+
mutation.addedNodes.forEach((node)=>{
|
|
394
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
395
|
+
const element = node;
|
|
396
|
+
// Check if the added element has source attribute
|
|
397
|
+
if (element.hasAttribute(SOURCE_ATTRIBUTE) && element instanceof HTMLElement) {
|
|
398
|
+
highlightManager.createHighlightForElement(element);
|
|
399
|
+
observeElementForResize(element);
|
|
400
|
+
}
|
|
401
|
+
// Check all child elements for source attributes
|
|
402
|
+
const elementsWithSource = element.querySelectorAll(`[${SOURCE_ATTRIBUTE}]`);
|
|
403
|
+
Array.from(elementsWithSource).forEach((childElement)=>{
|
|
404
|
+
if (childElement instanceof HTMLElement) {
|
|
405
|
+
highlightManager.createHighlightForElement(childElement);
|
|
406
|
+
observeElementForResize(childElement);
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
mutation.removedNodes.forEach((node)=>{
|
|
412
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
413
|
+
const element = node;
|
|
414
|
+
highlightManager.removeHighlightForElement(element);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
highlightObserver.observe(document, {
|
|
421
|
+
childList: true,
|
|
422
|
+
subtree: true,
|
|
423
|
+
attributes: true,
|
|
424
|
+
attributeFilter: [
|
|
425
|
+
SOURCE_ATTRIBUTE
|
|
426
|
+
]
|
|
427
|
+
});
|
|
164
428
|
return {
|
|
165
429
|
resizeObserver,
|
|
166
|
-
|
|
167
|
-
|
|
430
|
+
highlightObserver,
|
|
431
|
+
stegaObserver
|
|
168
432
|
};
|
|
169
433
|
};
|
|
170
434
|
const setupEventHandlers = (highlightManager)=>{
|
|
171
|
-
|
|
172
|
-
|
|
435
|
+
const handleMessage = (event)=>{
|
|
436
|
+
if (!event.data?.type) return;
|
|
437
|
+
// The user typed in an input, reflect the change in the preview
|
|
438
|
+
if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_CHANGE) {
|
|
439
|
+
const { field, value } = event.data.payload;
|
|
440
|
+
if (!field) return;
|
|
441
|
+
getElementsByPath(field).forEach((element)=>{
|
|
442
|
+
if (element instanceof HTMLElement) {
|
|
443
|
+
element.textContent = value || '';
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
// Update highlight dimensions since the new text content may affect them
|
|
447
|
+
highlightManager.updateAllHighlights();
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
// The user focused a new input, update the highlights in the preview
|
|
451
|
+
if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_FOCUS) {
|
|
452
|
+
const { field } = event.data.payload;
|
|
453
|
+
if (!field) return;
|
|
454
|
+
// Clear existing focused highlights
|
|
455
|
+
highlightManager.focusedHighlights.forEach((highlight)=>{
|
|
456
|
+
highlight.classList.remove('strapi-highlight-focused');
|
|
457
|
+
});
|
|
458
|
+
highlightManager.focusedHighlights.length = 0;
|
|
459
|
+
// Set new focused field and highlight matching elements
|
|
460
|
+
highlightManager.setFocusedField(field);
|
|
461
|
+
getElementsByPath(field).forEach((element, index)=>{
|
|
462
|
+
if (index === 0) {
|
|
463
|
+
element.scrollIntoView({
|
|
464
|
+
behavior: 'smooth',
|
|
465
|
+
block: 'center'
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
const highlight = highlightManager.highlights[Array.from(highlightManager.elements).indexOf(element)];
|
|
469
|
+
if (highlight) {
|
|
470
|
+
highlight.classList.add('strapi-highlight-focused');
|
|
471
|
+
highlightManager.focusedHighlights.push(highlight);
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
// The user is no longer focusing an input, remove the highlights
|
|
477
|
+
if (event.data.type === INTERNAL_EVENTS.STRAPI_FIELD_BLUR) {
|
|
478
|
+
const { field } = event.data.payload;
|
|
479
|
+
if (field !== highlightManager.getFocusedField()) return;
|
|
480
|
+
highlightManager.focusedHighlights.forEach((highlight)=>{
|
|
481
|
+
highlight.classList.remove('strapi-highlight-focused');
|
|
482
|
+
});
|
|
483
|
+
highlightManager.focusedHighlights.length = 0;
|
|
484
|
+
highlightManager.setFocusedField(null);
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
window.addEventListener('message', handleMessage);
|
|
488
|
+
// Add the message handler to the cleanup list
|
|
489
|
+
const messageEventListener = {
|
|
490
|
+
element: window,
|
|
491
|
+
type: 'message',
|
|
492
|
+
handler: handleMessage
|
|
493
|
+
};
|
|
494
|
+
return [
|
|
495
|
+
...highlightManager.eventListeners,
|
|
496
|
+
messageEventListener
|
|
497
|
+
];
|
|
173
498
|
};
|
|
174
|
-
const createCleanupSystem = (overlay, observers, eventHandlers)=>{
|
|
499
|
+
const createCleanupSystem = (overlay, observers, scrollManager, eventHandlers, highlightManager)=>{
|
|
175
500
|
window.__strapi_previewCleanup = ()=>{
|
|
176
501
|
observers.resizeObserver.disconnect();
|
|
177
|
-
|
|
178
|
-
observers.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
element.removeEventListener('scroll', observers.updateOnScroll);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
502
|
+
observers.highlightObserver.disconnect();
|
|
503
|
+
observers.stegaObserver?.disconnect();
|
|
504
|
+
// Clean up scroll listeners
|
|
505
|
+
scrollManager.cleanup();
|
|
506
|
+
// Clear all pending click timeouts
|
|
507
|
+
highlightManager.clearAllPendingClicks();
|
|
186
508
|
// Remove highlight event listeners
|
|
187
509
|
eventHandlers.forEach(({ element, type, handler })=>{
|
|
188
510
|
element.removeEventListener(type, handler);
|
|
189
511
|
});
|
|
512
|
+
// Clean up CSS styles
|
|
513
|
+
const existingStyles = document.getElementById(HIGHLIGHT_STYLES_ID);
|
|
514
|
+
if (existingStyles) {
|
|
515
|
+
existingStyles.remove();
|
|
516
|
+
}
|
|
190
517
|
overlay.remove();
|
|
191
518
|
};
|
|
192
519
|
};
|
|
193
520
|
/* -----------------------------------------------------------------------------------------------
|
|
194
521
|
* Orchestration
|
|
195
|
-
* ---------------------------------------------------------------------------------------------*/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
522
|
+
* ---------------------------------------------------------------------------------------------*/ setupStegaDOMObserver().then((stegaObserver)=>{
|
|
523
|
+
createHighlightStyles();
|
|
524
|
+
const overlay = createOverlaySystem();
|
|
525
|
+
const highlightManager = createHighlightManager(overlay);
|
|
526
|
+
const observers = setupObservers(highlightManager, stegaObserver);
|
|
527
|
+
const scrollManager = setupScrollManagement(highlightManager);
|
|
528
|
+
const eventHandlers = setupEventHandlers(highlightManager);
|
|
529
|
+
createCleanupSystem(overlay, observers, scrollManager, eventHandlers, highlightManager);
|
|
530
|
+
});
|
|
200
531
|
};
|
|
201
532
|
|
|
202
533
|
exports.previewScript = previewScript;
|