@capillarytech/creatives-library 8.0.255-alpha.4 → 8.0.255

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 (278) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -2
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +10 -5
  7. package/services/tests/api.test.js +34 -0
  8. package/translations/en.json +3 -4
  9. package/utils/common.js +5 -6
  10. package/utils/commonUtils.js +28 -5
  11. package/utils/tests/commonUtil.test.js +224 -0
  12. package/utils/tests/transformerUtils.test.js +0 -297
  13. package/utils/transformTemplateConfig.js +0 -10
  14. package/utils/transformerUtils.js +0 -40
  15. package/v2Components/CapDeviceContent/index.js +61 -56
  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 +6 -1
  21. package/v2Components/CapTagListWithInput/index.js +5 -1
  22. package/v2Components/CapTagListWithInput/messages.js +1 -1
  23. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  24. package/v2Components/ErrorInfoNote/constants.js +1 -0
  25. package/v2Components/ErrorInfoNote/index.js +457 -72
  26. package/v2Components/ErrorInfoNote/messages.js +36 -6
  27. package/v2Components/ErrorInfoNote/style.scss +282 -6
  28. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  29. package/v2Components/HtmlEditor/HTMLEditor.js +547 -94
  30. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
  31. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1441 -133
  32. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  33. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  34. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  35. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +23 -102
  36. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -140
  37. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  38. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  39. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
  40. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +4 -4
  41. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  45. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  46. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  47. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
  48. package/v2Components/HtmlEditor/components/PreviewPane/index.js +22 -43
  49. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  50. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +1 -0
  51. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
  52. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +50 -34
  53. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
  54. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +70 -41
  55. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +255 -0
  56. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +364 -0
  57. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  58. package/v2Components/HtmlEditor/constants.js +42 -20
  59. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  60. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +103 -0
  61. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  62. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  63. package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
  64. package/v2Components/HtmlEditor/index.js +1 -1
  65. package/v2Components/HtmlEditor/messages.js +92 -94
  66. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
  67. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
  68. package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
  69. package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
  70. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
  71. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  72. package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
  73. package/v2Components/HtmlEditor/utils/validationConstants.js +40 -0
  74. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  75. package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
  76. package/v2Components/TemplatePreview/index.js +47 -32
  77. package/v2Components/TemplatePreview/messages.js +4 -0
  78. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  79. package/v2Containers/App/constants.js +0 -5
  80. package/v2Containers/BeeEditor/index.js +172 -90
  81. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
  82. package/v2Containers/BeePopupEditor/constants.js +10 -0
  83. package/v2Containers/BeePopupEditor/index.js +194 -0
  84. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  85. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +3 -4
  86. package/v2Containers/CreativesContainer/SlideBoxContent.js +129 -107
  87. package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
  88. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
  89. package/v2Containers/CreativesContainer/constants.js +1 -3
  90. package/v2Containers/CreativesContainer/index.js +239 -214
  91. package/v2Containers/CreativesContainer/messages.js +8 -4
  92. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
  93. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  94. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -354
  95. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
  96. package/v2Containers/Email/actions.js +7 -0
  97. package/v2Containers/Email/constants.js +5 -1
  98. package/v2Containers/Email/index.js +234 -29
  99. package/v2Containers/Email/messages.js +32 -0
  100. package/v2Containers/Email/reducer.js +12 -1
  101. package/v2Containers/Email/sagas.js +61 -7
  102. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  103. package/v2Containers/Email/tests/reducer.test.js +46 -0
  104. package/v2Containers/Email/tests/sagas.test.js +320 -29
  105. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1285 -0
  106. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +211 -21
  107. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  108. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1880 -0
  109. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  110. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  111. package/v2Containers/EmailWrapper/constants.js +2 -0
  112. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
  113. package/v2Containers/EmailWrapper/index.js +103 -23
  114. package/v2Containers/EmailWrapper/messages.js +65 -1
  115. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
  116. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
  117. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  118. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  119. package/v2Containers/InApp/actions.js +7 -0
  120. package/v2Containers/InApp/constants.js +20 -4
  121. package/v2Containers/InApp/index.js +802 -359
  122. package/v2Containers/InApp/index.scss +4 -3
  123. package/v2Containers/InApp/messages.js +7 -3
  124. package/v2Containers/InApp/reducer.js +21 -3
  125. package/v2Containers/InApp/sagas.js +29 -9
  126. package/v2Containers/InApp/selectors.js +25 -5
  127. package/v2Containers/InApp/tests/index.test.js +154 -50
  128. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  129. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  130. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  131. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
  132. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  133. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
  134. package/v2Containers/InAppWrapper/constants.js +16 -0
  135. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  136. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  137. package/v2Containers/InAppWrapper/index.js +148 -0
  138. package/v2Containers/InAppWrapper/messages.js +49 -0
  139. package/v2Containers/InappAdvance/index.js +1099 -0
  140. package/v2Containers/InappAdvance/index.scss +10 -0
  141. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  142. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +15 -36
  143. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +8 -8
  144. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +77 -100
  145. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +63 -72
  146. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +190 -250
  147. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +12 -16
  148. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +40 -48
  149. package/v2Containers/TagList/index.js +62 -19
  150. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  151. package/v2Containers/Templates/_templates.scss +56 -202
  152. package/v2Containers/Templates/actions.js +1 -2
  153. package/v2Containers/Templates/constants.js +0 -1
  154. package/v2Containers/Templates/index.js +123 -278
  155. package/v2Containers/Templates/messages.js +4 -24
  156. package/v2Containers/Templates/reducer.js +0 -2
  157. package/v2Containers/Templates/tests/index.test.js +0 -10
  158. package/v2Containers/TemplatesV2/index.js +7 -15
  159. package/v2Containers/TemplatesV2/messages.js +0 -4
  160. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +768 -1272
  161. package/utils/imageUrlUpload.js +0 -141
  162. package/v2Components/CapImageUrlUpload/constants.js +0 -26
  163. package/v2Components/CapImageUrlUpload/index.js +0 -365
  164. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  165. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  166. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  167. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
  168. package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
  169. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
  170. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  171. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -145
  172. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -164
  173. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -463
  174. package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
  175. package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
  176. package/v2Containers/WebPush/Create/components/MediaSection.js +0 -142
  177. package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
  178. package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
  179. package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
  180. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
  181. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
  182. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
  183. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
  184. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -86
  185. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
  186. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
  187. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
  188. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
  189. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
  190. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  191. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  192. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  193. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
  194. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  195. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  196. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -78
  197. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -138
  198. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
  199. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
  200. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
  201. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
  202. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
  203. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
  204. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
  205. package/v2Containers/WebPush/Create/index.js +0 -1148
  206. package/v2Containers/WebPush/Create/index.scss +0 -134
  207. package/v2Containers/WebPush/Create/messages.js +0 -203
  208. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
  209. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
  210. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
  211. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
  212. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
  213. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
  214. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  215. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  216. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
  217. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
  218. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  219. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  220. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  221. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  222. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
  223. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
  224. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  225. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  226. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
  227. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
  228. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -47
  229. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -141
  230. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  231. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
  232. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
  233. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
  234. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
  235. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
  236. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -81
  237. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
  238. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
  239. package/v2Containers/WebPush/Create/preview/constants.js +0 -637
  240. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
  241. package/v2Containers/WebPush/Create/preview/preview.scss +0 -351
  242. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
  243. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  244. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  245. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  246. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
  247. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  248. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  249. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  250. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
  251. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
  252. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  253. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
  254. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
  255. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  256. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
  257. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  258. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
  259. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
  260. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
  261. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  262. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
  263. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
  264. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
  265. package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
  266. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
  267. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  268. package/v2Containers/WebPush/Create/utils/validation.js +0 -75
  269. package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
  270. package/v2Containers/WebPush/actions.js +0 -60
  271. package/v2Containers/WebPush/constants.js +0 -132
  272. package/v2Containers/WebPush/index.js +0 -2
  273. package/v2Containers/WebPush/reducer.js +0 -104
  274. package/v2Containers/WebPush/sagas.js +0 -119
  275. package/v2Containers/WebPush/selectors.js +0 -65
  276. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  277. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  278. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -0,0 +1,255 @@
1
+ /**
2
+ * ValidationTabs Styles
3
+ */
4
+
5
+ @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
6
+
7
+ .validation-tabs {
8
+ overflow-y: hidden;
9
+ width: 100%;
10
+ border-radius: 0.25rem;
11
+ box-sizing: border-box;
12
+
13
+ &__header {
14
+ display: flex;
15
+ align-items: flex-start;
16
+ justify-content: space-between;
17
+ width: 100%;
18
+ }
19
+
20
+ &__tabs {
21
+ flex: 1;
22
+
23
+ // Override CapTab styles for proper spacing
24
+ .cap-tab-v2 {
25
+ .ant-tabs-bar {
26
+ padding: 0.5rem 0.5rem;
27
+ background-color: $CAP_COLOR_05;
28
+ }
29
+ .ant-tabs-nav {
30
+ margin-bottom: 0;
31
+
32
+ &::before {
33
+ border-bottom: none; // Remove bottom border
34
+ }
35
+ }
36
+
37
+ .ant-tabs-tab {
38
+ padding: 0.5rem 0.75rem; // Add horizontal padding for spacing
39
+ margin-right: 0; // Remove margin, use padding instead
40
+
41
+ color: $CAP_G03;
42
+ font-size: 0.875rem;
43
+ font-weight: 400;
44
+ line-height: 1;
45
+ letter-spacing: 0;
46
+ background-color: $CAP_COLOR_05;
47
+ border-radius: 0.25rem;
48
+ border-bottom: none; // Remove bottom border
49
+
50
+ & + .ant-tabs-tab {
51
+ margin-left: 1.5rem; // Add space between tabs
52
+ }
53
+
54
+ &:hover {
55
+ color: $CAP_COLOR_05;
56
+ background-color: $CAP_COLOR_05;
57
+ }
58
+
59
+ &.ant-tabs-tab-active {
60
+ .ant-tabs-tab-btn {
61
+ color: $CAP_COLOR_05;
62
+ font-weight: 600;
63
+ }
64
+ }
65
+ }
66
+
67
+ .ant-tabs-ink-bar {
68
+ display: none; // Hide the ink bar (bottom border indicator)
69
+ }
70
+
71
+ .ant-tabs-content-holder {
72
+ padding-top: 0.25rem; // Reduced from 0.5rem
73
+ padding-bottom: 0; // No bottom padding
74
+ }
75
+ }
76
+ }
77
+
78
+ &__tab-label {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 0.25rem;
82
+ }
83
+
84
+ &__tab-count {
85
+ color: inherit;
86
+ }
87
+
88
+ &__actions {
89
+ display: flex;
90
+ align-items: center;
91
+ flex-shrink: 0;
92
+ padding-top: 0.5rem;
93
+ background-color: $CAP_COLOR_05;
94
+ }
95
+
96
+ &__close {
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ width: 1.9rem;
101
+ height: 2.3rem;
102
+ padding: 0;
103
+ background: transparent;
104
+ border: none;
105
+ border-radius: 0.25rem;
106
+ cursor: pointer;
107
+ color: $CAP_G03;
108
+ transition: all 0.2s ease;
109
+
110
+ // &:hover {
111
+ // background-color: rgba($CAP_COLOR_05, 0.1);
112
+ // color: $CAP_COLOR_05;
113
+ // }
114
+
115
+ .cap-icon-v2 {
116
+ font-size: 0.875rem;
117
+ }
118
+ }
119
+
120
+ &__content {
121
+ max-height: 15rem; // Limit height for many errors
122
+ overflow-y: auto;
123
+ padding-bottom: 0; // Remove bottom padding completely
124
+
125
+ // Custom scrollbar
126
+ &::-webkit-scrollbar {
127
+ width: 0.375rem;
128
+ }
129
+
130
+ &::-webkit-scrollbar-track {
131
+ background: transparent;
132
+ }
133
+
134
+ &::-webkit-scrollbar-thumb {
135
+ background-color: $CAP_G06;
136
+ border-radius: 0.1875rem;
137
+
138
+ &:hover {
139
+ background-color: $CAP_G04;
140
+ }
141
+ }
142
+ }
143
+
144
+ &__item {
145
+ display: flex;
146
+ align-items: flex-start;
147
+ gap: 0.5rem;
148
+ padding: 0.5rem 0.5rem; // Reduced from 0.375rem
149
+ margin-bottom: 3px;
150
+
151
+ &:last-child {
152
+ border-bottom: none;
153
+ padding-bottom: 0.25rem; // Minimal padding on last item
154
+ }
155
+
156
+ &--error {
157
+ .validation-tabs__icon--error {
158
+ color: $CAP_RED;
159
+ }
160
+ }
161
+
162
+ &--warning {
163
+ .validation-tabs__icon--warning {
164
+ color: $CAP_YELLOW;
165
+ }
166
+ }
167
+ }
168
+
169
+ &__item-icon {
170
+ flex-shrink: 0;
171
+ display: flex;
172
+ align-items: center;
173
+ padding-top: 0.125rem;
174
+ }
175
+
176
+ &__icon {
177
+ font-size: 0.875rem;
178
+
179
+ &--error {
180
+ color: $CAP_RED;
181
+ }
182
+
183
+ &--warning {
184
+ color: $CAP_YELLOW;
185
+ }
186
+ }
187
+
188
+ &__item-content {
189
+ flex: 1;
190
+ display: flex;
191
+ flex-wrap: wrap;
192
+ align-items: baseline;
193
+ gap: 0.25rem;
194
+ font-size: 0.75rem;
195
+ line-height: 2;
196
+ color: $CAP_G01;
197
+ }
198
+
199
+ &__item-message {
200
+ color: $CAP_G01;
201
+ }
202
+
203
+ &__item-location {
204
+ color: $CAP_G03;
205
+ white-space: nowrap;
206
+ }
207
+
208
+ &__item-rule {
209
+ color: $CAP_G04;
210
+ font-family: monospace;
211
+ font-size: 0.6875rem;
212
+ }
213
+
214
+ &__item-navigate {
215
+ flex-shrink: 0;
216
+ display: flex;
217
+ align-items: center;
218
+ width: 1.7rem;
219
+ height: 1.7rem;
220
+ padding: 0;
221
+ background: transparent;
222
+ border: none;
223
+ border-radius: 0.25rem;
224
+ cursor: pointer;
225
+ color: $CAP_G04;
226
+ transition: all 0.2s ease;
227
+
228
+ .anticon {
229
+ font-size: 1rem; // Increased icon size
230
+ }
231
+ }
232
+ }
233
+
234
+ // Responsive adjustments
235
+ @media (max-width: 768px) {
236
+ .validation-tabs {
237
+ padding: 0.375rem 0.5rem;
238
+
239
+ &__tabs {
240
+ .ant-tabs-tab {
241
+ margin-right: 1rem;
242
+ font-size: 0.8125rem;
243
+ background-color: $CAP_COLOR_05;
244
+ }
245
+ }
246
+
247
+ &__content {
248
+ max-height: 10rem;
249
+ }
250
+
251
+ &__item-content {
252
+ font-size: 0.6875rem;
253
+ }
254
+ }
255
+ }
@@ -0,0 +1,364 @@
1
+ /**
2
+ * ValidationTabs Component
3
+ *
4
+ * Displays validation errors in a tabbed interface with 3 categories:
5
+ * - HTML issues: General HTML/CSS validation errors and warnings
6
+ * - Label issues: Tag syntax errors (open/close tags, attributes, brackets)
7
+ * - Liquid issues: Liquid expression errors (shown when liquid content is detected, even if liquid feature is disabled)
8
+ */
9
+
10
+ import React, { useState, useMemo } from 'react';
11
+ import PropTypes from 'prop-types';
12
+ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
13
+
14
+ // Cap UI Library
15
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
16
+ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
17
+ import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
18
+
19
+ // Messages
20
+ import messages from './messages';
21
+ import { BLOCKING_ERROR_RULE_IDS } from '../../constants';
22
+ import { ISSUE_SOURCES, LABEL_ISSUE_PATTERNS } from '../../utils/validationConstants';
23
+
24
+ // Styles
25
+ import './_validationTabs.scss';
26
+ import {StyledCapTab} from '../../../../v2Containers/MobilePushNew/style';
27
+
28
+ /**
29
+ * Categorize issues into HTML, Label, and Liquid categories
30
+ */
31
+ const categorizeIssues = (allIssues) => {
32
+ const htmlIssues = [];
33
+ const labelIssues = [];
34
+ const liquidIssues = [];
35
+
36
+ allIssues.forEach((issue) => {
37
+ const { source, rule, message } = issue;
38
+ const messageLower = (message || '').toLowerCase();
39
+ const ruleLower = (rule || '').toLowerCase();
40
+
41
+ // Check if it's a Liquid issue - ONLY by source, not by message content
42
+ // This prevents false positives where HTML errors mention liquid syntax
43
+ if (source === ISSUE_SOURCES.LIQUID) {
44
+ liquidIssues.push(issue);
45
+ return;
46
+ }
47
+
48
+ // Check if it's a Label (tag syntax) issue
49
+ const isLabelIssue = LABEL_ISSUE_PATTERNS.some(
50
+ (pattern) => messageLower.includes(pattern.toLowerCase())
51
+ || ruleLower.includes(pattern.toLowerCase()),
52
+ );
53
+
54
+ if (isLabelIssue) {
55
+ labelIssues.push(issue);
56
+ return;
57
+ }
58
+
59
+ // Default to HTML issues
60
+ htmlIssues.push(issue);
61
+ });
62
+
63
+ return { htmlIssues, labelIssues, liquidIssues };
64
+ };
65
+
66
+ /**
67
+ * Check if an issue is a blocking error (API error, Rule Group #1, or client-side Liquid validation errors)
68
+ */
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
+ /**
87
+ * Get icon based on whether issue is blocking error or warning
88
+ * Blocking errors use error-icon, warnings use alert-warning
89
+ */
90
+ const getSeverityIcon = (issue) => {
91
+ if (isBlockingError(issue)) {
92
+ return <CapIcon type="error-icon" className="validation-tabs__icon validation-tabs__icon--error" />;
93
+ }
94
+ // All other issues (warnings, non-blocking) use warning icon
95
+ return <CapIcon type="alert-warning" className="validation-tabs__icon validation-tabs__icon--warning" />;
96
+ };
97
+
98
+ /**
99
+ * ValidationTabContent - Renders the content for each tab
100
+ */
101
+ const ValidationTabContent = ({
102
+ issues,
103
+ onErrorClick,
104
+ }) => {
105
+ if (!issues || issues.length === 0) {
106
+ return null;
107
+ }
108
+
109
+ const handleNavigateClick = (issue, e) => {
110
+ e.stopPropagation();
111
+ if (onErrorClick) {
112
+ // Always call onErrorClick to acknowledge the error (enables buttons)
113
+ // If line number exists, navigate to it; otherwise just acknowledge and focus editor
114
+ onErrorClick({
115
+ line: issue.line || 1, // Default to line 1 if no line number (for API errors)
116
+ column: issue.column || 1,
117
+ message: issue.message,
118
+ severity: issue.severity,
119
+ });
120
+ }
121
+ };
122
+
123
+ return (
124
+ <div className="validation-tabs__content">
125
+ {issues.map((issue, index) => {
126
+ const {
127
+ message, line, column,
128
+ } = issue;
129
+ const key = `${message}-${line}-${column}-${index}`;
130
+ const isBlocking = isBlockingError(issue);
131
+ const displaySeverity = isBlocking ? 'error' : 'warning';
132
+
133
+ return (
134
+ <div
135
+ key={key}
136
+ className={`validation-tabs__item validation-tabs__item--${displaySeverity}`}
137
+ >
138
+ <div className="validation-tabs__item-icon">
139
+ {getSeverityIcon(issue)}
140
+ </div>
141
+ <div className="validation-tabs__item-content">
142
+ <span className="validation-tabs__item-message">
143
+ {message}
144
+ </span>
145
+ {line && (
146
+ <span className="validation-tabs__item-location">
147
+ <FormattedMessage
148
+ {...messages.lineChar}
149
+ values={{ line, char: column || 1 }}
150
+ />
151
+ </span>
152
+ )}
153
+ </div>
154
+ {/* Always show redirection icon for errors (even API errors without line numbers) */}
155
+ {/* Clicking it acknowledges the error and enables buttons */}
156
+ <CapTooltip title={line ? `Line ${line}, Char ${column || 1}` : 'Click to acknowledge error and focus editor'}>
157
+ <button
158
+ type="button"
159
+ className="validation-tabs__item-navigate"
160
+ onClick={(e) => handleNavigateClick(issue, e)}
161
+ aria-label={line ? `Line ${line}, Char ${column || 1}` : 'Acknowledge error'}
162
+ >
163
+ <CapIcon type="redirection" />
164
+ </button>
165
+ </CapTooltip>
166
+ </div>
167
+ );
168
+ })}
169
+ </div>
170
+ );
171
+ };
172
+
173
+ ValidationTabContent.propTypes = {
174
+ issues: PropTypes.array,
175
+ onErrorClick: PropTypes.func,
176
+ };
177
+
178
+ ValidationTabContent.defaultProps = {
179
+ issues: [],
180
+ onErrorClick: null,
181
+ };
182
+
183
+ /**
184
+ * ValidationTabs Component
185
+ */
186
+ const ValidationTabs = ({
187
+ intl,
188
+ validation,
189
+ onErrorClick,
190
+ onClose,
191
+ className,
192
+ }) => {
193
+ const [activeKey, setActiveKey] = useState(null);
194
+
195
+ // Categorize issues
196
+ const { htmlIssues, labelIssues, liquidIssues } = useMemo(() => {
197
+ if (!validation) {
198
+ return { htmlIssues: [], labelIssues: [], liquidIssues: [] };
199
+ }
200
+
201
+ // Get all issues from validation
202
+ const allIssues = validation.getAllIssues ? validation.getAllIssues() : [];
203
+ const categorized = categorizeIssues(allIssues);
204
+ return categorized;
205
+ }, [validation]);
206
+
207
+ // Calculate counts
208
+ const htmlCount = htmlIssues.length;
209
+ const labelCount = labelIssues.length;
210
+ const liquidCount = liquidIssues.length;
211
+ // Include liquid issues in total count even when liquid is disabled
212
+ // This ensures liquid errors are shown when liquid content is detected but feature is disabled
213
+ const totalCount = htmlCount + labelCount + liquidCount;
214
+
215
+ // Set default active key when issues change
216
+ useMemo(() => {
217
+ if (htmlCount > 0 && !activeKey) {
218
+ setActiveKey('html');
219
+ } else if (labelCount > 0 && !activeKey) {
220
+ setActiveKey('label');
221
+ } else if (liquidCount > 0 && !activeKey) {
222
+ // Show liquid tab even when liquid is disabled if liquid content is detected
223
+ setActiveKey('liquid');
224
+ }
225
+ }, [htmlCount, labelCount, liquidCount, activeKey]);
226
+
227
+ // Don't render if no issues
228
+ if (totalCount === 0) {
229
+ return null;
230
+ }
231
+
232
+ // Build tab panes (CapTab uses 'panes' with 'tab' and 'content' properties)
233
+ const tabPanes = [];
234
+
235
+ if (htmlCount > 0) {
236
+ tabPanes.push({
237
+ key: 'html',
238
+ tab: (
239
+ <CapTooltip title={`${intl.formatMessage(messages.htmlIssues)} (${htmlCount})`}>
240
+ <span className="validation-tabs__tab-label">
241
+ <FormattedMessage {...messages.htmlIssues} />
242
+ <span className="validation-tabs__tab-count">
243
+ (
244
+ {htmlCount}
245
+ )
246
+ </span>
247
+ </span>
248
+ </CapTooltip>
249
+ ),
250
+ content: (
251
+ <ValidationTabContent
252
+ issues={htmlIssues}
253
+ onErrorClick={onErrorClick}
254
+ intl={intl}
255
+ />
256
+ ),
257
+ });
258
+ }
259
+
260
+ if (labelCount > 0) {
261
+ tabPanes.push({
262
+ key: 'label',
263
+ tab: (
264
+ <CapTooltip title={`${intl.formatMessage(messages.labelIssues)} (${labelCount})`}>
265
+ <span className="validation-tabs__tab-label">
266
+ <FormattedMessage {...messages.labelIssues} />
267
+ <span className="validation-tabs__tab-count">
268
+ (
269
+ {labelCount}
270
+ )
271
+ </span>
272
+ </span>
273
+ </CapTooltip>
274
+ ),
275
+ content: (
276
+ <ValidationTabContent
277
+ issues={labelIssues}
278
+ onErrorClick={onErrorClick}
279
+ intl={intl}
280
+ />
281
+ ),
282
+ });
283
+ }
284
+
285
+ // Show liquid issues tab even when liquid is disabled if liquid content is detected
286
+ // This allows users to see errors when they add liquid content but liquid feature is not enabled
287
+ if (liquidCount > 0) {
288
+ tabPanes.push({
289
+ key: 'liquid',
290
+ tab: (
291
+ <CapTooltip title={`${intl.formatMessage(messages.liquidIssues)} (${liquidCount})`}>
292
+ <span className="validation-tabs__tab-label">
293
+ <FormattedMessage {...messages.liquidIssues} />
294
+ <span className="validation-tabs__tab-count">
295
+ (
296
+ {liquidCount}
297
+ )
298
+ </span>
299
+ </span>
300
+ </CapTooltip>
301
+ ),
302
+ content: (
303
+ <ValidationTabContent
304
+ issues={liquidIssues}
305
+ onErrorClick={onErrorClick}
306
+ intl={intl}
307
+ />
308
+ ),
309
+ });
310
+ }
311
+
312
+ // Handle close
313
+ const handleClose = () => {
314
+ if (onClose) {
315
+ onClose();
316
+ }
317
+ };
318
+
319
+ return (
320
+ <div className={`validation-tabs ${className || ''}`}>
321
+ <CapRow className="validation-tabs__header">
322
+ <StyledCapTab
323
+ className="validation-tabs__tabs"
324
+ activeKey={activeKey || (tabPanes[0]?.key)}
325
+ onChange={setActiveKey}
326
+ panes={tabPanes}
327
+ />
328
+ <CapRow className="validation-tabs__actions">
329
+ <CapTooltip title={intl.formatMessage(messages.closePanel)}>
330
+ <button
331
+ type="button"
332
+ className="validation-tabs__close"
333
+ onClick={handleClose}
334
+ aria-label={intl.formatMessage(messages.closePanel)}
335
+ >
336
+ <CapIcon type="close" />
337
+ </button>
338
+ </CapTooltip>
339
+ </CapRow>
340
+ </CapRow>
341
+ </div>
342
+ );
343
+ };
344
+
345
+ ValidationTabs.propTypes = {
346
+ intl: intlShape.isRequired,
347
+ validation: PropTypes.shape({
348
+ getAllIssues: PropTypes.func,
349
+ }),
350
+ onErrorClick: PropTypes.func,
351
+ onClose: PropTypes.func,
352
+ isLiquidEnabled: PropTypes.bool,
353
+ className: PropTypes.string,
354
+ };
355
+
356
+ ValidationTabs.defaultProps = {
357
+ validation: null,
358
+ onErrorClick: null,
359
+ onClose: null,
360
+ isLiquidEnabled: false,
361
+ className: '',
362
+ };
363
+
364
+ export default injectIntl(ValidationTabs);
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ValidationTabs Messages
3
+ *
4
+ * Internationalization messages for the ValidationTabs component
5
+ */
6
+
7
+ import { defineMessages } from 'react-intl';
8
+
9
+ const scope = 'app.components.HtmlEditor.ValidationTabs';
10
+
11
+ export default defineMessages({
12
+ // Tab labels
13
+ htmlIssues: {
14
+ id: `${scope}.htmlIssues`,
15
+ defaultMessage: 'HTML issues',
16
+ },
17
+ labelIssues: {
18
+ id: `${scope}.labelIssues`,
19
+ defaultMessage: 'Label issues',
20
+ },
21
+ liquidIssues: {
22
+ id: `${scope}.liquidIssues`,
23
+ defaultMessage: 'Liquid issues',
24
+ },
25
+
26
+ // Error item labels
27
+ syntaxError: {
28
+ id: `${scope}.syntaxError`,
29
+ defaultMessage: 'Syntax Error',
30
+ },
31
+ lineChar: {
32
+ id: `${scope}.lineChar`,
33
+ defaultMessage: 'Line {line}, Char {char}.',
34
+ },
35
+
36
+ // Tooltips
37
+ navigateToError: {
38
+ id: `${scope}.navigateToError`,
39
+ defaultMessage: 'Go to error location',
40
+ },
41
+ closePanel: {
42
+ id: `${scope}.closePanel`,
43
+ defaultMessage: 'Close validation panel',
44
+ },
45
+
46
+ // Liquid documentation
47
+ liquidDocumentation: {
48
+ id: `${scope}.liquidDocumentation`,
49
+ defaultMessage: 'Liquid documentation',
50
+ },
51
+ });