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