@capillarytech/creatives-library 8.0.250-alpha.2 → 8.0.251

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 (276) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +1 -3
  4. package/initialReducer.js +0 -2
  5. package/package.json +1 -1
  6. package/services/api.js +0 -15
  7. package/services/tests/api.test.js +0 -34
  8. package/translations/en.json +3 -4
  9. package/utils/common.js +0 -11
  10. package/utils/commonUtils.js +5 -28
  11. package/utils/tests/commonUtil.test.js +0 -224
  12. package/utils/tests/transformerUtils.test.js +0 -297
  13. package/utils/transformTemplateConfig.js +10 -0
  14. package/utils/transformerUtils.js +0 -40
  15. package/v2Components/CapDeviceContent/index.js +56 -61
  16. package/v2Components/CapImageUpload/constants.js +0 -2
  17. package/v2Components/CapImageUpload/index.js +16 -65
  18. package/v2Components/CapImageUpload/index.scss +1 -4
  19. package/v2Components/CapImageUpload/messages.js +1 -5
  20. package/v2Components/CapTagList/index.js +1 -6
  21. package/v2Components/CapTagListWithInput/index.js +1 -5
  22. package/v2Components/CapTagListWithInput/messages.js +1 -1
  23. package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
  24. package/v2Components/ErrorInfoNote/index.js +72 -455
  25. package/v2Components/ErrorInfoNote/messages.js +6 -36
  26. package/v2Components/ErrorInfoNote/style.scss +4 -280
  27. package/v2Components/FormBuilder/tests/index.test.js +4 -13
  28. package/v2Components/HtmlEditor/HTMLEditor.js +94 -547
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1358
  30. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +16 -27
  31. package/v2Components/HtmlEditor/_htmlEditor.scss +45 -108
  32. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  33. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +101 -22
  34. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +140 -146
  35. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
  36. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  37. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +0 -9
  38. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  39. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -22
  40. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
  45. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +6 -3
  46. package/v2Components/HtmlEditor/components/PreviewPane/index.js +34 -24
  47. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  48. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +152 -0
  49. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -49
  50. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +34 -50
  51. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +41 -70
  52. package/v2Components/HtmlEditor/constants.js +20 -42
  53. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
  54. package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
  55. package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
  56. package/v2Components/HtmlEditor/hooks/useValidation.js +53 -189
  57. package/v2Components/HtmlEditor/index.js +1 -1
  58. package/v2Components/HtmlEditor/messages.js +85 -95
  59. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +45 -94
  60. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +0 -134
  61. package/v2Components/HtmlEditor/utils/contentSanitizer.js +41 -40
  62. package/v2Components/HtmlEditor/utils/htmlValidator.js +72 -71
  63. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +102 -134
  64. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
  65. package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -66
  66. package/v2Components/MobilePushPreviewV2/index.js +7 -32
  67. package/v2Components/TemplatePreview/_templatePreview.scss +24 -55
  68. package/v2Components/TemplatePreview/index.js +32 -47
  69. package/v2Components/TemplatePreview/messages.js +0 -4
  70. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +0 -1
  71. package/v2Containers/App/constants.js +0 -5
  72. package/v2Containers/BeeEditor/index.js +90 -172
  73. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +3 -4
  74. package/v2Containers/CreativesContainer/SlideBoxContent.js +53 -184
  75. package/v2Containers/CreativesContainer/SlideBoxFooter.js +13 -163
  76. package/v2Containers/CreativesContainer/SlideBoxHeader.js +1 -3
  77. package/v2Containers/CreativesContainer/constants.js +0 -4
  78. package/v2Containers/CreativesContainer/index.js +46 -407
  79. package/v2Containers/CreativesContainer/messages.js +0 -12
  80. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
  81. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +2 -11
  82. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +50 -342
  83. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -106
  84. package/v2Containers/Email/actions.js +0 -7
  85. package/v2Containers/Email/constants.js +1 -5
  86. package/v2Containers/Email/index.js +29 -234
  87. package/v2Containers/Email/messages.js +0 -32
  88. package/v2Containers/Email/reducer.js +1 -12
  89. package/v2Containers/Email/sagas.js +7 -61
  90. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
  91. package/v2Containers/Email/tests/reducer.test.js +0 -46
  92. package/v2Containers/Email/tests/sagas.test.js +29 -320
  93. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +19 -207
  94. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
  95. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
  96. package/v2Containers/EmailWrapper/constants.js +0 -2
  97. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +77 -629
  98. package/v2Containers/EmailWrapper/index.js +23 -103
  99. package/v2Containers/EmailWrapper/messages.js +1 -61
  100. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +214 -0
  101. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -594
  102. package/v2Containers/InApp/actions.js +0 -7
  103. package/v2Containers/InApp/constants.js +4 -20
  104. package/v2Containers/InApp/index.js +359 -802
  105. package/v2Containers/InApp/index.scss +3 -4
  106. package/v2Containers/InApp/messages.js +3 -7
  107. package/v2Containers/InApp/reducer.js +3 -21
  108. package/v2Containers/InApp/sagas.js +9 -29
  109. package/v2Containers/InApp/selectors.js +5 -25
  110. package/v2Containers/InApp/tests/index.test.js +50 -154
  111. package/v2Containers/InApp/tests/reducer.test.js +0 -34
  112. package/v2Containers/InApp/tests/sagas.test.js +9 -61
  113. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +9 -15
  114. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +6 -10
  115. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +75 -102
  116. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +54 -81
  117. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +174 -244
  118. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +12 -16
  119. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +36 -52
  120. package/v2Containers/TagList/index.js +19 -62
  121. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  122. package/v2Containers/Templates/_templates.scss +1 -265
  123. package/v2Containers/Templates/actions.js +1 -2
  124. package/v2Containers/Templates/constants.js +0 -1
  125. package/v2Containers/Templates/index.js +38 -363
  126. package/v2Containers/Templates/messages.js +0 -28
  127. package/v2Containers/Templates/reducer.js +0 -4
  128. package/v2Containers/Templates/tests/index.test.js +0 -10
  129. package/v2Containers/TemplatesV2/index.js +7 -15
  130. package/v2Containers/TemplatesV2/messages.js +0 -4
  131. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +486 -682
  132. package/utils/imageUrlUpload.js +0 -141
  133. package/v2Components/CapImageUrlUpload/constants.js +0 -26
  134. package/v2Components/CapImageUrlUpload/index.js +0 -365
  135. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  136. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  137. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -874
  138. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +0 -6
  139. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -254
  140. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -364
  141. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
  142. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +0 -795
  143. package/v2Components/HtmlEditor/utils/validationConstants.js +0 -40
  144. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +0 -14
  145. package/v2Containers/BeePopupEditor/constants.js +0 -10
  146. package/v2Containers/BeePopupEditor/index.js +0 -194
  147. package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
  148. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1285
  149. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +0 -1870
  150. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +0 -520
  151. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +0 -643
  152. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
  153. package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
  154. package/v2Containers/InApp/tests/selectors.test.js +0 -612
  155. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -151
  156. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
  157. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -23
  158. package/v2Containers/InAppWrapper/constants.js +0 -16
  159. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
  160. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
  161. package/v2Containers/InAppWrapper/index.js +0 -148
  162. package/v2Containers/InAppWrapper/messages.js +0 -49
  163. package/v2Containers/InappAdvance/index.js +0 -1099
  164. package/v2Containers/InappAdvance/index.scss +0 -10
  165. package/v2Containers/InappAdvance/tests/index.test.js +0 -448
  166. package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
  167. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
  168. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  169. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -107
  170. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -160
  171. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -476
  172. package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
  173. package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
  174. package/v2Containers/WebPush/Create/components/MediaSection.js +0 -143
  175. package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
  176. package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
  177. package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
  178. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
  179. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
  180. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
  181. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
  182. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -82
  183. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
  184. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
  185. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
  186. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
  187. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
  188. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  189. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  190. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  191. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -515
  192. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  193. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  194. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -46
  195. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -150
  196. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
  197. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
  198. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
  199. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
  200. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
  201. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
  202. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
  203. package/v2Containers/WebPush/Create/index.js +0 -1148
  204. package/v2Containers/WebPush/Create/index.scss +0 -134
  205. package/v2Containers/WebPush/Create/messages.js +0 -203
  206. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
  207. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
  208. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
  209. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
  210. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
  211. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
  212. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  213. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  214. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
  215. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
  216. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  217. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  218. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  219. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  220. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
  221. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
  222. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  223. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  224. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
  225. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
  226. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -47
  227. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -141
  228. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  229. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
  230. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
  231. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
  232. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
  233. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
  234. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -81
  235. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
  236. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
  237. package/v2Containers/WebPush/Create/preview/constants.js +0 -637
  238. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
  239. package/v2Containers/WebPush/Create/preview/preview.scss +0 -351
  240. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
  241. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  242. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  243. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  244. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
  245. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  246. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  247. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  248. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
  249. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
  250. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  251. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
  252. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
  253. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  254. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
  255. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  256. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
  257. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
  258. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
  259. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  260. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
  261. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
  262. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
  263. package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
  264. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
  265. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  266. package/v2Containers/WebPush/Create/utils/validation.js +0 -75
  267. package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
  268. package/v2Containers/WebPush/actions.js +0 -60
  269. package/v2Containers/WebPush/constants.js +0 -132
  270. package/v2Containers/WebPush/index.js +0 -2
  271. package/v2Containers/WebPush/reducer.js +0 -104
  272. package/v2Containers/WebPush/sagas.js +0 -119
  273. package/v2Containers/WebPush/selectors.js +0 -65
  274. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  275. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  276. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -0,0 +1,152 @@
1
+ /**
2
+ * ValidationErrorDisplay Component Tests
3
+ *
4
+ * Tests for the ValidationErrorDisplay component that integrates with ErrorInfoNote.
5
+ */
6
+
7
+ import React from 'react';
8
+ import { render, screen } from '@testing-library/react';
9
+ import '@testing-library/jest-dom';
10
+ import ValidationErrorDisplay from '../index';
11
+
12
+ // Mock ErrorInfoNote component
13
+ jest.mock('../../../../ErrorInfoNote', () => {
14
+ return function MockErrorInfoNote({ errorMessages }) {
15
+ const liquidErrors = errorMessages?.LIQUID_ERROR_MSG || [];
16
+ const standardErrors = errorMessages?.STANDARD_ERROR_MSG || [];
17
+ const hasErrors = liquidErrors.length > 0 || standardErrors.length > 0;
18
+
19
+ if (!hasErrors) return null;
20
+
21
+ return (
22
+ <div data-testid="error-info-note">
23
+ {liquidErrors.map((msg, index) => (
24
+ <div key={`liquid-${index}`} data-testid="error-message">
25
+ {msg}
26
+ </div>
27
+ ))}
28
+ {standardErrors.map((msg, index) => (
29
+ <div key={`standard-${index}`} data-testid="error-message">
30
+ {msg}
31
+ </div>
32
+ ))}
33
+ </div>
34
+ );
35
+ };
36
+ });
37
+
38
+ describe('ValidationErrorDisplay', () => {
39
+ it('renders standard errors when validation has issues', () => {
40
+ const mockValidation = {
41
+ getAllIssues: () => [
42
+ { message: 'Missing closing tag', severity: 'error', line: 5, column: 10 },
43
+ { message: 'Invalid attribute', severity: 'error', line: 7 }
44
+ ],
45
+ isClean: () => false,
46
+ isValidating: false
47
+ };
48
+
49
+ render(<ValidationErrorDisplay validation={mockValidation} />);
50
+
51
+ expect(screen.getByTestId('error-info-note')).toBeInTheDocument();
52
+ const errorMessages = screen.getAllByTestId('error-message');
53
+ expect(errorMessages).toHaveLength(2);
54
+ expect(errorMessages[0]).toHaveTextContent('Missing closing tag Line 5, Char 10.');
55
+ expect(errorMessages[1]).toHaveTextContent('Invalid attribute Line 7.');
56
+ });
57
+
58
+ it('renders liquid errors separately', () => {
59
+ const mockValidation = {
60
+ getAllIssues: () => [
61
+ { message: 'Invalid liquid syntax', severity: 'error', source: 'liquid-validator', line: 3 },
62
+ { message: 'HTML error', severity: 'error', source: 'htmlhint', line: 10 }
63
+ ],
64
+ isClean: () => false,
65
+ isValidating: false
66
+ };
67
+
68
+ render(<ValidationErrorDisplay validation={mockValidation} />);
69
+
70
+ expect(screen.getByTestId('error-info-note')).toBeInTheDocument();
71
+ const errorMessages = screen.getAllByTestId('error-message');
72
+ expect(errorMessages).toHaveLength(2);
73
+ // First should be liquid error, second should be standard error
74
+ expect(errorMessages[0]).toHaveTextContent('Invalid liquid syntax Line 3.');
75
+ expect(errorMessages[1]).toHaveTextContent('HTML error Line 10.');
76
+ });
77
+
78
+ it('does not render when validation has no errors', () => {
79
+ const mockValidation = {
80
+ getAllIssues: () => [],
81
+ isClean: () => true,
82
+ isValidating: false
83
+ };
84
+
85
+ const { container } = render(<ValidationErrorDisplay validation={mockValidation} />);
86
+
87
+ expect(screen.queryByTestId('error-info-note')).not.toBeInTheDocument();
88
+ expect(container.firstChild).toBeNull();
89
+ });
90
+
91
+ it('does not render when validation is null', () => {
92
+ const { container } = render(<ValidationErrorDisplay validation={null} />);
93
+
94
+ expect(screen.queryByTestId('error-info-note')).not.toBeInTheDocument();
95
+ expect(container.firstChild).toBeNull();
96
+ });
97
+
98
+ it('does not render when validation is in progress', () => {
99
+ const mockValidation = {
100
+ getAllIssues: () => [],
101
+ isClean: () => false,
102
+ isValidating: true
103
+ };
104
+
105
+ const { container } = render(<ValidationErrorDisplay validation={mockValidation} />);
106
+
107
+ expect(screen.queryByTestId('error-info-note')).not.toBeInTheDocument();
108
+ expect(container.firstChild).toBeNull();
109
+ });
110
+
111
+ it('applies custom className', () => {
112
+ const mockValidation = {
113
+ getAllIssues: () => [{ message: 'Error', severity: 'error' }],
114
+ isClean: () => false,
115
+ isValidating: false
116
+ };
117
+
118
+ const { container } = render(
119
+ <ValidationErrorDisplay validation={mockValidation} className="custom-class" />
120
+ );
121
+
122
+ const wrapper = container.querySelector('.validation-error-display');
123
+ expect(wrapper).toHaveClass('custom-class');
124
+ });
125
+
126
+ it('handles inapp variant correctly', () => {
127
+ const mockValidation = {
128
+ getAllIssues: () => [{ message: 'Mobile error', severity: 'error' }],
129
+ isClean: () => false,
130
+ isValidating: false
131
+ };
132
+
133
+ render(<ValidationErrorDisplay validation={mockValidation} variant="inapp" />);
134
+
135
+ expect(screen.getByTestId('error-info-note')).toBeInTheDocument();
136
+ expect(screen.getByTestId('error-message')).toHaveTextContent('Mobile error');
137
+ });
138
+
139
+ it('includes rule information in error messages when available', () => {
140
+ const mockValidation = {
141
+ getAllIssues: () => [
142
+ { message: 'Alt attribute required', severity: 'error', rule: 'alt-require', line: 5 }
143
+ ],
144
+ isClean: () => false,
145
+ isValidating: false
146
+ };
147
+
148
+ render(<ValidationErrorDisplay validation={mockValidation} />);
149
+
150
+ expect(screen.getByTestId('error-message')).toHaveTextContent('Alt attribute required Line 5. • alt-require');
151
+ });
152
+ });
@@ -1,15 +1,18 @@
1
1
  /**
2
- * ValidationErrorDisplay - HTML Editor validation display
2
+ * ValidationErrorDisplay - HTML Editor validation using ErrorInfoNote
3
3
  *
4
- * This component displays validation errors using the new ValidationTabs component
5
- * with tabbed interface for HTML, Label, and Liquid issues.
4
+ * This component integrates the existing ErrorInfoNote component with the HTML Editor's
5
+ * validation system, providing a consistent error display that matches the Figma design.
6
6
  */
7
7
 
8
- import React, { useState } from 'react';
8
+ import React from 'react';
9
9
  import PropTypes from 'prop-types';
10
10
 
11
- import { hasValidationErrors } from '../../utils/validationAdapter';
12
- import ValidationTabs from '../ValidationTabs';
11
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
12
+ import ErrorInfoNote from '../../../ErrorInfoNote';
13
+
14
+ import { transformValidationToErrorInfo, hasValidationErrors } from '../../utils/validationAdapter';
15
+ import { HTML_EDITOR_VARIANTS } from '../../constants';
13
16
 
14
17
  // Styles
15
18
  import './_validationErrorDisplay.scss';
@@ -17,72 +20,51 @@ import './_validationErrorDisplay.scss';
17
20
  /**
18
21
  * ValidationErrorDisplay Component
19
22
  *
20
- * Displays validation errors using the ValidationTabs component
23
+ * Displays validation errors using the existing ErrorInfoNote component
21
24
  */
22
25
  const ValidationErrorDisplay = ({
23
26
  validation,
27
+ variant = HTML_EDITOR_VARIANTS.EMAIL,
24
28
  onErrorClick,
25
- onClose,
26
- isLiquidEnabled = false,
27
- className = '',
29
+ className = ''
28
30
  }) => {
29
- // Track if panel is dismissed
30
- const [isDismissed, setIsDismissed] = useState(false);
31
-
32
- // Handle close - dismiss temporarily
33
- const handleClose = () => {
34
- setIsDismissed(true);
35
- if (onClose) {
36
- onClose();
37
- }
38
- };
39
-
40
- // Reset dismissed state when validation changes (new errors appear)
41
- React.useEffect(() => {
42
- if (hasValidationErrors(validation)) {
43
- setIsDismissed(false);
44
- }
45
- }, [validation]);
46
-
47
- // Don't render if no validation, no errors, or dismissed
48
- if (!hasValidationErrors(validation) || isDismissed) {
31
+ // Don't render if no validation or no errors
32
+ if (!hasValidationErrors(validation)) {
49
33
  return null;
50
34
  }
51
35
 
36
+ // Transform validation data to ErrorInfoNote format
37
+ const errorData = transformValidationToErrorInfo(validation, variant);
38
+ const { errorMessages } = errorData || {};
39
+
40
+ // Handle error click if provided
41
+ const handleErrorClick = (error) => {
42
+ onErrorClick?.(error);
43
+ };
44
+
52
45
  return (
53
- <div
46
+ <CapRow
54
47
  className={`validation-error-display ${className}`}
55
48
  role="alert"
56
49
  aria-live="polite"
57
50
  aria-label="Validation errors"
58
51
  >
59
- <ValidationTabs
60
- validation={validation}
61
- onErrorClick={onErrorClick}
62
- onClose={handleClose}
63
- isLiquidEnabled={isLiquidEnabled}
52
+ <ErrorInfoNote
53
+ errorMessages={errorMessages}
54
+ onErrorClick={handleErrorClick}
64
55
  />
65
- </div>
56
+ </CapRow>
66
57
  );
67
58
  };
68
59
 
69
60
  ValidationErrorDisplay.propTypes = {
70
61
  validation: PropTypes.shape({
71
62
  isValidating: PropTypes.bool,
72
- getAllIssues: PropTypes.func,
63
+ getAllIssues: PropTypes.func
73
64
  }),
65
+ variant: PropTypes.oneOf(Object.values(HTML_EDITOR_VARIANTS)),
74
66
  onErrorClick: PropTypes.func,
75
- onClose: PropTypes.func,
76
- isLiquidEnabled: PropTypes.bool,
77
- className: PropTypes.string,
78
- };
79
-
80
- ValidationErrorDisplay.defaultProps = {
81
- validation: null,
82
- onErrorClick: null,
83
- onClose: null,
84
- isLiquidEnabled: false,
85
- className: '',
67
+ className: PropTypes.string
86
68
  };
87
69
 
88
70
  export default ValidationErrorDisplay;
@@ -5,17 +5,17 @@
5
5
  @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
6
6
 
7
7
  .validation-panel {
8
- border: 1px solid $CAP_COLOR_16;
9
- border-radius: $CAP_SPACE_06;
10
- background: $CAP_WHITE;
8
+ border: 1px solid #d9d9d9;
9
+ border-radius: 6px;
10
+ background: #fff;
11
11
 
12
12
  &--loading {
13
- padding: $CAP_SPACE_16;
13
+ padding: 16px;
14
14
  text-align: center;
15
15
  }
16
16
 
17
17
  &--clean {
18
- padding: $CAP_SPACE_16;
18
+ padding: 16px;
19
19
  text-align: center;
20
20
  background: #f6ffed;
21
21
  border-color: #b7eb8f;
@@ -25,7 +25,7 @@
25
25
  display: flex;
26
26
  align-items: center;
27
27
  justify-content: center;
28
- gap: $CAP_SPACE_08;
28
+ gap: 8px;
29
29
  color: #666;
30
30
  font-size: 14px;
31
31
  }
@@ -34,36 +34,36 @@
34
34
  display: flex;
35
35
  align-items: center;
36
36
  justify-content: center;
37
- gap: $CAP_SPACE_08;
37
+ gap: 8px;
38
38
  color: #52c41a;
39
39
  font-size: 14px;
40
- font-weight: $FONT_WEIGHT_MEDIUM;
40
+ font-weight: 500;
41
41
  }
42
42
 
43
43
  &__summary {
44
44
  display: flex;
45
- gap: $CAP_SPACE_16;
46
- padding: $CAP_SPACE_12 $CAP_SPACE_16;
47
- background: $CAP_G21;
48
- border-bottom: 1px solid $CAP_COLOR_16;
49
- border-radius: $CAP_SPACE_06 $CAP_SPACE_06 0 0;
45
+ gap: 16px;
46
+ padding: 12px 16px;
47
+ background: #fafafa;
48
+ border-bottom: 1px solid #d9d9d9;
49
+ border-radius: 6px 6px 0 0;
50
50
  }
51
51
 
52
52
  &__summary-item {
53
53
  display: flex;
54
54
  align-items: center;
55
- gap: $CAP_SPACE_04;
56
- font-size: $CAP_SPACE_12;
55
+ gap: 4px;
56
+ font-size: 12px;
57
57
  color: #666;
58
58
 
59
59
  &--security {
60
60
  color: #ff4d4f;
61
- font-weight: $FONT_WEIGHT_MEDIUM;
61
+ font-weight: 500;
62
62
  }
63
63
 
64
64
  span:first-of-type {
65
65
  font-weight: 600;
66
- margin-left: $CAP_SPACE_02;
66
+ margin-left: 2px;
67
67
  }
68
68
  }
69
69
 
@@ -72,7 +72,7 @@
72
72
  border: none;
73
73
 
74
74
  &:last-child {
75
- border-radius: 0 0 $CAP_SPACE_06 $CAP_SPACE_06;
75
+ border-radius: 0 0 6px 6px;
76
76
  }
77
77
  }
78
78
 
@@ -123,8 +123,8 @@
123
123
  &__title {
124
124
  display: flex;
125
125
  align-items: center;
126
- gap: $CAP_SPACE_08;
127
- font-weight: $FONT_WEIGHT_MEDIUM;
126
+ gap: 8px;
127
+ font-weight: 500;
128
128
  }
129
129
 
130
130
  &__issues {
@@ -133,41 +133,41 @@
133
133
  }
134
134
 
135
135
  &__sanitization {
136
- border-top: 1px solid $CAP_COLOR_16;
136
+ border-top: 1px solid #d9d9d9;
137
137
  background: #f9f9f9;
138
138
  }
139
139
 
140
140
  &__sanitization-header {
141
141
  display: flex;
142
142
  align-items: center;
143
- gap: $CAP_SPACE_08;
144
- padding: $CAP_SPACE_12 $CAP_SPACE_16;
145
- font-weight: $FONT_WEIGHT_MEDIUM;
143
+ gap: 8px;
144
+ padding: 12px 16px;
145
+ font-weight: 500;
146
146
  color: #666;
147
147
  font-size: 13px;
148
148
  }
149
149
 
150
150
  &__sanitization-list {
151
- padding: 0 $CAP_SPACE_16 $CAP_SPACE_12;
151
+ padding: 0 16px 12px;
152
152
  }
153
153
 
154
154
  &__sanitization-item {
155
- padding: $CAP_SPACE_04 0;
156
- font-size: $CAP_SPACE_12;
155
+ padding: 4px 0;
156
+ font-size: 12px;
157
157
  color: #8c8c8c;
158
158
  }
159
159
  }
160
160
 
161
161
  .validation-issue {
162
162
  display: flex;
163
- gap: $CAP_SPACE_12;
164
- padding: $CAP_SPACE_12 $CAP_SPACE_16;
163
+ gap: 12px;
164
+ padding: 12px 16px;
165
165
  border-bottom: 1px solid #f0f0f0;
166
166
  cursor: pointer;
167
167
  transition: background-color 0.2s;
168
168
 
169
169
  &:hover {
170
- background: $CAP_G21;
170
+ background: #fafafa;
171
171
  }
172
172
 
173
173
  &:last-child {
@@ -189,22 +189,6 @@
189
189
  &__icon {
190
190
  flex-shrink: 0;
191
191
  margin-top: 2px;
192
-
193
- &--error {
194
- color: #ff4d4f;
195
- }
196
-
197
- &--info {
198
- color: #1890ff;
199
- }
200
-
201
- &--warning {
202
- color: #faad14;
203
- }
204
-
205
- &--security {
206
- color: #ff4d4f;
207
- }
208
192
  }
209
193
 
210
194
  &__content {
@@ -216,14 +200,14 @@
216
200
  font-size: 13px;
217
201
  line-height: 1.4;
218
202
  color: #262626;
219
- margin-bottom: $CAP_SPACE_04;
203
+ margin-bottom: 4px;
220
204
  word-break: break-word;
221
205
  }
222
206
 
223
207
  &__meta {
224
208
  display: flex;
225
209
  flex-wrap: wrap;
226
- gap: $CAP_SPACE_08;
210
+ gap: 8px;
227
211
  font-size: 11px;
228
212
  color: #8c8c8c;
229
213
  }
@@ -246,9 +230,9 @@
246
230
  &__source {
247
231
  display: flex;
248
232
  align-items: center;
249
- gap: $CAP_SPACE_04;
233
+ gap: 4px;
250
234
  background: #f0f0f0;
251
- padding: $CAP_SPACE_02 $CAP_SPACE_06;
235
+ padding: 2px 6px;
252
236
  border-radius: 3px;
253
237
  }
254
238
  }
@@ -21,14 +21,13 @@ import ShieldOutlined from '@ant-design/icons/ShieldOutlined';
21
21
  import BugOutlined from '@ant-design/icons/BugOutlined';
22
22
  import CodeOutlined from '@ant-design/icons/CodeOutlined';
23
23
  import EyeInvisibleOutlined from '@ant-design/icons/EyeInvisibleOutlined';
24
- import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
24
+ import CheckCircleOutlined from '@ant-design/icons/CheckCircleOutlined';
25
25
 
26
26
  import messages from './messages';
27
- import { BLOCKING_ERROR_RULE_IDS } from '../../constants';
28
27
  import './_validationPanel.scss';
29
- import { SEVERITY } from './constants';
30
28
 
31
29
  const { Panel } = Collapse;
30
+
32
31
  /**
33
32
  * ValidationPanel Component
34
33
  */
@@ -38,7 +37,7 @@ const ValidationPanel = ({
38
37
  onErrorClick,
39
38
  showLineNumbers = true,
40
39
  groupBySource = false,
41
- variant = 'email',
40
+ variant = 'email'
42
41
  }) => {
43
42
  const [activeKeys, setActiveKeys] = useState(['errors', 'warnings']);
44
43
 
@@ -57,50 +56,31 @@ const ValidationPanel = ({
57
56
  groups[source].push(issue);
58
57
  return groups;
59
58
  }, {});
59
+ } else {
60
+ return {
61
+ errors: allIssues.filter(issue => issue.severity === 'error'),
62
+ warnings: allIssues.filter(issue => issue.severity === 'warning'),
63
+ info: allIssues.filter(issue => issue.severity === 'info')
64
+ };
60
65
  }
61
- return {
62
- errors: allIssues.filter((issue) => issue.severity === SEVERITY.ERROR),
63
- warnings: allIssues.filter((issue) => issue.severity === SEVERITY.WARNING),
64
- info: allIssues.filter((issue) => issue.severity === SEVERITY.INFO),
65
- };
66
66
  }, [validation, groupBySource]);
67
67
 
68
- // Check if an issue is a blocking error (API error, Rule Group #1, or client-side Liquid validation errors)
69
- const isBlockingError = (issue) => {
70
- const { rule, source, severity } = issue || {};
71
- // API errors are blocking
72
- if (rule === 'liquid-api-validation' || rule === 'standard-api-validation') {
73
- return true;
74
- }
75
- // Client-side Liquid validation errors are blocking (genuine syntax errors)
76
- if (source === 'liquid-validator' && severity === 'error') {
77
- return true;
78
- }
79
- // Rule Group #1 errors are blocking
80
- if (BLOCKING_ERROR_RULE_IDS.includes(rule)) {
81
- return true;
82
- }
83
- return false;
84
- };
85
-
86
68
  // Get icon for issue type
87
- // Blocking errors use error-icon, warnings use alert-warning
88
- const getIssueIcon = (issue) => {
89
- const { source, severity } = issue || {};
69
+ const getIssueIcon = (severity, source) => {
90
70
  if (source === 'security') {
91
- return <ShieldOutlined className="validation-issue__icon validation-issue__icon--security" />;
92
- }
93
-
94
- // Only show error icon for blocking errors (API errors or Rule Group #1)
95
- if (isBlockingError(issue)) {
96
- return <CapIcon type="error-icon" className="validation-issue__icon validation-issue__icon--error" />;
71
+ return <ShieldOutlined style={{ color: '#ff4d4f' }} />;
97
72
  }
98
73
 
99
- // All other issues show as warnings
100
- if (severity === SEVERITY.INFO) {
101
- return <CapIcon type="info" className="validation-issue__icon validation-issue__icon--info" />;
74
+ switch (severity) {
75
+ case 'error':
76
+ return <ExclamationCircleOutlined style={{ color: '#ff4d4f' }} />;
77
+ case 'warning':
78
+ return <WarningOutlined style={{ color: '#faad14' }} />;
79
+ case 'info':
80
+ return <InfoCircleOutlined style={{ color: '#1890ff' }} />;
81
+ default:
82
+ return <BugOutlined style={{ color: '#666' }} />;
102
83
  }
103
- return <CapIcon type="alert-warning" className="validation-issue__icon validation-issue__icon--warning" />;
104
84
  };
105
85
 
106
86
  // Get source icon
@@ -126,7 +106,7 @@ const ValidationPanel = ({
126
106
  line: issue.line,
127
107
  column: issue.column || 1,
128
108
  message: issue.message,
129
- severity: issue.severity,
109
+ severity: issue.severity
130
110
  });
131
111
  }
132
112
  };
@@ -146,7 +126,7 @@ const ValidationPanel = ({
146
126
  }}
147
127
  >
148
128
  <div className="validation-issue__icon">
149
- {getIssueIcon(issue)}
129
+ {getIssueIcon(issue.severity, issue.source)}
150
130
  </div>
151
131
 
152
132
  <div className="validation-issue__content">
@@ -157,12 +137,10 @@ const ValidationPanel = ({
157
137
  <div className="validation-issue__meta">
158
138
  {showLineNumbers && issue.line && (
159
139
  <span className="validation-issue__location">
160
- <FormattedMessage
161
- {...messages.lineColumn}
162
- values={{
163
- line: issue.line,
164
- column: issue.column || 1,
165
- }} />
140
+ <FormattedMessage {...messages.lineColumn} values={{
141
+ line: issue.line,
142
+ column: issue.column || 1
143
+ }} />
166
144
  </span>
167
145
  )}
168
146
 
@@ -184,24 +162,17 @@ const ValidationPanel = ({
184
162
  );
185
163
 
186
164
  // Render panel header with count
187
- const renderPanelHeader = (title, count, severity, issues = []) => {
188
- // Check if any issue in this group is a blocking error
189
- const hasBlocking = issues.some((issue) => isBlockingError(issue));
190
- // Use blocking error icon only if there are blocking errors, otherwise use warning icon
191
- const iconIssue = hasBlocking ? { rule: 'blocking', source: 'blocking' } : { severity: 'warning' };
192
-
193
- return (
194
- <div className="validation-panel__header">
195
- <span className="validation-panel__title">
196
- {getIssueIcon(iconIssue)}
197
- <FormattedMessage {...title} />
198
- </span>
199
- {count > 0 && (
200
- <Badge count={count} style={{ backgroundColor: getSeverityColor(severity) }} />
201
- )}
202
- </div>
203
- );
204
- };
165
+ const renderPanelHeader = (title, count, severity) => (
166
+ <div className="validation-panel__header">
167
+ <span className="validation-panel__title">
168
+ {getIssueIcon(severity)}
169
+ <FormattedMessage {...title} />
170
+ </span>
171
+ {count > 0 && (
172
+ <Badge count={count} style={{ backgroundColor: getSeverityColor(severity) }} />
173
+ )}
174
+ </div>
175
+ );
205
176
 
206
177
  // Get severity color
207
178
  const getSeverityColor = (severity) => {
@@ -270,14 +241,14 @@ const ValidationPanel = ({
270
241
  : messages[key] || { id: `htmlEditor.validation.${key}`, defaultMessage: key };
271
242
 
272
243
  const severity = isSourceGroup
273
- ? (issues.find((i) => i.severity === 'error') ? 'error'
274
- : issues.find((i) => i.severity === 'warning') ? 'warning' : 'info')
244
+ ? (issues.find(i => i.severity === 'error') ? 'error' :
245
+ issues.find(i => i.severity === 'warning') ? 'warning' : 'info')
275
246
  : key;
276
247
 
277
248
  return (
278
249
  <Panel
279
250
  key={key}
280
- header={renderPanelHeader(title, issues.length, severity, issues)}
251
+ header={renderPanelHeader(title, issues.length, severity)}
281
252
  className={`validation-panel__panel validation-panel__panel--${severity}`}
282
253
  >
283
254
  <div className="validation-panel__issues">
@@ -320,7 +291,7 @@ ValidationPanel.propTypes = {
320
291
  onErrorClick: PropTypes.func,
321
292
  showLineNumbers: PropTypes.bool,
322
293
  groupBySource: PropTypes.bool,
323
- variant: PropTypes.oneOf(['email', 'inapp']),
294
+ variant: PropTypes.oneOf(['email', 'inapp'])
324
295
  };
325
296
 
326
297
  export default ValidationPanel;