@capillarytech/creatives-library 8.0.242-alpha.0 → 8.0.242-alpha.1

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 (215) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/sagas/__tests__/assetPolling.test.js +74 -3
  7. package/sagas/assetPolling.js +8 -1
  8. package/services/api.js +10 -5
  9. package/services/tests/api.test.js +18 -0
  10. package/translations/en.json +0 -1
  11. package/utils/common.js +5 -0
  12. package/utils/commonUtils.js +14 -1
  13. package/utils/tests/commonUtil.test.js +224 -0
  14. package/utils/transformTemplateConfig.js +0 -10
  15. package/utils/transformerUtils.js +0 -42
  16. package/v2Components/CapDeviceContent/index.js +61 -56
  17. package/v2Components/CapImageUpload/constants.js +0 -2
  18. package/v2Components/CapImageUpload/index.js +14 -54
  19. package/v2Components/CapImageUpload/index.scss +1 -4
  20. package/v2Components/CapImageUpload/messages.js +0 -4
  21. package/v2Components/CapTagList/index.js +6 -1
  22. package/v2Components/CapTagListWithInput/index.js +5 -1
  23. package/v2Components/CapTagListWithInput/messages.js +1 -1
  24. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  25. package/v2Components/ErrorInfoNote/index.js +412 -72
  26. package/v2Components/ErrorInfoNote/messages.js +22 -0
  27. package/v2Components/ErrorInfoNote/style.scss +279 -2
  28. package/v2Components/HtmlEditor/HTMLEditor.js +210 -89
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1132 -133
  30. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
  31. package/v2Components/HtmlEditor/_htmlEditor.scss +8 -23
  32. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  33. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
  34. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
  35. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  36. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  37. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  38. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +1 -0
  39. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  40. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  44. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
  45. package/v2Components/HtmlEditor/components/PreviewPane/index.js +10 -11
  46. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  47. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +87 -62
  48. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
  49. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
  50. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +362 -0
  51. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  52. package/v2Components/HtmlEditor/constants.js +29 -20
  53. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  54. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  55. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  56. package/v2Components/HtmlEditor/index.js +1 -1
  57. package/v2Components/HtmlEditor/messages.js +95 -85
  58. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +99 -101
  59. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  60. package/v2Components/HtmlEditor/utils/validationAdapter.js +34 -41
  61. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  62. package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
  63. package/v2Components/TemplatePreview/index.js +47 -32
  64. package/v2Components/TemplatePreview/messages.js +4 -0
  65. package/v2Components/TestAndPreviewSlidebox/index.js +31 -25
  66. package/v2Containers/App/constants.js +0 -5
  67. package/v2Containers/BeeEditor/index.js +82 -80
  68. package/v2Containers/BeePopupEditor/constants.js +10 -0
  69. package/v2Containers/BeePopupEditor/index.js +193 -0
  70. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  71. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +0 -1
  72. package/v2Containers/CreativesContainer/SlideBoxContent.js +148 -120
  73. package/v2Containers/CreativesContainer/SlideBoxFooter.js +9 -3
  74. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
  75. package/v2Containers/CreativesContainer/constants.js +1 -2
  76. package/v2Containers/CreativesContainer/index.js +173 -193
  77. package/v2Containers/CreativesContainer/messages.js +4 -4
  78. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  79. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +36 -0
  80. package/v2Containers/Email/actions.js +7 -0
  81. package/v2Containers/Email/constants.js +5 -1
  82. package/v2Containers/Email/index.js +13 -0
  83. package/v2Containers/Email/messages.js +32 -0
  84. package/v2Containers/Email/reducer.js +12 -1
  85. package/v2Containers/Email/sagas.js +41 -6
  86. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  87. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1045 -0
  88. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +193 -7
  89. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  90. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  91. package/v2Containers/EmailWrapper/constants.js +2 -0
  92. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +436 -67
  93. package/v2Containers/EmailWrapper/index.js +99 -23
  94. package/v2Containers/EmailWrapper/messages.js +61 -1
  95. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +26 -1
  96. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +111 -77
  97. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  98. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  99. package/v2Containers/InApp/actions.js +7 -0
  100. package/v2Containers/InApp/constants.js +20 -4
  101. package/v2Containers/InApp/index.js +800 -357
  102. package/v2Containers/InApp/index.scss +4 -3
  103. package/v2Containers/InApp/messages.js +7 -3
  104. package/v2Containers/InApp/reducer.js +21 -3
  105. package/v2Containers/InApp/sagas.js +29 -9
  106. package/v2Containers/InApp/selectors.js +25 -5
  107. package/v2Containers/InApp/tests/index.test.js +154 -50
  108. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  109. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  110. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  111. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
  112. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  113. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
  114. package/v2Containers/InAppWrapper/constants.js +16 -0
  115. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  116. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  117. package/v2Containers/InAppWrapper/index.js +148 -0
  118. package/v2Containers/InAppWrapper/messages.js +49 -0
  119. package/v2Containers/InappAdvance/index.js +1099 -0
  120. package/v2Containers/InappAdvance/index.scss +10 -0
  121. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  122. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -3
  123. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -2
  124. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -25
  125. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -18
  126. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -46
  127. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +0 -4
  128. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -8
  129. package/v2Containers/TagList/index.js +67 -1
  130. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  131. package/v2Containers/Templates/_templates.scss +56 -200
  132. package/v2Containers/Templates/actions.js +1 -2
  133. package/v2Containers/Templates/constants.js +0 -1
  134. package/v2Containers/Templates/index.js +124 -277
  135. package/v2Containers/Templates/messages.js +4 -24
  136. package/v2Containers/Templates/reducer.js +0 -2
  137. package/v2Containers/Templates/tests/index.test.js +0 -10
  138. package/v2Containers/TemplatesV2/index.js +2 -3
  139. package/v2Containers/TemplatesV2/messages.js +0 -4
  140. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -132
  141. package/v2Components/CapImageUrlUpload/constants.js +0 -19
  142. package/v2Components/CapImageUrlUpload/index.js +0 -455
  143. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  144. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  145. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -175
  146. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  147. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -144
  148. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  149. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  150. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  151. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
  152. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  153. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  154. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -80
  155. package/v2Containers/WebPush/Create/index.js +0 -1755
  156. package/v2Containers/WebPush/Create/index.scss +0 -123
  157. package/v2Containers/WebPush/Create/messages.js +0 -199
  158. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -241
  159. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -290
  160. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -81
  161. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -240
  162. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
  163. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -144
  164. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  165. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  166. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  167. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  168. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  169. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  170. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  171. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  172. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -44
  173. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -110
  174. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  175. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -72
  176. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -55
  177. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -70
  178. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -512
  179. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -77
  180. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -527
  181. package/v2Containers/WebPush/Create/preview/constants.js +0 -162
  182. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -104
  183. package/v2Containers/WebPush/Create/preview/preview.scss +0 -409
  184. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -300
  185. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  186. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  187. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  188. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -303
  189. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  190. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  191. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  192. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -188
  193. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -106
  194. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  195. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -75
  196. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -174
  197. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  198. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1077
  199. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  200. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -943
  201. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -128
  202. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -121
  203. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  204. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -127
  205. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -116
  206. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  207. package/v2Containers/WebPush/actions.js +0 -60
  208. package/v2Containers/WebPush/constants.js +0 -108
  209. package/v2Containers/WebPush/index.js +0 -2
  210. package/v2Containers/WebPush/reducer.js +0 -104
  211. package/v2Containers/WebPush/sagas.js +0 -119
  212. package/v2Containers/WebPush/selectors.js +0 -65
  213. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  214. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  215. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -8,33 +8,43 @@
8
8
  * - Theme support with proper styling
9
9
  */
10
10
 
11
- import React, { forwardRef, useImperativeHandle, useRef, useEffect, useState } from '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 { EditorView, lineNumbers, highlightActiveLine } from '@codemirror/view';
18
+ import {
19
+ EditorView, lineNumbers, highlightActiveLine, placeholder,
20
+ } from '@codemirror/view';
17
21
 
18
- // Import our comprehensive syntax highlighting solution
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';
25
29
  import messages from '../../messages';
26
30
 
27
31
  // Cap UI Components
28
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
29
32
 
30
33
  // Components
31
34
  import TagList from '../../../../v2Containers/TagList';
35
+ import ValidationErrorDisplay from '../ValidationErrorDisplay';
36
+
37
+ // Constants - removed unused imports since tag fetching is handled by parent
32
38
 
33
39
  // Context
34
40
  import { useEditorContext } from '../common/EditorContext';
35
41
 
36
42
  // Styles
37
43
  import './_codeEditorPane.scss';
44
+ import { INAPP } from '../../../../constants/unified';
45
+
46
+ // Define Theme and Highlighting inline to avoid "multiple instances of @codemirror/state" error
47
+
38
48
 
39
49
  // Legacy CodeMirrorEditor removed - using enhanced implementation only
40
50
 
@@ -42,12 +52,25 @@ const CodeEditorPaneComponent = ({
42
52
  intl,
43
53
  readOnly = false,
44
54
  className = '',
45
- isFullscreenMode = false,
46
- onLabelInsert,
47
- forwardedRef
55
+ forwardedRef,
56
+ // Tag-related props - tags are fetched and managed by parent component
57
+ tags = [],
58
+ injectedTags = {},
59
+ location,
60
+ eventContextTags = [],
61
+ selectedOfferDetails = [],
62
+ channel,
63
+ userLocale = 'en',
64
+ moduleFilterEnabled = true,
65
+ onTagContextChange,
66
+ // Validation props
67
+ onErrorClick,
48
68
  }) => {
49
- const { content, validation } = useEditorContext();
50
- const { content: contentValue, updateContent } = content;
69
+ const context = useEditorContext();
70
+ const {
71
+ content, validation, variant, isLiquidEnabled,
72
+ } = context || {};
73
+ const { content: contentValue, updateContent } = content || {};
51
74
  const editorRef = useRef(null);
52
75
  const viewRef = useRef(null);
53
76
 
@@ -61,7 +84,7 @@ const CodeEditorPaneComponent = ({
61
84
  get view() {
62
85
  return viewRef.current;
63
86
  },
64
- viewRef: viewRef, // For compatibility with existing code
87
+ viewRef, // For compatibility with existing code
65
88
 
66
89
  focus: () => {
67
90
  if (viewRef.current) {
@@ -75,7 +98,7 @@ const CodeEditorPaneComponent = ({
75
98
  const pos = position !== undefined ? position : head;
76
99
  view.dispatch({
77
100
  changes: { from: pos, insert: text },
78
- selection: { anchor: pos + text.length }
101
+ selection: { anchor: pos + text.length },
79
102
  });
80
103
  } else {
81
104
  throw new Error('CodeMirror view not initialized');
@@ -88,9 +111,7 @@ const CodeEditorPaneComponent = ({
88
111
  }
89
112
  return 0;
90
113
  },
91
- getValue: () => {
92
- return contentValue || '';
93
- },
114
+ getValue: () => contentValue || '',
94
115
  setValue: (value) => {
95
116
  updateContent(value);
96
117
  },
@@ -107,7 +128,7 @@ const CodeEditorPaneComponent = ({
107
128
 
108
129
  view.dispatch({
109
130
  selection: { anchor: pos },
110
- effects: EditorView.scrollIntoView(pos, { y: 'center' })
131
+ effects: EditorView.scrollIntoView(pos, { y: 'center' }),
111
132
  });
112
133
  view.focus();
113
134
  } catch (error) {
@@ -117,7 +138,7 @@ const CodeEditorPaneComponent = ({
117
138
  }
118
139
  }
119
140
  }
120
- }
141
+ },
121
142
  }), [contentValue]);
122
143
 
123
144
  // Note: handleContentChange removed - using updateContentRef directly in CodeMirror
@@ -133,7 +154,9 @@ const CodeEditorPaneComponent = ({
133
154
  if (typeof tagData === 'string') {
134
155
  tagText = tagData;
135
156
  } else if (tagData) {
136
- const { text, name, label, value } = tagData;
157
+ const {
158
+ text, name, label, value,
159
+ } = tagData;
137
160
  tagText = text || name || label || value;
138
161
  if (!tagText) {
139
162
  console.warn('Invalid tag data:', tagData);
@@ -147,49 +170,67 @@ const CodeEditorPaneComponent = ({
147
170
  // For unified HTML editor, insert as template variable
148
171
  const formattedTag = `{{${tagText}}}`;
149
172
 
150
- // Insert the tag at cursor position
173
+ // Insert the tag at cursor position directly
151
174
  view.dispatch({
152
175
  changes: { from: pos, insert: formattedTag },
153
- selection: { anchor: pos + formattedTag.length }
176
+ selection: { anchor: pos + formattedTag.length },
154
177
  });
155
178
 
156
179
  // Focus back to editor
157
180
  view.focus();
158
181
 
159
- // Call the parent's handleLabelInsert if available
160
- if (onLabelInsert) {
161
- onLabelInsert(formattedTag, pos);
162
- }
182
+ // Note: We don't call onLabelInsert here because:
183
+ // 1. The tag is already inserted directly into the editor
184
+ // 2. onLabelInsert (handleLabelInsert from HTMLEditor) would try to insert again
185
+ // 3. This causes "Editor method not available" error
186
+ // The direct insertion via view.dispatch is sufficient
163
187
  }
164
188
  };
165
189
 
190
+ // Handle tag context change - delegate to parent component
191
+ // Tags are fetched in parent components (EmailHTMLEditor, INAPP, etc.)
192
+ // This component just passes the context change event up
193
+ const handleTagContextChange = useCallback((data) => {
194
+ if (onTagContextChange) {
195
+ // Parent component handles tag fetching and updates
196
+ onTagContextChange(data);
197
+ }
198
+ // No fallback - tags must be managed by parent component
199
+ }, [onTagContextChange]);
200
+
166
201
  // Initialize CodeMirror effect
167
202
  useEffect(() => {
168
203
  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
- ];
204
+ // Determine placeholder text based on channel
205
+ let placeholderText = intl.formatMessage(messages.editorPlaceholderEmail); // Default to email
206
+ if (channel === INAPP || channel === INAPP.toUpperCase()) {
207
+ placeholderText = intl.formatMessage(messages.editorPlaceholderInapp);
208
+ }
209
+
210
+ // Add additional extensions for line numbers, active line, placeholder, line wrapping, and update listener
211
+ const extensions = [
212
+ lineNumbers(),
213
+ highlightActiveLine(),
214
+ placeholder(placeholderText),
215
+ EditorView.lineWrapping, // Enable soft-wrapping of long lines
216
+ // html(), // 1. HTML language support - TEMPORARILY DISABLED due to version conflict
217
+ // syntaxHighlighting(comprehensiveVSCodeTheme), // 2. Syntax highlighting - TEMPORARILY DISABLED
218
+ // cleanEditorTheme, // 3. Theme - TEMPORARILY DISABLED
219
+ EditorView.updateListener.of((update) => {
220
+ if (update.docChanged) {
221
+ updateContentRef.current(update.state.doc.toString());
222
+ }
223
+ }),
224
+ ];
184
225
 
185
226
  const state = EditorState.create({
186
227
  doc: contentValue || '',
187
- extensions
228
+ extensions,
188
229
  });
189
230
 
190
231
  viewRef.current = new EditorView({
191
232
  state,
192
- parent: editorRef.current
233
+ parent: editorRef.current,
193
234
  });
194
235
  }
195
236
 
@@ -204,116 +245,74 @@ const CodeEditorPaneComponent = ({
204
245
  viewRef.current = null;
205
246
  }
206
247
  };
207
- }, []);
248
+ }, [channel, intl]);
208
249
 
209
250
  // Update editor content when content changes
210
251
  useEffect(() => {
211
- if (viewRef.current && contentValue !== viewRef.current.state.doc.toString()) {
252
+ if (viewRef.current && contentValue && contentValue !== viewRef.current.state.doc.toString()) {
212
253
  const { current: view } = viewRef;
213
254
  const { state: { doc: { length } } } = view;
214
255
  view.dispatch({
215
256
  changes: {
216
257
  from: 0,
217
258
  to: length,
218
- insert: contentValue || ''
219
- }
259
+ insert: contentValue || '',
260
+ },
220
261
  });
221
262
  }
222
263
  }, [contentValue]);
223
264
 
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
- );
265
+ return (
266
+ <CapRow className={`code-editor-pane ${className}`}>
267
+ {/* Code Editor Content - Stacked vertically with validation */}
268
+ <div
269
+ className="code-editor-pane__wrapper"
270
+ style={{
271
+ display: 'flex', flexDirection: 'column', height: '100%', width: '100%',
272
+ }}>
273
+ {/* Code Editor with Floating Add Label Button */}
274
+ <div className="codemirror-wrapper" style={{ flex: '1 1 auto', minHeight: 0 }}>
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
- // Create the forwardRef wrapper
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
- <CodeEditorPaneComponent {...props} forwardedRef={ref} />
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 with injectIntl - ref forwarding is handled by forwardRef wrapper
330
- export default injectIntl(CodeEditorPane);
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
- gap: 1rem;
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);
@@ -81,7 +81,7 @@ const EditorToolbar = ({
81
81
  )}
82
82
  aria-pressed={isFullscreenMode}
83
83
  >
84
- <CapIcon type={isFullscreenMode ? "minimizer" : "expander"} size="m" />
84
+ <CapIcon type={isFullscreenMode ? "collapse2" : "expander"} size="m" />
85
85
  </CapButton>
86
86
  )}
87
87
  </CapRow>
@@ -49,6 +49,7 @@ 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;
@@ -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
- {children}
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;