@capillarytech/creatives-library 8.0.254 → 8.0.255-alpha.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.
- package/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +2 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/services/api.js +10 -0
- package/services/tests/api.test.js +34 -0
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +28 -5
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/v2Components/CapDeviceContent/index.js +61 -56
- package/v2Components/CapTagList/index.js +6 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
- package/v2Components/ErrorInfoNote/constants.js +1 -0
- package/v2Components/ErrorInfoNote/index.js +457 -72
- package/v2Components/ErrorInfoNote/messages.js +36 -6
- package/v2Components/ErrorInfoNote/style.scss +282 -6
- package/v2Components/FormBuilder/tests/index.test.js +13 -4
- package/v2Components/HtmlEditor/HTMLEditor.js +547 -94
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1358 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
- package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
- package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +22 -101
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +149 -140
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +24 -34
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
- package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +50 -34
- package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +70 -41
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +364 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +42 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +794 -0
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +95 -85
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
- package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
- package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
- package/v2Components/HtmlEditor/utils/validationConstants.js +40 -0
- package/v2Components/MobilePushPreviewV2/index.js +32 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
- package/v2Containers/BeeEditor/index.js +172 -90
- package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +194 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +128 -51
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +239 -46
- package/v2Containers/CreativesContainer/messages.js +8 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +234 -29
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +61 -7
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/Email/tests/reducer.test.js +46 -0
- package/v2Containers/Email/tests/sagas.test.js +320 -29
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1285 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +207 -19
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1870 -0
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
- package/v2Containers/EmailWrapper/index.js +103 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
- package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
- package/v2Containers/InApp/actions.js +7 -0
- package/v2Containers/InApp/constants.js +20 -4
- package/v2Containers/InApp/index.js +802 -359
- package/v2Containers/InApp/index.scss +4 -3
- package/v2Containers/InApp/messages.js +7 -3
- package/v2Containers/InApp/reducer.js +21 -3
- package/v2Containers/InApp/sagas.js +29 -9
- package/v2Containers/InApp/selectors.js +25 -5
- package/v2Containers/InApp/tests/index.test.js +154 -50
- package/v2Containers/InApp/tests/reducer.test.js +34 -0
- package/v2Containers/InApp/tests/sagas.test.js +61 -9
- package/v2Containers/InApp/tests/selectors.test.js +612 -0
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
- package/v2Containers/InAppWrapper/constants.js +16 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
- package/v2Containers/InAppWrapper/index.js +148 -0
- package/v2Containers/InAppWrapper/messages.js +49 -0
- package/v2Containers/InappAdvance/index.js +1099 -0
- package/v2Containers/InappAdvance/index.scss +10 -0
- package/v2Containers/InappAdvance/tests/index.test.js +448 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
- package/v2Containers/TagList/index.js +62 -19
- package/v2Containers/Templates/_templates.scss +60 -1
- package/v2Containers/Templates/index.js +89 -4
- package/v2Containers/Templates/messages.js +4 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
|
@@ -8,33 +8,44 @@
|
|
|
8
8
|
* - Theme support with proper styling
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import React, {
|
|
11
|
+
import React, {
|
|
12
|
+
forwardRef, useImperativeHandle, useRef, useEffect, useCallback,
|
|
13
|
+
} from 'react';
|
|
12
14
|
import PropTypes from 'prop-types';
|
|
13
15
|
|
|
14
16
|
// CodeMirror 6 imports
|
|
15
17
|
import { EditorState } from '@codemirror/state';
|
|
16
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
EditorView, lineNumbers, highlightActiveLine, placeholder,
|
|
20
|
+
} from '@codemirror/view';
|
|
17
21
|
|
|
18
|
-
//
|
|
19
|
-
import { createRobustExtensions } from '../../utils/properSyntaxHighlighting';
|
|
22
|
+
// Define Theme and Highlighting inline to avoid "multiple instances of @codemirror/state" error
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
import { injectIntl, intlShape } from 'react-intl';
|
|
23
26
|
|
|
24
27
|
// Messages
|
|
28
|
+
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
29
|
+
import { createRobustExtensions } from '../../utils/properSyntaxHighlighting';
|
|
25
30
|
import messages from '../../messages';
|
|
26
31
|
|
|
27
32
|
// Cap UI Components
|
|
28
|
-
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
29
33
|
|
|
30
34
|
// Components
|
|
31
35
|
import TagList from '../../../../v2Containers/TagList';
|
|
36
|
+
import ValidationErrorDisplay from '../ValidationErrorDisplay';
|
|
37
|
+
|
|
38
|
+
// Constants - removed unused imports since tag fetching is handled by parent
|
|
32
39
|
|
|
33
40
|
// Context
|
|
34
41
|
import { useEditorContext } from '../common/EditorContext';
|
|
35
42
|
|
|
36
43
|
// Styles
|
|
37
44
|
import './_codeEditorPane.scss';
|
|
45
|
+
import { INAPP } from '../../../../constants/unified';
|
|
46
|
+
|
|
47
|
+
// Define Theme and Highlighting inline to avoid "multiple instances of @codemirror/state" error
|
|
48
|
+
|
|
38
49
|
|
|
39
50
|
// Legacy CodeMirrorEditor removed - using enhanced implementation only
|
|
40
51
|
|
|
@@ -42,12 +53,25 @@ const CodeEditorPaneComponent = ({
|
|
|
42
53
|
intl,
|
|
43
54
|
readOnly = false,
|
|
44
55
|
className = '',
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
forwardedRef,
|
|
57
|
+
// Tag-related props - tags are fetched and managed by parent component
|
|
58
|
+
tags = [],
|
|
59
|
+
injectedTags = {},
|
|
60
|
+
location,
|
|
61
|
+
eventContextTags = [],
|
|
62
|
+
selectedOfferDetails = [],
|
|
63
|
+
channel,
|
|
64
|
+
userLocale = 'en',
|
|
65
|
+
moduleFilterEnabled = true,
|
|
66
|
+
onTagContextChange,
|
|
67
|
+
// Validation props
|
|
68
|
+
onErrorClick,
|
|
48
69
|
}) => {
|
|
49
|
-
const
|
|
50
|
-
const {
|
|
70
|
+
const context = useEditorContext();
|
|
71
|
+
const {
|
|
72
|
+
content, validation, variant, isLiquidEnabled,
|
|
73
|
+
} = context || {};
|
|
74
|
+
const { content: contentValue, updateContent } = content || {};
|
|
51
75
|
const editorRef = useRef(null);
|
|
52
76
|
const viewRef = useRef(null);
|
|
53
77
|
|
|
@@ -61,7 +85,7 @@ const CodeEditorPaneComponent = ({
|
|
|
61
85
|
get view() {
|
|
62
86
|
return viewRef.current;
|
|
63
87
|
},
|
|
64
|
-
viewRef
|
|
88
|
+
viewRef, // For compatibility with existing code
|
|
65
89
|
|
|
66
90
|
focus: () => {
|
|
67
91
|
if (viewRef.current) {
|
|
@@ -75,7 +99,7 @@ const CodeEditorPaneComponent = ({
|
|
|
75
99
|
const pos = position !== undefined ? position : head;
|
|
76
100
|
view.dispatch({
|
|
77
101
|
changes: { from: pos, insert: text },
|
|
78
|
-
selection: { anchor: pos + text.length }
|
|
102
|
+
selection: { anchor: pos + text.length },
|
|
79
103
|
});
|
|
80
104
|
} else {
|
|
81
105
|
throw new Error('CodeMirror view not initialized');
|
|
@@ -88,9 +112,7 @@ const CodeEditorPaneComponent = ({
|
|
|
88
112
|
}
|
|
89
113
|
return 0;
|
|
90
114
|
},
|
|
91
|
-
getValue: () =>
|
|
92
|
-
return contentValue || '';
|
|
93
|
-
},
|
|
115
|
+
getValue: () => contentValue || '',
|
|
94
116
|
setValue: (value) => {
|
|
95
117
|
updateContent(value);
|
|
96
118
|
},
|
|
@@ -107,7 +129,7 @@ const CodeEditorPaneComponent = ({
|
|
|
107
129
|
|
|
108
130
|
view.dispatch({
|
|
109
131
|
selection: { anchor: pos },
|
|
110
|
-
effects: EditorView.scrollIntoView(pos, { y: 'center' })
|
|
132
|
+
effects: EditorView.scrollIntoView(pos, { y: 'center' }),
|
|
111
133
|
});
|
|
112
134
|
view.focus();
|
|
113
135
|
} catch (error) {
|
|
@@ -117,7 +139,7 @@ const CodeEditorPaneComponent = ({
|
|
|
117
139
|
}
|
|
118
140
|
}
|
|
119
141
|
}
|
|
120
|
-
}
|
|
142
|
+
},
|
|
121
143
|
}), [contentValue]);
|
|
122
144
|
|
|
123
145
|
// Note: handleContentChange removed - using updateContentRef directly in CodeMirror
|
|
@@ -133,7 +155,9 @@ const CodeEditorPaneComponent = ({
|
|
|
133
155
|
if (typeof tagData === 'string') {
|
|
134
156
|
tagText = tagData;
|
|
135
157
|
} else if (tagData) {
|
|
136
|
-
const {
|
|
158
|
+
const {
|
|
159
|
+
text, name, label, value,
|
|
160
|
+
} = tagData;
|
|
137
161
|
tagText = text || name || label || value;
|
|
138
162
|
if (!tagText) {
|
|
139
163
|
console.warn('Invalid tag data:', tagData);
|
|
@@ -147,49 +171,70 @@ const CodeEditorPaneComponent = ({
|
|
|
147
171
|
// For unified HTML editor, insert as template variable
|
|
148
172
|
const formattedTag = `{{${tagText}}}`;
|
|
149
173
|
|
|
150
|
-
// Insert the tag at cursor position
|
|
174
|
+
// Insert the tag at cursor position directly
|
|
151
175
|
view.dispatch({
|
|
152
176
|
changes: { from: pos, insert: formattedTag },
|
|
153
|
-
selection: { anchor: pos + formattedTag.length }
|
|
177
|
+
selection: { anchor: pos + formattedTag.length },
|
|
154
178
|
});
|
|
155
179
|
|
|
156
180
|
// Focus back to editor
|
|
157
181
|
view.focus();
|
|
158
182
|
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
183
|
+
// Note: We don't call onLabelInsert here because:
|
|
184
|
+
// 1. The tag is already inserted directly into the editor
|
|
185
|
+
// 2. onLabelInsert (handleLabelInsert from HTMLEditor) would try to insert again
|
|
186
|
+
// 3. This causes "Editor method not available" error
|
|
187
|
+
// The direct insertion via view.dispatch is sufficient
|
|
163
188
|
}
|
|
164
189
|
};
|
|
165
190
|
|
|
191
|
+
// Handle tag context change - delegate to parent component
|
|
192
|
+
// Tags are fetched in parent components (EmailHTMLEditor, INAPP, etc.)
|
|
193
|
+
// This component just passes the context change event up
|
|
194
|
+
const handleTagContextChange = useCallback((data) => {
|
|
195
|
+
if (onTagContextChange) {
|
|
196
|
+
// Parent component handles tag fetching and updates
|
|
197
|
+
onTagContextChange(data);
|
|
198
|
+
}
|
|
199
|
+
// No fallback - tags must be managed by parent component
|
|
200
|
+
}, [onTagContextChange]);
|
|
201
|
+
|
|
166
202
|
// Initialize CodeMirror effect
|
|
167
203
|
useEffect(() => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
204
|
+
// Ensure editorRef.current is a valid DOM element before initializing CodeMirror
|
|
205
|
+
if (editorRef.current && editorRef.current instanceof HTMLElement && !viewRef.current) {
|
|
206
|
+
// Determine placeholder text based on channel
|
|
207
|
+
let placeholderText = intl.formatMessage(messages.editorPlaceholderEmail); // Default to email
|
|
208
|
+
if (channel === INAPP || channel === INAPP.toUpperCase()) {
|
|
209
|
+
placeholderText = intl.formatMessage(messages.editorPlaceholderInapp);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Use the comprehensive extensions from properSyntaxHighlighting.js
|
|
213
|
+
// This includes: html(), syntaxHighlighting(comprehensiveVSCodeTheme), cleanEditorTheme
|
|
214
|
+
const robustExtensions = createRobustExtensions();
|
|
215
|
+
|
|
216
|
+
// Add additional extensions for line numbers, active line, and update listener
|
|
217
|
+
const extensions = [
|
|
218
|
+
lineNumbers(),
|
|
219
|
+
highlightActiveLine(),
|
|
220
|
+
placeholder(placeholderText),
|
|
221
|
+
...robustExtensions, // Spread the robust extensions (html, syntax highlighting, theme)
|
|
222
|
+
EditorView.lineWrapping, // Enable soft-wrapping of long lines
|
|
223
|
+
EditorView.updateListener.of((update) => {
|
|
224
|
+
if (update.docChanged) {
|
|
225
|
+
updateContentRef.current(update.state.doc.toString());
|
|
226
|
+
}
|
|
227
|
+
}),
|
|
228
|
+
];
|
|
184
229
|
|
|
185
230
|
const state = EditorState.create({
|
|
186
231
|
doc: contentValue || '',
|
|
187
|
-
extensions
|
|
232
|
+
extensions,
|
|
188
233
|
});
|
|
189
234
|
|
|
190
235
|
viewRef.current = new EditorView({
|
|
191
236
|
state,
|
|
192
|
-
parent: editorRef.current
|
|
237
|
+
parent: editorRef.current,
|
|
193
238
|
});
|
|
194
239
|
}
|
|
195
240
|
|
|
@@ -204,116 +249,70 @@ const CodeEditorPaneComponent = ({
|
|
|
204
249
|
viewRef.current = null;
|
|
205
250
|
}
|
|
206
251
|
};
|
|
207
|
-
}, []);
|
|
252
|
+
}, [channel, intl]);
|
|
208
253
|
|
|
209
254
|
// Update editor content when content changes
|
|
210
255
|
useEffect(() => {
|
|
211
|
-
if (viewRef.current && contentValue !== viewRef.current.state.doc.toString()) {
|
|
256
|
+
if (viewRef.current && contentValue && contentValue !== viewRef.current.state.doc.toString()) {
|
|
212
257
|
const { current: view } = viewRef;
|
|
213
258
|
const { state: { doc: { length } } } = view;
|
|
214
259
|
view.dispatch({
|
|
215
260
|
changes: {
|
|
216
261
|
from: 0,
|
|
217
262
|
to: length,
|
|
218
|
-
insert: contentValue || ''
|
|
219
|
-
}
|
|
263
|
+
insert: contentValue || '',
|
|
264
|
+
},
|
|
220
265
|
});
|
|
221
266
|
}
|
|
222
267
|
}, [contentValue]);
|
|
223
268
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
'customer.phone': {
|
|
264
|
-
name: 'Phone',
|
|
265
|
-
desc: 'Customer phone number',
|
|
266
|
-
resolved: true
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
'Common Tags': {
|
|
271
|
-
name: 'Common Tags',
|
|
272
|
-
desc: 'Commonly used template tags',
|
|
273
|
-
resolved: true,
|
|
274
|
-
'tag-header': true,
|
|
275
|
-
subtags: {
|
|
276
|
-
'organization.name': {
|
|
277
|
-
name: 'Organization Name',
|
|
278
|
-
desc: 'Organization name',
|
|
279
|
-
resolved: true
|
|
280
|
-
},
|
|
281
|
-
'currentDate': {
|
|
282
|
-
name: 'Current Date',
|
|
283
|
-
desc: 'Current date',
|
|
284
|
-
resolved: true
|
|
285
|
-
},
|
|
286
|
-
'unsubscribeLink': {
|
|
287
|
-
name: 'Unsubscribe Link',
|
|
288
|
-
desc: 'Unsubscribe link',
|
|
289
|
-
resolved: true
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}}
|
|
294
|
-
moduleFilterEnabled={true}
|
|
295
|
-
userLocale="en"
|
|
296
|
-
channel="email"
|
|
297
|
-
disabled={readOnly}
|
|
298
|
-
location={{
|
|
299
|
-
query: {
|
|
300
|
-
type: 'html-editor' // Identify the context
|
|
301
|
-
}
|
|
302
|
-
}}
|
|
303
|
-
selectedOfferDetails={[]}
|
|
304
|
-
eventContextTags={[]}
|
|
305
|
-
/>
|
|
306
|
-
</CapRow>
|
|
307
|
-
</div>
|
|
308
|
-
</CapRow>
|
|
309
|
-
|
|
310
|
-
</CapRow>
|
|
311
|
-
);
|
|
269
|
+
return (
|
|
270
|
+
<CapRow className={`code-editor-pane ${className}`}>
|
|
271
|
+
{/* Code Editor Content - Stacked vertically with validation */}
|
|
272
|
+
<div className="code-editor-pane__wrapper">
|
|
273
|
+
{/* Code Editor with Floating Add Label Button */}
|
|
274
|
+
<div className="codemirror-wrapper">
|
|
275
|
+
<div ref={editorRef} className="codemirror-editor" />
|
|
276
|
+
{/* Floating Add Label Button */}
|
|
277
|
+
<CapRow className="code-editor-pane__actions">
|
|
278
|
+
<TagList
|
|
279
|
+
key="html-editor-taglist"
|
|
280
|
+
label={intl.formatMessage(messages.addLabel)}
|
|
281
|
+
onTagSelect={handleTagSelect}
|
|
282
|
+
onContextChange={handleTagContextChange}
|
|
283
|
+
className="tag-list-trigger"
|
|
284
|
+
tags={tags}
|
|
285
|
+
injectedTags={injectedTags}
|
|
286
|
+
moduleFilterEnabled={moduleFilterEnabled}
|
|
287
|
+
userLocale={userLocale}
|
|
288
|
+
channel={channel}
|
|
289
|
+
disabled={readOnly}
|
|
290
|
+
location={location}
|
|
291
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
292
|
+
eventContextTags={eventContextTags}
|
|
293
|
+
popoverPlacement="rightTop"
|
|
294
|
+
/>
|
|
295
|
+
</CapRow>
|
|
296
|
+
</div>
|
|
297
|
+
|
|
298
|
+
{/* Validation Error Display - Below editor, always visible */}
|
|
299
|
+
<ValidationErrorDisplay
|
|
300
|
+
validation={validation}
|
|
301
|
+
onErrorClick={onErrorClick}
|
|
302
|
+
isLiquidEnabled={isLiquidEnabled}
|
|
303
|
+
className="code-editor-pane__validation"
|
|
304
|
+
/>
|
|
305
|
+
</div>
|
|
306
|
+
</CapRow>
|
|
307
|
+
);
|
|
312
308
|
};
|
|
313
309
|
|
|
314
|
-
//
|
|
310
|
+
// Apply injectIntl to the component first, then wrap with forwardRef
|
|
311
|
+
const CodeEditorPaneWithIntl = injectIntl(CodeEditorPaneComponent);
|
|
312
|
+
|
|
313
|
+
// Create the forwardRef wrapper that forwards ref to the intl-wrapped component
|
|
315
314
|
const CodeEditorPane = forwardRef((props, ref) => (
|
|
316
|
-
<
|
|
315
|
+
<CodeEditorPaneWithIntl {...props} forwardedRef={ref} />
|
|
317
316
|
));
|
|
318
317
|
|
|
319
318
|
CodeEditorPane.displayName = 'CodeEditorPane';
|
|
@@ -323,9 +322,19 @@ CodeEditorPane.propTypes = {
|
|
|
323
322
|
readOnly: PropTypes.bool,
|
|
324
323
|
className: PropTypes.string,
|
|
325
324
|
isFullscreenMode: PropTypes.bool,
|
|
326
|
-
onLabelInsert: PropTypes.func
|
|
325
|
+
onLabelInsert: PropTypes.func,
|
|
326
|
+
onErrorClick: PropTypes.func,
|
|
327
|
+
// Tag-related props - tags are fetched and managed by parent component
|
|
328
|
+
tags: PropTypes.array,
|
|
329
|
+
injectedTags: PropTypes.object,
|
|
330
|
+
location: PropTypes.object,
|
|
331
|
+
eventContextTags: PropTypes.array,
|
|
332
|
+
selectedOfferDetails: PropTypes.array,
|
|
333
|
+
channel: PropTypes.string,
|
|
334
|
+
userLocale: PropTypes.string,
|
|
335
|
+
moduleFilterEnabled: PropTypes.bool,
|
|
336
|
+
onTagContextChange: PropTypes.func, // Required - parent must handle tag fetching
|
|
327
337
|
};
|
|
328
338
|
|
|
329
|
-
// Export
|
|
330
|
-
export default
|
|
331
|
-
|
|
339
|
+
// Export the forwardRef-wrapped component
|
|
340
|
+
export default CodeEditorPane;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
.html-editor .device-toggle {
|
|
10
10
|
display: flex;
|
|
11
11
|
align-items: center;
|
|
12
|
-
|
|
12
|
+
margin-left: 2.5rem;
|
|
13
13
|
padding: 0;
|
|
14
14
|
background-color: $CAP_G10;
|
|
15
15
|
border-radius: 0.25rem 0.25rem 0 0;
|
|
@@ -220,6 +220,7 @@
|
|
|
220
220
|
|
|
221
221
|
// Integration with editor toolbar
|
|
222
222
|
.html-editor.html-editor--inapp {
|
|
223
|
+
margin-top: 4%;
|
|
223
224
|
.editor-toolbar {
|
|
224
225
|
padding: 0 1rem 0 0; // Remove left padding to align with device toggle
|
|
225
226
|
background-color: $CAP_G10;
|
|
@@ -32,7 +32,7 @@ const DeviceToggle = ({
|
|
|
32
32
|
onDeviceChange,
|
|
33
33
|
keepContentSame = false,
|
|
34
34
|
onKeepContentSameChange,
|
|
35
|
-
className = ''
|
|
35
|
+
className = '',
|
|
36
36
|
}) => {
|
|
37
37
|
const handleDeviceClick = (device) => {
|
|
38
38
|
if (onDeviceChange && device !== activeDevice) {
|
|
@@ -97,7 +97,7 @@ DeviceToggle.propTypes = {
|
|
|
97
97
|
onDeviceChange: PropTypes.func,
|
|
98
98
|
keepContentSame: PropTypes.bool,
|
|
99
99
|
onKeepContentSameChange: PropTypes.func,
|
|
100
|
-
className: PropTypes.string
|
|
100
|
+
className: PropTypes.string,
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
DeviceToggle.defaultProps = {
|
|
@@ -105,7 +105,7 @@ DeviceToggle.defaultProps = {
|
|
|
105
105
|
onDeviceChange: null,
|
|
106
106
|
keepContentSame: false,
|
|
107
107
|
onKeepContentSameChange: null,
|
|
108
|
-
className: ''
|
|
108
|
+
className: '',
|
|
109
109
|
};
|
|
110
110
|
|
|
111
111
|
export default injectIntl(DeviceToggle);
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
border-radius: 0.25rem 0.25rem 0 0;
|
|
16
16
|
box-sizing: border-box;
|
|
17
17
|
flex-shrink: 0;
|
|
18
|
+
position: relative;
|
|
18
19
|
|
|
19
20
|
&__left {
|
|
20
21
|
display: flex;
|
|
@@ -110,4 +111,12 @@
|
|
|
110
111
|
display: none;
|
|
111
112
|
}
|
|
112
113
|
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Library mode override for InApp variant - Position absolute for toolbar
|
|
117
|
+
// These selectors target the toolbar when inside library mode InApp variant
|
|
118
|
+
.html-editor--inapp.html-editor--library-mode .html-editor__header .editor-toolbar,
|
|
119
|
+
.html-editor--inapp.html-editor--library-mode .html-editor__header .editor-toolbar.editor-toolbar,
|
|
120
|
+
.html-editor--inapp.html-editor--library-mode .html-editor__header .ant-layout-header.editor-toolbar {
|
|
121
|
+
position: absolute;
|
|
113
122
|
}
|
|
@@ -49,9 +49,31 @@ body .ant-modal-mask+.ant-modal-wrap .ant-modal.html-editor-fullscreen-modal .an
|
|
|
49
49
|
padding: 0;
|
|
50
50
|
min-height: 3.25rem;
|
|
51
51
|
height: 3.25rem;
|
|
52
|
+
position: relative;
|
|
52
53
|
|
|
53
54
|
&__right {
|
|
54
55
|
margin-left: auto;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Library mode overrides for INAPP variant - Position absolute for toolbar
|
|
61
|
+
// These selectors match the high-specificity patterns above but include library-mode class
|
|
62
|
+
.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar,
|
|
63
|
+
.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar.editor-toolbar,
|
|
64
|
+
.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .ant-layout-header.editor-toolbar,
|
|
65
|
+
.html-editor.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar,
|
|
66
|
+
.html-editor.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar.editor-toolbar,
|
|
67
|
+
.html-editor.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .ant-layout-header.editor-toolbar,
|
|
68
|
+
.html-editor__header--fullscreen.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .editor-toolbar,
|
|
69
|
+
.html-editor__header.html-editor__header--fullscreen.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .editor-toolbar,
|
|
70
|
+
.html-editor__header.html-editor__header--fullscreen.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .editor-toolbar.editor-toolbar,
|
|
71
|
+
.html-editor__header.html-editor__header--fullscreen.html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .ant-layout-header.editor-toolbar,
|
|
72
|
+
.ant-modal .html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar,
|
|
73
|
+
.ant-modal .html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar.editor-toolbar,
|
|
74
|
+
.ant-modal .html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .ant-layout-header.editor-toolbar,
|
|
75
|
+
.ant-modal-content .html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar,
|
|
76
|
+
.ant-modal-content .html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .editor-toolbar.editor-toolbar,
|
|
77
|
+
.ant-modal-content .html-editor-fullscreen--inapp.html-editor-fullscreen--library-mode .html-editor__header--fullscreen .ant-layout-header.editor-toolbar {
|
|
78
|
+
position: absolute;
|
|
57
79
|
}
|
|
@@ -14,9 +14,7 @@ const DeviceFrame = ({
|
|
|
14
14
|
className = '',
|
|
15
15
|
...props
|
|
16
16
|
}) => {
|
|
17
|
-
const getFrameAsset = () =>
|
|
18
|
-
return device === DEVICE_TYPES.IOS ? iosFrame : androidFrame;
|
|
19
|
-
};
|
|
17
|
+
const getFrameAsset = () => device === DEVICE_TYPES.IOS ? iosFrame : androidFrame;
|
|
20
18
|
|
|
21
19
|
const getFrameStyles = () => {
|
|
22
20
|
const baseStyles = {
|
|
@@ -26,14 +24,13 @@ const DeviceFrame = ({
|
|
|
26
24
|
backgroundRepeat: 'no-repeat',
|
|
27
25
|
backgroundPosition: 'center',
|
|
28
26
|
backgroundSize: 'contain',
|
|
29
|
-
filter: 'drop-shadow(0 12px 48px rgba(0, 0, 0, 0.25)) brightness(1.05) contrast(1.1)'
|
|
30
27
|
};
|
|
31
28
|
|
|
32
29
|
// Unified dimensions - both devices use the same size since assets are identical
|
|
33
30
|
return {
|
|
34
31
|
...baseStyles,
|
|
35
32
|
width: '450px',
|
|
36
|
-
height: '920px'
|
|
33
|
+
height: '920px',
|
|
37
34
|
};
|
|
38
35
|
};
|
|
39
36
|
|
|
@@ -45,7 +42,7 @@ const DeviceFrame = ({
|
|
|
45
42
|
{...props}
|
|
46
43
|
>
|
|
47
44
|
|
|
48
|
-
|
|
45
|
+
{children}
|
|
49
46
|
|
|
50
47
|
</div>
|
|
51
48
|
);
|
|
@@ -54,7 +51,7 @@ const DeviceFrame = ({
|
|
|
54
51
|
DeviceFrame.propTypes = {
|
|
55
52
|
device: PropTypes.oneOf(Object.values(DEVICE_TYPES)),
|
|
56
53
|
children: PropTypes.node,
|
|
57
|
-
className: PropTypes.string
|
|
54
|
+
className: PropTypes.string,
|
|
58
55
|
};
|
|
59
56
|
|
|
60
57
|
export default DeviceFrame;
|