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

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 (255) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/config/app.js +1 -1
  4. package/constants/unified.js +2 -2
  5. package/initialReducer.js +0 -2
  6. package/package.json +1 -1
  7. package/services/api.js +5 -10
  8. package/services/tests/api.test.js +0 -18
  9. package/translations/en.json +4 -3
  10. package/utils/common.js +6 -5
  11. package/utils/commonUtils.js +1 -14
  12. package/utils/imageUrlUpload.js +141 -0
  13. package/utils/tests/commonUtil.test.js +0 -224
  14. package/utils/transformTemplateConfig.js +10 -0
  15. package/v2Components/CapDeviceContent/index.js +56 -61
  16. package/v2Components/CapImageUpload/constants.js +2 -0
  17. package/v2Components/CapImageUpload/index.js +65 -16
  18. package/v2Components/CapImageUpload/index.scss +4 -1
  19. package/v2Components/CapImageUpload/messages.js +5 -1
  20. package/v2Components/CapImageUrlUpload/constants.js +26 -0
  21. package/v2Components/CapImageUrlUpload/index.js +365 -0
  22. package/v2Components/CapImageUrlUpload/index.scss +35 -0
  23. package/v2Components/CapImageUrlUpload/messages.js +47 -0
  24. package/v2Components/CapTagList/index.js +1 -6
  25. package/v2Components/CapTagListWithInput/index.js +1 -5
  26. package/v2Components/CapTagListWithInput/messages.js +1 -1
  27. package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
  28. package/v2Components/ErrorInfoNote/index.js +72 -412
  29. package/v2Components/ErrorInfoNote/messages.js +0 -22
  30. package/v2Components/ErrorInfoNote/style.scss +2 -279
  31. package/v2Components/HtmlEditor/HTMLEditor.js +89 -210
  32. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1132
  33. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +12 -17
  34. package/v2Components/HtmlEditor/_htmlEditor.scss +23 -8
  35. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  36. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +101 -13
  37. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +139 -148
  38. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
  39. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  40. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  41. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -1
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
  45. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  46. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
  47. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +6 -3
  48. package/v2Components/HtmlEditor/components/PreviewPane/index.js +11 -10
  49. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  50. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +62 -87
  51. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -49
  52. package/v2Components/HtmlEditor/constants.js +20 -29
  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/index.js +1 -1
  57. package/v2Components/HtmlEditor/messages.js +85 -95
  58. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +101 -99
  59. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
  60. package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -34
  61. package/v2Components/MobilePushPreviewV2/index.js +7 -32
  62. package/v2Components/TemplatePreview/_templatePreview.scss +24 -44
  63. package/v2Components/TemplatePreview/index.js +32 -47
  64. package/v2Components/TemplatePreview/messages.js +0 -4
  65. package/v2Components/TestAndPreviewSlidebox/index.js +25 -31
  66. package/v2Containers/App/constants.js +5 -0
  67. package/v2Containers/BeeEditor/index.js +80 -82
  68. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +4 -3
  69. package/v2Containers/CreativesContainer/SlideBoxContent.js +118 -148
  70. package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -9
  71. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
  72. package/v2Containers/CreativesContainer/constants.js +2 -1
  73. package/v2Containers/CreativesContainer/index.js +41 -173
  74. package/v2Containers/CreativesContainer/messages.js +4 -4
  75. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +210 -0
  76. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +354 -38
  77. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -36
  78. package/v2Containers/Email/actions.js +0 -7
  79. package/v2Containers/Email/constants.js +1 -5
  80. package/v2Containers/Email/index.js +0 -13
  81. package/v2Containers/Email/messages.js +0 -32
  82. package/v2Containers/Email/reducer.js +1 -12
  83. package/v2Containers/Email/sagas.js +6 -41
  84. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
  85. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +7 -193
  86. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
  87. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
  88. package/v2Containers/EmailWrapper/constants.js +0 -2
  89. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +67 -436
  90. package/v2Containers/EmailWrapper/index.js +23 -99
  91. package/v2Containers/EmailWrapper/messages.js +1 -61
  92. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +1 -26
  93. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -111
  94. package/v2Containers/InApp/actions.js +0 -7
  95. package/v2Containers/InApp/constants.js +4 -20
  96. package/v2Containers/InApp/index.js +357 -800
  97. package/v2Containers/InApp/index.scss +3 -4
  98. package/v2Containers/InApp/messages.js +3 -7
  99. package/v2Containers/InApp/reducer.js +3 -21
  100. package/v2Containers/InApp/sagas.js +9 -29
  101. package/v2Containers/InApp/selectors.js +5 -25
  102. package/v2Containers/InApp/tests/index.test.js +50 -154
  103. package/v2Containers/InApp/tests/reducer.test.js +0 -34
  104. package/v2Containers/InApp/tests/sagas.test.js +9 -61
  105. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +12 -12
  106. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +8 -8
  107. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +100 -77
  108. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +72 -63
  109. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +184 -150
  110. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +16 -12
  111. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +32 -28
  112. package/v2Containers/TagList/index.js +1 -67
  113. package/v2Containers/Templates/ChannelTypeIllustration.js +13 -1
  114. package/v2Containers/Templates/_templates.scss +202 -56
  115. package/v2Containers/Templates/actions.js +2 -1
  116. package/v2Containers/Templates/constants.js +1 -0
  117. package/v2Containers/Templates/index.js +278 -128
  118. package/v2Containers/Templates/messages.js +24 -4
  119. package/v2Containers/Templates/reducer.js +2 -0
  120. package/v2Containers/Templates/tests/index.test.js +10 -0
  121. package/v2Containers/TemplatesV2/index.js +8 -1
  122. package/v2Containers/TemplatesV2/messages.js +4 -0
  123. package/v2Containers/WebPush/Create/components/BrandIconSection.js +108 -0
  124. package/v2Containers/WebPush/Create/components/ButtonForm.js +172 -0
  125. package/v2Containers/WebPush/Create/components/ButtonItem.js +101 -0
  126. package/v2Containers/WebPush/Create/components/ButtonList.js +145 -0
  127. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +164 -0
  128. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +463 -0
  129. package/v2Containers/WebPush/Create/components/FormActions.js +54 -0
  130. package/v2Containers/WebPush/Create/components/FormActions.test.js +163 -0
  131. package/v2Containers/WebPush/Create/components/MediaSection.js +142 -0
  132. package/v2Containers/WebPush/Create/components/MediaSection.test.js +341 -0
  133. package/v2Containers/WebPush/Create/components/MessageSection.js +103 -0
  134. package/v2Containers/WebPush/Create/components/MessageSection.test.js +268 -0
  135. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +87 -0
  136. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +210 -0
  137. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +54 -0
  138. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +143 -0
  139. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +86 -0
  140. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +16 -0
  141. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +41 -0
  142. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +54 -0
  143. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +37 -0
  144. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +21 -0
  145. package/v2Containers/WebPush/Create/components/_buttons.scss +246 -0
  146. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +554 -0
  147. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +607 -0
  148. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +633 -0
  149. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +666 -0
  150. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +74 -0
  151. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +78 -0
  152. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +138 -0
  153. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +406 -0
  154. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +30 -0
  155. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +151 -0
  156. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +104 -0
  157. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +538 -0
  158. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +122 -0
  159. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +633 -0
  160. package/v2Containers/WebPush/Create/index.js +1056 -0
  161. package/v2Containers/WebPush/Create/index.scss +134 -0
  162. package/v2Containers/WebPush/Create/messages.js +203 -0
  163. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +228 -0
  164. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +294 -0
  165. package/v2Containers/WebPush/Create/preview/PreviewContent.js +90 -0
  166. package/v2Containers/WebPush/Create/preview/PreviewControls.js +305 -0
  167. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +23 -0
  168. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +150 -0
  169. package/v2Containers/WebPush/Create/preview/assets/Light.svg +53 -0
  170. package/v2Containers/WebPush/Create/preview/assets/Top.svg +5 -0
  171. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +9 -0
  172. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +9 -0
  173. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  174. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  175. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +106 -0
  176. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +26 -0
  177. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +9 -0
  178. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +9 -0
  179. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +18 -0
  180. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +29 -0
  181. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +9 -0
  182. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +9 -0
  183. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +47 -0
  184. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +141 -0
  185. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +45 -0
  186. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +68 -0
  187. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +61 -0
  188. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +99 -0
  189. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +733 -0
  190. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +571 -0
  191. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +81 -0
  192. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +81 -0
  193. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +50 -0
  194. package/v2Containers/WebPush/Create/preview/constants.js +637 -0
  195. package/v2Containers/WebPush/Create/preview/notification-container.scss +79 -0
  196. package/v2Containers/WebPush/Create/preview/preview.scss +351 -0
  197. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +370 -0
  198. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +12 -0
  199. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +12 -0
  200. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +12 -0
  201. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +47 -0
  202. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +11 -0
  203. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +11 -0
  204. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +11 -0
  205. package/v2Containers/WebPush/Create/preview/styles/_base.scss +207 -0
  206. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +153 -0
  207. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +107 -0
  208. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +101 -0
  209. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +229 -0
  210. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +909 -0
  211. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +1081 -0
  212. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +723 -0
  213. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +943 -0
  214. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +131 -0
  215. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +112 -0
  216. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +144 -0
  217. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +129 -0
  218. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +94 -0
  219. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +390 -0
  220. package/v2Containers/WebPush/Create/utils/previewUtils.js +89 -0
  221. package/v2Containers/WebPush/Create/utils/urlValidation.js +115 -0
  222. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +449 -0
  223. package/v2Containers/WebPush/Create/utils/validation.js +75 -0
  224. package/v2Containers/WebPush/Create/utils/validation.test.js +283 -0
  225. package/v2Containers/WebPush/actions.js +60 -0
  226. package/v2Containers/WebPush/constants.js +128 -0
  227. package/v2Containers/WebPush/index.js +2 -0
  228. package/v2Containers/WebPush/reducer.js +104 -0
  229. package/v2Containers/WebPush/sagas.js +119 -0
  230. package/v2Containers/WebPush/selectors.js +65 -0
  231. package/v2Containers/WebPush/tests/reducer.test.js +863 -0
  232. package/v2Containers/WebPush/tests/sagas.test.js +566 -0
  233. package/v2Containers/WebPush/tests/selectors.test.js +843 -0
  234. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +528 -431
  235. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -254
  236. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -362
  237. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
  238. package/v2Containers/BeePopupEditor/constants.js +0 -10
  239. package/v2Containers/BeePopupEditor/index.js +0 -193
  240. package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
  241. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1045
  242. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
  243. package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
  244. package/v2Containers/InApp/tests/selectors.test.js +0 -612
  245. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -162
  246. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
  247. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -9
  248. package/v2Containers/InAppWrapper/constants.js +0 -16
  249. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
  250. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
  251. package/v2Containers/InAppWrapper/index.js +0 -148
  252. package/v2Containers/InAppWrapper/messages.js +0 -49
  253. package/v2Containers/InappAdvance/index.js +0 -1099
  254. package/v2Containers/InappAdvance/index.scss +0 -10
  255. package/v2Containers/InappAdvance/tests/index.test.js +0 -448
@@ -0,0 +1,74 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`ButtonItem Rendering should render correctly with default props 1`] = `
4
+ <div
5
+ className="webpush-button-item "
6
+ draggable={true}
7
+ onDragEnd={[MockFunction]}
8
+ onDragOver={[Function]}
9
+ onDragStart={[Function]}
10
+ onDrop={[Function]}
11
+ >
12
+ <CapRow
13
+ align="middle"
14
+ className="button-item-content"
15
+ >
16
+ <CapColumn
17
+ className="button-item-drag-handle"
18
+ span={1}
19
+ >
20
+ <CapIcon
21
+ className="drag-icon"
22
+ type="drag"
23
+ />
24
+ </CapColumn>
25
+ <CapColumn
26
+ className="button-item-icon"
27
+ span={1}
28
+ >
29
+ <CapIcon
30
+ className="link-icon"
31
+ type="link"
32
+ />
33
+ </CapColumn>
34
+ <CapColumn
35
+ className="button-item-info"
36
+ span={14}
37
+ >
38
+ <div
39
+ className="button-item-text-row"
40
+ >
41
+ <span
42
+ className="button-item-text"
43
+ >
44
+ Click Me
45
+ </span>
46
+ </div>
47
+ </CapColumn>
48
+ <CapColumn
49
+ className="button-item-actions"
50
+ span={8}
51
+ >
52
+ <div
53
+ className="button-item-url"
54
+ >
55
+ https://example.com
56
+ </div>
57
+ <div
58
+ className="action-icons"
59
+ >
60
+ <CapIcon
61
+ className="action-icon"
62
+ onClick={[Function]}
63
+ type="edit"
64
+ />
65
+ <CapIcon
66
+ className="action-icon delete-icon"
67
+ onClick={[Function]}
68
+ type="delete"
69
+ />
70
+ </div>
71
+ </CapColumn>
72
+ </CapRow>
73
+ </div>
74
+ `;
@@ -0,0 +1,78 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`ButtonList Rendering should render correctly with default props 1`] = `
4
+ <div
5
+ className="webpush-button-list"
6
+ >
7
+ <MockButtonItem
8
+ button={
9
+ Object {
10
+ "text": "Primary Button",
11
+ "type": "primary",
12
+ "url": "https://example.com",
13
+ }
14
+ }
15
+ disabled={false}
16
+ index={0}
17
+ onDelete={[MockFunction]}
18
+ onDragEnd={[Function]}
19
+ onDragOver={[Function]}
20
+ onDragStart={[Function]}
21
+ onDrop={[Function]}
22
+ onEdit={[MockFunction]}
23
+ />
24
+ <MockButtonItem
25
+ button={
26
+ Object {
27
+ "text": "Secondary Button",
28
+ "type": "secondary",
29
+ "url": "https://example2.com",
30
+ }
31
+ }
32
+ disabled={false}
33
+ index={1}
34
+ onDelete={[MockFunction]}
35
+ onDragEnd={[Function]}
36
+ onDragOver={[Function]}
37
+ onDragStart={[Function]}
38
+ onDrop={[Function]}
39
+ onEdit={[MockFunction]}
40
+ />
41
+ <CapRow
42
+ className="button-list-add-button"
43
+ >
44
+ <CapButton
45
+ className="add-primary-button button-add-trigger"
46
+ disabled={false}
47
+ icon="plus"
48
+ isAddBtn={false}
49
+ onClick={[MockFunction]}
50
+ type="flat"
51
+ >
52
+ <FormattedMessage
53
+ defaultMessage="Add primary button"
54
+ id="creatives.containersV2.WebPush.addPrimaryButton"
55
+ values={Object {}}
56
+ />
57
+ </CapButton>
58
+ </CapRow>
59
+ <CapRow
60
+ className="button-list-add-button"
61
+ >
62
+ <CapButton
63
+ className="add-secondary-button button-add-trigger"
64
+ disabled={false}
65
+ icon="plus"
66
+ isAddBtn={false}
67
+ onClick={[MockFunction]}
68
+ type="flat"
69
+ >
70
+ <FormattedMessage
71
+ defaultMessage="Add secondary button"
72
+ id="creatives.containersV2.WebPush.addSecondaryButton"
73
+ values={Object {}}
74
+ />
75
+ </CapButton>
76
+ </CapRow>
77
+ </div>
78
+ `;
@@ -0,0 +1,138 @@
1
+ import { useState, useCallback, useMemo } from 'react';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { WEBPUSH_BUTTON_TYPES } from '../../constants';
4
+
5
+ /**
6
+ * Custom hook for managing Web Push CTA buttons
7
+ * @param {Array} initialButtons - Initial button data
8
+ * @returns {Object} Button state and handlers
9
+ */
10
+ export const useButtonManagement = (initialButtons = []) => {
11
+ const [buttons, setButtons] = useState(initialButtons);
12
+ const [isAddingButton, setIsAddingButton] = useState(false);
13
+ const [buttonBeingAdded, setButtonBeingAdded] = useState(null);
14
+ const [editingButtonIndex, setEditingButtonIndex] = useState(null);
15
+
16
+ const handleAddPrimaryButton = useCallback(() => {
17
+ setIsAddingButton(true);
18
+ setButtonBeingAdded(WEBPUSH_BUTTON_TYPES.PRIMARY);
19
+ setEditingButtonIndex(null);
20
+ }, []);
21
+
22
+ const handleAddSecondaryButton = useCallback(() => {
23
+ setIsAddingButton(true);
24
+ setButtonBeingAdded(WEBPUSH_BUTTON_TYPES.SECONDARY);
25
+ setEditingButtonIndex(null);
26
+ }, []);
27
+
28
+ const handleButtonSave = useCallback(
29
+ (buttonData) => {
30
+ if (editingButtonIndex !== null) {
31
+ // Editing existing button - preserve existing ID
32
+ const newButtons = [...buttons];
33
+ newButtons[editingButtonIndex] = {
34
+ ...buttonData,
35
+ id: buttons[editingButtonIndex].id,
36
+ };
37
+ setButtons(newButtons);
38
+ } else {
39
+ // Adding new button - generate unique ID
40
+ const buttonWithId = {
41
+ ...buttonData,
42
+ id: uuidv4(),
43
+ };
44
+ setButtons((prev) => [...prev, buttonWithId]);
45
+ }
46
+ setIsAddingButton(false);
47
+ setButtonBeingAdded(null);
48
+ setEditingButtonIndex(null);
49
+ },
50
+ [buttons, editingButtonIndex],
51
+ );
52
+
53
+ const handleButtonCancel = useCallback(() => {
54
+ setIsAddingButton(false);
55
+ setButtonBeingAdded(null);
56
+ setEditingButtonIndex(null);
57
+ }, []);
58
+
59
+ const handleButtonEdit = useCallback(
60
+ (index) => {
61
+ setIsAddingButton(true);
62
+ setButtonBeingAdded(buttons[index].type);
63
+ setEditingButtonIndex(index);
64
+ },
65
+ [buttons],
66
+ );
67
+
68
+ const handleButtonDelete = useCallback(
69
+ (index) => {
70
+ const newButtons = [...buttons];
71
+ newButtons.splice(index, 1);
72
+ setButtons(newButtons);
73
+ },
74
+ [buttons],
75
+ );
76
+
77
+ const handleButtonReorder = useCallback(
78
+ (fromIndex, toIndex) => {
79
+ const newButtons = [...buttons];
80
+ const [movedButton] = newButtons.splice(fromIndex, 1);
81
+ newButtons.splice(toIndex, 0, movedButton);
82
+ setButtons(newButtons);
83
+ },
84
+ [buttons],
85
+ );
86
+
87
+ const isAddFlow = useMemo(
88
+ () => isAddingButton && editingButtonIndex === null,
89
+ [isAddingButton, editingButtonIndex],
90
+ );
91
+
92
+ const isEditFlow = useMemo(
93
+ () => isAddingButton && editingButtonIndex !== null,
94
+ [isAddingButton, editingButtonIndex],
95
+ );
96
+
97
+ const showAddPrimaryButton = useMemo(
98
+ () => buttons.length === 0 && !isAddingButton,
99
+ [buttons.length, isAddingButton],
100
+ );
101
+
102
+ const showAddSecondaryButton = useMemo(
103
+ () => buttons.length === 1 && !isAddingButton,
104
+ [buttons.length, isAddingButton],
105
+ );
106
+
107
+ const showDisabledSecondaryDuringPrimary = useMemo(
108
+ () => isAddFlow && buttonBeingAdded === WEBPUSH_BUTTON_TYPES.PRIMARY && buttons.length === 0,
109
+ [isAddFlow, buttonBeingAdded, buttons.length],
110
+ );
111
+
112
+ const disableSecondaryAddButton = useMemo(
113
+ () => isAddFlow && buttonBeingAdded === WEBPUSH_BUTTON_TYPES.PRIMARY,
114
+ [isAddFlow, buttonBeingAdded],
115
+ );
116
+
117
+ return {
118
+ buttons,
119
+ setButtons,
120
+ isAddingButton,
121
+ buttonBeingAdded,
122
+ editingButtonIndex,
123
+ handleAddPrimaryButton,
124
+ handleAddSecondaryButton,
125
+ handleButtonSave,
126
+ handleButtonCancel,
127
+ handleButtonEdit,
128
+ handleButtonDelete,
129
+ handleButtonReorder,
130
+ isAddFlow,
131
+ isEditFlow,
132
+ showAddPrimaryButton,
133
+ showAddSecondaryButton,
134
+ showDisabledSecondaryDuringPrimary,
135
+ disableSecondaryAddButton,
136
+ };
137
+ };
138
+
@@ -0,0 +1,406 @@
1
+ import { renderHook } from '@testing-library/react';
2
+ import { act } from 'react';
3
+ import { useButtonManagement } from './useButtonManagement';
4
+ import { WEBPUSH_BUTTON_TYPES } from '../../constants';
5
+
6
+ describe('useButtonManagement', () => {
7
+ describe('Initialization', () => {
8
+ it('should initialize with empty buttons array by default', () => {
9
+ const { result } = renderHook(() => useButtonManagement());
10
+
11
+ expect(result.current.buttons).toEqual([]);
12
+ expect(result.current.isAddingButton).toBe(false);
13
+ expect(result.current.buttonBeingAdded).toBe(null);
14
+ expect(result.current.editingButtonIndex).toBe(null);
15
+ });
16
+
17
+ it('should initialize with provided initial buttons', () => {
18
+ const initialButtons = [
19
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com' },
20
+ ];
21
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
22
+
23
+ expect(result.current.buttons).toEqual(initialButtons);
24
+ });
25
+ });
26
+
27
+ describe('Adding Buttons', () => {
28
+ it('should handle adding primary button', () => {
29
+ const { result } = renderHook(() => useButtonManagement());
30
+
31
+ act(() => {
32
+ result.current.handleAddPrimaryButton();
33
+ });
34
+
35
+ expect(result.current.isAddingButton).toBe(true);
36
+ expect(result.current.buttonBeingAdded).toBe(WEBPUSH_BUTTON_TYPES.PRIMARY);
37
+ expect(result.current.editingButtonIndex).toBe(null);
38
+ });
39
+
40
+ it('should handle adding secondary button', () => {
41
+ const { result } = renderHook(() => useButtonManagement());
42
+
43
+ act(() => {
44
+ result.current.handleAddSecondaryButton();
45
+ });
46
+
47
+ expect(result.current.isAddingButton).toBe(true);
48
+ expect(result.current.buttonBeingAdded).toBe(WEBPUSH_BUTTON_TYPES.SECONDARY);
49
+ expect(result.current.editingButtonIndex).toBe(null);
50
+ });
51
+ });
52
+
53
+ describe('Saving Buttons', () => {
54
+ it('should add new button when not editing', () => {
55
+ const { result } = renderHook(() => useButtonManagement());
56
+
57
+ act(() => {
58
+ result.current.handleAddPrimaryButton();
59
+ });
60
+
61
+ const buttonData = {
62
+ type: WEBPUSH_BUTTON_TYPES.PRIMARY,
63
+ text: 'Click Me',
64
+ url: 'https://example.com',
65
+ };
66
+
67
+ act(() => {
68
+ result.current.handleButtonSave(buttonData);
69
+ });
70
+
71
+ expect(result.current.buttons).toHaveLength(1);
72
+ expect(result.current.buttons[0]).toEqual(expect.objectContaining(buttonData));
73
+ expect(result.current.buttons[0].id).toBeDefined();
74
+ expect(typeof result.current.buttons[0].id).toBe('string');
75
+ expect(result.current.isAddingButton).toBe(false);
76
+ expect(result.current.buttonBeingAdded).toBe(null);
77
+ expect(result.current.editingButtonIndex).toBe(null);
78
+ });
79
+
80
+ it('should update existing button when editing', () => {
81
+ const initialButtons = [
82
+ { id: 'test-id-1', type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Old Text', url: 'https://old.com' },
83
+ ];
84
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
85
+
86
+ act(() => {
87
+ result.current.handleButtonEdit(0);
88
+ });
89
+
90
+ const updatedButtonData = {
91
+ type: WEBPUSH_BUTTON_TYPES.PRIMARY,
92
+ text: 'New Text',
93
+ url: 'https://new.com',
94
+ };
95
+
96
+ act(() => {
97
+ result.current.handleButtonSave(updatedButtonData);
98
+ });
99
+
100
+ expect(result.current.buttons).toHaveLength(1);
101
+ expect(result.current.buttons[0]).toEqual(expect.objectContaining(updatedButtonData));
102
+ expect(result.current.buttons[0].id).toBe('test-id-1'); // ID should be preserved
103
+ expect(result.current.isAddingButton).toBe(false);
104
+ expect(result.current.buttonBeingAdded).toBe(null);
105
+ expect(result.current.editingButtonIndex).toBe(null);
106
+ });
107
+
108
+ it('should add multiple buttons', () => {
109
+ const { result } = renderHook(() => useButtonManagement());
110
+
111
+ const button1 = {
112
+ type: WEBPUSH_BUTTON_TYPES.PRIMARY,
113
+ text: 'Button 1',
114
+ url: 'https://example.com/1',
115
+ };
116
+
117
+ act(() => {
118
+ result.current.handleAddPrimaryButton();
119
+ result.current.handleButtonSave(button1);
120
+ });
121
+
122
+ const button2 = {
123
+ type: WEBPUSH_BUTTON_TYPES.SECONDARY,
124
+ text: 'Button 2',
125
+ url: 'https://example.com/2',
126
+ };
127
+
128
+ act(() => {
129
+ result.current.handleAddSecondaryButton();
130
+ result.current.handleButtonSave(button2);
131
+ });
132
+
133
+ expect(result.current.buttons).toHaveLength(2);
134
+ expect(result.current.buttons[0]).toEqual(expect.objectContaining(button1));
135
+ expect(result.current.buttons[0].id).toBeDefined();
136
+ expect(result.current.buttons[1]).toEqual(expect.objectContaining(button2));
137
+ expect(result.current.buttons[1].id).toBeDefined();
138
+ expect(result.current.buttons[0].id).not.toBe(result.current.buttons[1].id);
139
+ });
140
+ });
141
+
142
+ describe('Canceling Button Operations', () => {
143
+ it('should cancel adding button', () => {
144
+ const { result } = renderHook(() => useButtonManagement());
145
+
146
+ act(() => {
147
+ result.current.handleAddPrimaryButton();
148
+ });
149
+
150
+ act(() => {
151
+ result.current.handleButtonCancel();
152
+ });
153
+
154
+ expect(result.current.isAddingButton).toBe(false);
155
+ expect(result.current.buttonBeingAdded).toBe(null);
156
+ expect(result.current.editingButtonIndex).toBe(null);
157
+ });
158
+
159
+ it('should cancel editing button', () => {
160
+ const initialButtons = [
161
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button', url: 'https://example.com' },
162
+ ];
163
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
164
+
165
+ act(() => {
166
+ result.current.handleButtonEdit(0);
167
+ });
168
+
169
+ act(() => {
170
+ result.current.handleButtonCancel();
171
+ });
172
+
173
+ expect(result.current.isAddingButton).toBe(false);
174
+ expect(result.current.buttonBeingAdded).toBe(null);
175
+ expect(result.current.editingButtonIndex).toBe(null);
176
+ expect(result.current.buttons).toEqual(initialButtons);
177
+ });
178
+ });
179
+
180
+ describe('Editing Buttons', () => {
181
+ it('should set up editing state for existing button', () => {
182
+ const initialButtons = [
183
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button', url: 'https://example.com' },
184
+ ];
185
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
186
+
187
+ act(() => {
188
+ result.current.handleButtonEdit(0);
189
+ });
190
+
191
+ expect(result.current.isAddingButton).toBe(true);
192
+ expect(result.current.buttonBeingAdded).toBe(WEBPUSH_BUTTON_TYPES.PRIMARY);
193
+ expect(result.current.editingButtonIndex).toBe(0);
194
+ });
195
+
196
+ it('should set correct button type when editing', () => {
197
+ const initialButtons = [
198
+ { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button', url: 'https://example.com' },
199
+ ];
200
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
201
+
202
+ act(() => {
203
+ result.current.handleButtonEdit(0);
204
+ });
205
+
206
+ expect(result.current.buttonBeingAdded).toBe(WEBPUSH_BUTTON_TYPES.SECONDARY);
207
+ });
208
+ });
209
+
210
+ describe('Deleting Buttons', () => {
211
+ it('should delete button at specified index', () => {
212
+ const initialButtons = [
213
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
214
+ { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button 2', url: 'https://example.com/2' },
215
+ ];
216
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
217
+
218
+ act(() => {
219
+ result.current.handleButtonDelete(0);
220
+ });
221
+
222
+ expect(result.current.buttons).toHaveLength(1);
223
+ expect(result.current.buttons[0]).toEqual(initialButtons[1]);
224
+ });
225
+
226
+ it('should delete last button', () => {
227
+ const initialButtons = [
228
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button', url: 'https://example.com' },
229
+ ];
230
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
231
+
232
+ act(() => {
233
+ result.current.handleButtonDelete(0);
234
+ });
235
+
236
+ expect(result.current.buttons).toHaveLength(0);
237
+ });
238
+
239
+ it('should delete middle button correctly', () => {
240
+ const initialButtons = [
241
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
242
+ { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button 2', url: 'https://example.com/2' },
243
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 3', url: 'https://example.com/3' },
244
+ ];
245
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
246
+
247
+ act(() => {
248
+ result.current.handleButtonDelete(1);
249
+ });
250
+
251
+ expect(result.current.buttons).toHaveLength(2);
252
+ expect(result.current.buttons[0]).toEqual(initialButtons[0]);
253
+ expect(result.current.buttons[1]).toEqual(initialButtons[2]);
254
+ });
255
+ });
256
+
257
+ describe('Reordering Buttons', () => {
258
+ it('should reorder buttons correctly', () => {
259
+ const initialButtons = [
260
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
261
+ { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button 2', url: 'https://example.com/2' },
262
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 3', url: 'https://example.com/3' },
263
+ ];
264
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
265
+
266
+ act(() => {
267
+ result.current.handleButtonReorder(0, 2);
268
+ });
269
+
270
+ expect(result.current.buttons).toHaveLength(3);
271
+ expect(result.current.buttons[0]).toEqual(initialButtons[1]);
272
+ expect(result.current.buttons[1]).toEqual(initialButtons[2]);
273
+ expect(result.current.buttons[2]).toEqual(initialButtons[0]);
274
+ });
275
+
276
+ it('should move button to beginning', () => {
277
+ const initialButtons = [
278
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
279
+ { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button 2', url: 'https://example.com/2' },
280
+ ];
281
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
282
+
283
+ act(() => {
284
+ result.current.handleButtonReorder(1, 0);
285
+ });
286
+
287
+ expect(result.current.buttons[0]).toEqual(initialButtons[1]);
288
+ expect(result.current.buttons[1]).toEqual(initialButtons[0]);
289
+ });
290
+
291
+ it('should move button to end', () => {
292
+ const initialButtons = [
293
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button 1', url: 'https://example.com/1' },
294
+ { type: WEBPUSH_BUTTON_TYPES.SECONDARY, text: 'Button 2', url: 'https://example.com/2' },
295
+ ];
296
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
297
+
298
+ act(() => {
299
+ result.current.handleButtonReorder(0, 1);
300
+ });
301
+
302
+ expect(result.current.buttons[0]).toEqual(initialButtons[1]);
303
+ expect(result.current.buttons[1]).toEqual(initialButtons[0]);
304
+ });
305
+ });
306
+
307
+ describe('Computed Values', () => {
308
+ it('should return isAddFlow as true when adding new button', () => {
309
+ const { result } = renderHook(() => useButtonManagement());
310
+
311
+ act(() => {
312
+ result.current.handleAddPrimaryButton();
313
+ });
314
+
315
+ expect(result.current.isAddFlow).toBe(true);
316
+ expect(result.current.isEditFlow).toBe(false);
317
+ });
318
+
319
+ it('should return isEditFlow as true when editing existing button', () => {
320
+ const initialButtons = [
321
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button', url: 'https://example.com' },
322
+ ];
323
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
324
+
325
+ act(() => {
326
+ result.current.handleButtonEdit(0);
327
+ });
328
+
329
+ expect(result.current.isAddFlow).toBe(false);
330
+ expect(result.current.isEditFlow).toBe(true);
331
+ });
332
+
333
+ it('should show add primary button when no buttons exist', () => {
334
+ const { result } = renderHook(() => useButtonManagement());
335
+
336
+ expect(result.current.showAddPrimaryButton).toBe(true);
337
+ expect(result.current.showAddSecondaryButton).toBe(false);
338
+ });
339
+
340
+ it('should show add secondary button when one button exists', () => {
341
+ const initialButtons = [
342
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button', url: 'https://example.com' },
343
+ ];
344
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
345
+
346
+ expect(result.current.showAddPrimaryButton).toBe(false);
347
+ expect(result.current.showAddSecondaryButton).toBe(true);
348
+ });
349
+
350
+ it('should not show add buttons when adding primary button', () => {
351
+ const { result } = renderHook(() => useButtonManagement());
352
+
353
+ act(() => {
354
+ result.current.handleAddPrimaryButton();
355
+ });
356
+
357
+ expect(result.current.showAddPrimaryButton).toBe(false);
358
+ expect(result.current.showAddSecondaryButton).toBe(false);
359
+ });
360
+
361
+ it('should show disabled secondary during primary add flow', () => {
362
+ const { result } = renderHook(() => useButtonManagement());
363
+
364
+ act(() => {
365
+ result.current.handleAddPrimaryButton();
366
+ });
367
+
368
+ expect(result.current.showDisabledSecondaryDuringPrimary).toBe(true);
369
+ expect(result.current.disableSecondaryAddButton).toBe(true);
370
+ });
371
+
372
+ it('should not show disabled secondary when not in primary add flow', () => {
373
+ const { result } = renderHook(() => useButtonManagement());
374
+
375
+ expect(result.current.showDisabledSecondaryDuringPrimary).toBe(false);
376
+ expect(result.current.disableSecondaryAddButton).toBe(false);
377
+ });
378
+
379
+ it('should not show disabled secondary when buttons already exist', () => {
380
+ const initialButtons = [
381
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'Button', url: 'https://example.com' },
382
+ ];
383
+ const { result } = renderHook(() => useButtonManagement(initialButtons));
384
+
385
+ expect(result.current.showDisabledSecondaryDuringPrimary).toBe(false);
386
+ expect(result.current.disableSecondaryAddButton).toBe(false);
387
+ });
388
+ });
389
+
390
+ describe('setButtons', () => {
391
+ it('should allow direct button state update', () => {
392
+ const { result } = renderHook(() => useButtonManagement());
393
+
394
+ const newButtons = [
395
+ { type: WEBPUSH_BUTTON_TYPES.PRIMARY, text: 'New Button', url: 'https://example.com' },
396
+ ];
397
+
398
+ act(() => {
399
+ result.current.setButtons(newButtons);
400
+ });
401
+
402
+ expect(result.current.buttons).toEqual(newButtons);
403
+ });
404
+ });
405
+ });
406
+