@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
@@ -1,294 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import chromeIcon from './assets/chrome-icon.png';
4
- import AndroidMobileChromeHeader from './components/AndroidMobileChromeHeader';
5
- import AndroidMobileExpanded from './components/AndroidMobileExpanded';
6
- import NotificationExpandedContent from './components/NotificationExpandedContent';
7
- import NotificationHeader from './components/NotificationHeader';
8
- import WindowsChromeExpanded from './components/WindowsChromeExpanded';
9
- import IOSHeader from './components/IOSHeader';
10
- import {
11
- OS_MACOS,
12
- OS_IOS,
13
- OS_IPADOS,
14
- OS_WINDOWS,
15
- OS_ANDROID_MOBILE,
16
- OS_ANDROID_TABLET,
17
- BROWSER_CHROME,
18
- BROWSER_FIREFOX,
19
- BROWSER_EDGE,
20
- BROWSER_OPERA,
21
- BRAND_ICON_SUPPORTED_BROWSERS,
22
- BROWSER_DISPLAY_NAMES,
23
- NOTIFICATION_STATE_COLLAPSED,
24
- NOTIFICATION_STATE_EXPANDED,
25
- } from './constants';
26
- import {
27
- getNotificationContainerClassName,
28
- formatUrlForPreview,
29
- transformButtonsForPreview,
30
- } from '../utils/previewUtils';
31
-
32
- /**
33
- * NotificationContainer Component
34
- *
35
- * Standalone notification container component that renders the actual notification UI.
36
- * This component is decoupled from any wrapper containers and can be used
37
- * in different contexts (main preview, device frame preview, etc.).
38
- *
39
- * The component renders the notification-container div with all its content:
40
- * - Notification header (icon, title, URL, body)
41
- * - Expanded content (media image, CTA buttons) when state is 'Expanded'
42
- *
43
- * @param {string} notificationTitle - Title of the notification
44
- * @param {string} notificationBody - Body text of the notification
45
- * @param {string} url - URL for the notification
46
- * @param {string} selectedOS - Operating system name
47
- * @param {string} selectedBrowser - Browser name
48
- * @param {string} notificationState - 'Collapsed' or 'Expanded' (default: 'Collapsed')
49
- * @param {string} className - Additional CSS classes to apply to the container
50
- * @param {string} icon - Icon asset for the browser (defaults to Chrome)
51
- * @param {boolean} supportsExpanded - Whether Expanded state is supported for this variant
52
- * @param {boolean} enableMedia - Whether to render media section when expanded
53
- * @param {boolean} enableCtas - Whether to render CTA buttons when expanded
54
- * @param {string} imageSrc - Media/banner image source URL
55
- * @param {string} brandIconSrc - Brand icon image source URL
56
- */
57
- const NotificationContainer = ({
58
- notificationTitle,
59
- notificationBody,
60
- url,
61
- selectedOS,
62
- selectedBrowser,
63
- notificationState = NOTIFICATION_STATE_COLLAPSED,
64
- className = '',
65
- icon = chromeIcon,
66
- supportsExpanded = true,
67
- enableMedia = true,
68
- enableCtas = true,
69
- brandIcon = '',
70
- enableBrandIconPreview = true,
71
- imageSrc = '',
72
- brandIconSrc = '',
73
- buttons = [],
74
- showSeparateIOSCTAs = false,
75
- }) => {
76
- // Force expanded UI for Windows when Collapsed state is selected
77
- // Windows only supports expanded preview - when Windows + Collapsed is selected, render expanded UI
78
- // Note: If Windows needs separate Collapsed/Expanded states later, remove the second condition
79
- const isExpanded = (supportsExpanded && notificationState === NOTIFICATION_STATE_EXPANDED) ||
80
- (selectedOS === OS_WINDOWS && notificationState === NOTIFICATION_STATE_COLLAPSED);
81
- const notificationContainerClass = getNotificationContainerClassName(selectedOS, selectedBrowser);
82
- const stateClass = isExpanded ? 'expanded' : 'collapsed';
83
- const selectedBrowserLower = (selectedBrowser || '').toLowerCase();
84
-
85
- // Platform detection object - provides clean access to all platform/browser checks
86
- const platform = {
87
- parts: notificationContainerClass.split('-'),
88
- get os() { return this.parts[0]; },
89
- get browser() { return this.parts.length === 3 ? this.parts[2] : this.parts[1]; },
90
- get isMacOs() { return selectedOS === OS_MACOS; },
91
- get isIOS() { return selectedOS === OS_IOS; },
92
- get isIPadOS() { return selectedOS === OS_IPADOS; },
93
- get isAndroidMobile() { return this.os === 'android' && this.parts[1] === 'mobile'; },
94
- get isAndroidTablet() { return this.os === 'android' && this.parts[1] === 'tablet'; },
95
- get isIOSBrowser() { return this.os === 'ios'; },
96
- get isIPadOSBrowser() { return this.os === 'ipados'; },
97
- get isWindows() { return this.os === 'windows'; },
98
- get supportsBrandIcon() { return BRAND_ICON_SUPPORTED_BROWSERS.includes(selectedBrowserLower); },
99
- get isMacOsBrandIconBrowser() { return this.isMacOs && this.supportsBrandIcon; },
100
- get isWindowsExpanded() { return this.isWindows && isExpanded; },
101
- get isMacOsExpandedBrand() { return this.isMacOs && isExpanded && this.supportsBrandIcon; },
102
- };
103
-
104
- const displayUrl = formatUrlForPreview(url) || url || '';
105
- // Use real media image from form/props
106
- const mediaImageUrl = imageSrc || '';
107
- // Use real brand icon from form/props, fallback to prop if provided for backward compatibility
108
- const actualBrandIcon = brandIconSrc || brandIcon || '';
109
- const shouldShowBrandIconAndroidExpanded =
110
- (platform.isAndroidMobile || platform.isAndroidTablet) && isExpanded && enableBrandIconPreview && Boolean(actualBrandIcon);
111
- const ctaButtons = transformButtonsForPreview(buttons);
112
-
113
- // Brand icon preview toggle (set enableBrandIconPreview to false to see no-brand state)
114
- const shouldShowBrandIcon = (() => {
115
- // iOS/iPadOS NEVER show brand icons - they use a simple notification style
116
- if (platform.isIOSBrowser || platform.isIPadOSBrowser) return false;
117
-
118
- if (!enableBrandIconPreview || !actualBrandIcon) return false;
119
- if (platform.isAndroidMobile && !isExpanded) return true;
120
- if (platform.isAndroidTablet && !isExpanded) return true;
121
- // macOS: show brand icon for all browsers in collapsed state
122
- if (platform.isMacOs && !isExpanded) return true;
123
- // Windows browsers: show brand icon in collapsed state (same as macOS Chrome)
124
- if (platform.isWindows && !isExpanded) return true;
125
- return false;
126
- })();
127
-
128
- const shouldShowBrandIconInExpandedMac = (() => {
129
- if (!platform.isMacOsExpandedBrand) return false;
130
- if (!enableBrandIconPreview || !actualBrandIcon) return false;
131
- return true;
132
- })();
133
-
134
- const shouldRenderExpandedMedia = (() => {
135
- if (!enableMedia) return false;
136
- if (platform.isMacOsExpandedBrand) {
137
- // For macOS brand browsers, only render if brand icon is available.
138
- return shouldShowBrandIconInExpandedMac;
139
- }
140
- return Boolean(mediaImageUrl);
141
- })();
142
-
143
- const containerClasses = [
144
- 'notification-container',
145
- notificationContainerClass,
146
- stateClass,
147
- className,
148
- platform.isWindowsExpanded ? 'windows-chrome-expanded' : '',
149
- ]
150
- .filter(Boolean)
151
- .join(' ')
152
- .trim();
153
-
154
- // Get browser display name for Windows expanded notifications
155
- const getBrowserDisplayName = (browser) => {
156
- return BROWSER_DISPLAY_NAMES[browser] || browser;
157
- };
158
-
159
- // Check if we need to render separate CTA container for iOS + Collapsed
160
- const shouldRenderSeparateIOSCTAs =
161
- showSeparateIOSCTAs &&
162
- platform.isIOSBrowser &&
163
- !isExpanded &&
164
- enableCtas &&
165
- ctaButtons &&
166
- ctaButtons.length > 0;
167
-
168
- const notificationContent = (
169
- <div className={containerClasses}>
170
- {platform.isWindowsExpanded ? (
171
- <WindowsChromeExpanded
172
- icon={icon}
173
- brandIcon={actualBrandIcon}
174
- enableBrandIconPreview={enableBrandIconPreview}
175
- notificationTitle={notificationTitle}
176
- notificationBody={notificationBody}
177
- displayUrl={displayUrl}
178
- browserName={getBrowserDisplayName(selectedBrowser)}
179
- mediaImageUrl={mediaImageUrl}
180
- enableCtas={enableCtas}
181
- ctaButtons={ctaButtons}
182
- />
183
- ) : (platform.isAndroidMobile || platform.isAndroidTablet) && isExpanded ? (
184
- <AndroidMobileExpanded
185
- icon={icon}
186
- selectedBrowser={selectedBrowser}
187
- notificationTitle={notificationTitle}
188
- notificationBody={notificationBody}
189
- displayUrl={displayUrl}
190
- brandIcon={actualBrandIcon}
191
- shouldShowBrandIcon={shouldShowBrandIcon}
192
- shouldShowBrandIconExpanded={shouldShowBrandIconAndroidExpanded}
193
- mediaImageUrl={mediaImageUrl}
194
- enableCtas={enableCtas}
195
- ctaButtons={ctaButtons}
196
- />
197
- ) : (
198
- <>
199
- {(platform.isAndroidMobile || platform.isAndroidTablet) && !isExpanded ? (
200
- <AndroidMobileChromeHeader
201
- icon={icon}
202
- selectedBrowser={selectedBrowser}
203
- notificationTitle={notificationTitle}
204
- notificationBody={notificationBody}
205
- brandIcon={actualBrandIcon}
206
- shouldShowBrandIcon={shouldShowBrandIcon}
207
- />
208
- ) : (platform.isIOSBrowser || platform.isIPadOSBrowser) ? (
209
- <IOSHeader
210
- icon={icon}
211
- selectedBrowser={selectedBrowser}
212
- notificationTitle={notificationTitle}
213
- notificationBody={notificationBody}
214
- />
215
- ) : (
216
- <NotificationHeader
217
- icon={icon}
218
- selectedBrowser={selectedBrowser}
219
- notificationTitle={notificationTitle}
220
- displayUrl={displayUrl}
221
- notificationBody={notificationBody}
222
- shouldShowBrandIcon={shouldShowBrandIcon}
223
- brandIcon={actualBrandIcon}
224
- isExpanded={isExpanded}
225
- />
226
- )}
227
-
228
- {isExpanded && (
229
- <NotificationExpandedContent
230
- shouldRenderExpandedMedia={shouldRenderExpandedMedia}
231
- shouldShowBrandIconInExpandedMac={shouldShowBrandIconInExpandedMac}
232
- brandIcon={actualBrandIcon}
233
- mediaImageUrl={mediaImageUrl}
234
- enableCtas={enableCtas}
235
- ctaButtons={ctaButtons}
236
- />
237
- )}
238
- </>
239
- )}
240
- </div>
241
- );
242
-
243
- // For iOS + Collapsed with CTAs, render notification and separate CTA container
244
- if (shouldRenderSeparateIOSCTAs) {
245
- return (
246
- <div className="ios-notification-wrapper">
247
- {notificationContent}
248
- <div className="ios-cta-container">
249
- {ctaButtons.map((button) => (
250
- <button
251
- key={button.id}
252
- type="button"
253
- className="ios-cta-button"
254
- >
255
- {button.label}
256
- </button>
257
- ))}
258
- </div>
259
- </div>
260
- );
261
- }
262
-
263
- // Default: return just the notification container
264
- return notificationContent;
265
- };
266
-
267
- NotificationContainer.propTypes = {
268
- notificationTitle: PropTypes.string,
269
- notificationBody: PropTypes.string,
270
- url: PropTypes.string,
271
- selectedOS: PropTypes.string.isRequired,
272
- selectedBrowser: PropTypes.string.isRequired,
273
- notificationState: PropTypes.oneOf([NOTIFICATION_STATE_COLLAPSED, NOTIFICATION_STATE_EXPANDED]),
274
- className: PropTypes.string,
275
- icon: PropTypes.string,
276
- supportsExpanded: PropTypes.bool,
277
- enableMedia: PropTypes.bool,
278
- enableCtas: PropTypes.bool,
279
- brandIcon: PropTypes.string,
280
- enableBrandIconPreview: PropTypes.bool,
281
- imageSrc: PropTypes.string,
282
- brandIconSrc: PropTypes.string,
283
- buttons: PropTypes.arrayOf(
284
- PropTypes.shape({
285
- text: PropTypes.string,
286
- url: PropTypes.string,
287
- type: PropTypes.string,
288
- })
289
- ),
290
- showSeparateIOSCTAs: PropTypes.bool,
291
- };
292
-
293
- export default NotificationContainer;
294
-
@@ -1,90 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import NotificationContainer from './NotificationContainer';
4
- import { getResolvedVariant } from './config/notificationMappings';
5
- import { NOTIFICATION_STATE_COLLAPSED, NOTIFICATION_STATE_EXPANDED } from './constants';
6
- import './preview.scss';
7
-
8
- /**
9
- * PreviewContent Component
10
- *
11
- * Renders the preview area for web push notification.
12
- * Displays actual notification preview for macOS + Chrome combination.
13
- * For other OS/Browser combinations, shows the selection text.
14
- *
15
- * This component wraps the NotificationContainer in a preview-specific
16
- * container (notification-preview) for the main preview area.
17
- *
18
- * @param {string} notificationState - NOTIFICATION_STATE_COLLAPSED or NOTIFICATION_STATE_EXPANDED (default: NOTIFICATION_STATE_COLLAPSED)
19
- */
20
-
21
- const PreviewContent = ({
22
- notificationTitle,
23
- notificationBody,
24
- url,
25
- selectedOS,
26
- selectedBrowser,
27
- notificationState = NOTIFICATION_STATE_COLLAPSED,
28
- imageSrc,
29
- brandIconSrc,
30
- buttons = [],
31
- }) => {
32
- const resolvedVariant = getResolvedVariant(selectedOS, selectedBrowser, notificationState);
33
-
34
- return (
35
- <div className="preview-content">
36
- <div className="preview-content-wrapper">
37
- <div className={`notification-preview ${resolvedVariant ? '' : 'preview-unavailable'}`.trim()}>
38
- {resolvedVariant && (
39
- <NotificationContainer
40
- notificationTitle={notificationTitle}
41
- notificationBody={notificationBody}
42
- url={url}
43
- selectedOS={selectedOS}
44
- selectedBrowser={selectedBrowser}
45
- notificationState={resolvedVariant.stateKey}
46
- icon={resolvedVariant.variant.icon}
47
- supportsExpanded={resolvedVariant.stateConfig.supportsExpanded}
48
- enableMedia={resolvedVariant.stateConfig.showMedia}
49
- enableCtas={buttons.length > 0}
50
- className={resolvedVariant.variant.notificationClassName}
51
- imageSrc={imageSrc}
52
- brandIconSrc={brandIconSrc}
53
- buttons={buttons}
54
- />
55
- )}
56
- </div>
57
- </div>
58
- </div>
59
- );
60
- };
61
-
62
- PreviewContent.propTypes = {
63
- notificationTitle: PropTypes.string,
64
- notificationBody: PropTypes.string,
65
- url: PropTypes.string,
66
- selectedOS: PropTypes.string.isRequired,
67
- selectedBrowser: PropTypes.string.isRequired,
68
- notificationState: PropTypes.oneOf([NOTIFICATION_STATE_COLLAPSED, NOTIFICATION_STATE_EXPANDED]),
69
- imageSrc: PropTypes.string,
70
- brandIconSrc: PropTypes.string,
71
- buttons: PropTypes.arrayOf(
72
- PropTypes.shape({
73
- text: PropTypes.string,
74
- url: PropTypes.string,
75
- type: PropTypes.string,
76
- })
77
- ),
78
- };
79
-
80
- PreviewContent.defaultProps = {
81
- notificationTitle: '',
82
- notificationBody: '',
83
- url: '',
84
- imageSrc: '',
85
- brandIconSrc: '',
86
- buttons: [],
87
- };
88
-
89
- export default PreviewContent;
90
-
@@ -1,305 +0,0 @@
1
- import React, { useCallback, useMemo } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { FormattedMessage } from 'react-intl';
4
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
- import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
6
- import CapSelect from '@capillarytech/cap-ui-library/CapSelect';
7
- import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
8
- import { LAYOUT_MODE, SELECT_WIDTH, STATE_OPTIONS } from './constants';
9
- import { getBrowserOptionsForOS, getSupportedStates } from './config/notificationMappings';
10
- import messages from '../messages';
11
- import './preview.scss';
12
-
13
- /**
14
- * PreviewControls Component
15
- *
16
- * Renders dropdown controls for selecting Operating System, Browser, and State
17
- * for the web push notification preview.
18
- *
19
- * Implements cascading dropdown reset behavior:
20
- * - When OS changes, Browser and State reset to first available option
21
- * - When Browser changes, State resets to first available option
22
- *
23
- * @param {string} layoutMode - 'inline', 'newRow', or 'compact' (default: 'newRow')
24
- * @param {boolean} showStateDropdown - Whether to show the State dropdown (default: true)
25
- * @param {boolean|function} stateDropdownDisabled - Controls State dropdown disabled state.
26
- * - If boolean: directly sets disabled state
27
- * - If function: receives (selectedOS, selectedBrowser, stateOptions) and returns boolean
28
- * - Note: Can be extended to accept object { disabled: boolean, tooltip?: string } for tooltip support
29
- */
30
- const PreviewControls = ({
31
- selectedOS,
32
- selectedBrowser,
33
- selectedState,
34
- osOptions,
35
- browserOptions,
36
- stateOptions,
37
- onOSChange,
38
- onBrowserChange,
39
- onStateChange,
40
- layoutMode = LAYOUT_MODE.NEW_ROW,
41
- showStateDropdown = true,
42
- stateDropdownDisabled = false,
43
- }) => {
44
- const selectWidth = layoutMode === LAYOUT_MODE.COMPACT ? SELECT_WIDTH.COMPACT : SELECT_WIDTH.FULL;
45
-
46
- // Determine if State dropdown should be disabled
47
- // Supports boolean or function for extensibility
48
- // Note: Can be extended to support object { disabled: boolean, tooltip?: string } for tooltip messages
49
- const isStateDropdownDisabled = useMemo(() => {
50
- // Disable State dropdown for Windows (only Collapsed state is supported)
51
- if (selectedOS === 'Windows') {
52
- return true;
53
- }
54
- return typeof stateDropdownDisabled === 'function'
55
- ? stateDropdownDisabled(selectedOS, selectedBrowser, stateOptions)
56
- : stateDropdownDisabled;
57
- }, [stateDropdownDisabled, selectedOS, selectedBrowser, stateOptions]);
58
-
59
- // Memoized State dropdown content to avoid recreating on every render
60
- const stateDropdownContent = useMemo(() => (
61
- <>
62
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
63
- <FormattedMessage {...messages.state} />
64
- </CapLabel>
65
- <CapSelect.CapCustomSelect
66
- width={selectWidth}
67
- options={stateOptions}
68
- value={selectedState}
69
- onChange={onStateChange}
70
- // Note: Add tooltip prop here when tooltip mechanism is implemented
71
- // tooltip={tooltipMessage ? tooltipMessage : undefined}
72
- />
73
- </>
74
- ), [selectWidth, stateOptions, selectedState, onStateChange]);
75
-
76
- // Memoized State dropdown renderer with disabled wrapper
77
- const renderStateDropdown = useMemo(() => {
78
- if (isStateDropdownDisabled) {
79
- return (
80
- <div style={{ pointerEvents: 'none', opacity: 0.6 }}>
81
- {stateDropdownContent}
82
- </div>
83
- );
84
- }
85
- return stateDropdownContent;
86
- }, [isStateDropdownDisabled, stateDropdownContent]);
87
-
88
- /**
89
- * Cascading dropdown reset handler for OS changes
90
- * Resets Browser and State to first available option when OS changes
91
- *
92
- * This implements cascading dropdown behavior: when a parent dropdown (OS) changes,
93
- * dependent dropdowns (Browser, State) reset to their first available option.
94
- */
95
- const handleOSChangeWithCascade = useCallback((value) => {
96
- onOSChange(value);
97
-
98
- // Get browser options for the new OS to ensure we reset to a valid option
99
- const newBrowserOptions = getBrowserOptionsForOS(value);
100
-
101
- // Reset Browser to first available option for the new OS
102
- const newBrowserValue = newBrowserOptions && newBrowserOptions.length > 0
103
- ? newBrowserOptions[0].value
104
- : null;
105
-
106
- if (newBrowserValue && onBrowserChange) {
107
- onBrowserChange(newBrowserValue);
108
- }
109
-
110
- // Compute fresh state options based on new OS and Browser combination
111
- // Only reset state if stateOptions is provided and not empty
112
- if (showStateDropdown && newBrowserValue && onStateChange && stateOptions && stateOptions.length > 0) {
113
- // For Windows, always reset to "Collapsed" (only supported state)
114
- if (value === 'Windows') {
115
- onStateChange('Collapsed');
116
- } else {
117
- const newSupportedStates = getSupportedStates(value, newBrowserValue);
118
- const newStateOptions = newSupportedStates.length > 0
119
- ? newSupportedStates.map((state) => ({ value: state, label: state }))
120
- : STATE_OPTIONS;
121
-
122
- if (newStateOptions.length > 0) {
123
- onStateChange(newStateOptions[0].value);
124
- }
125
- }
126
- }
127
- }, [onOSChange, onBrowserChange, onStateChange, stateOptions, showStateDropdown]);
128
-
129
- /**
130
- * Cascading dropdown reset handler for Browser changes
131
- * Resets State to first available option when Browser changes
132
- */
133
- const handleBrowserChangeWithCascade = useCallback((value) => {
134
- onBrowserChange(value);
135
-
136
- // Compute fresh state options based on current OS and new Browser combination
137
- // Only reset state if stateOptions is provided and not empty
138
- if (showStateDropdown && onStateChange && stateOptions && stateOptions.length > 0) {
139
- const newSupportedStates = getSupportedStates(selectedOS, value);
140
- const newStateOptions = newSupportedStates.length > 0
141
- ? newSupportedStates.map((state) => ({ value: state, label: state }))
142
- : STATE_OPTIONS;
143
-
144
- if (newStateOptions.length > 0) {
145
- onStateChange(newStateOptions[0].value);
146
- }
147
- }
148
- }, [onBrowserChange, onStateChange, selectedOS, stateOptions, showStateDropdown]);
149
-
150
- const controls = [
151
- {
152
- key: 'os',
153
- label: 'operatingSystem',
154
- value: selectedOS,
155
- options: osOptions,
156
- onChange: handleOSChangeWithCascade,
157
- className: 'preview-control-os',
158
- },
159
- {
160
- key: 'browser',
161
- label: 'browser',
162
- value: selectedBrowser,
163
- options: browserOptions,
164
- onChange: handleBrowserChangeWithCascade,
165
- className: 'preview-control-browser',
166
- },
167
- ];
168
-
169
- if (showStateDropdown) {
170
- controls.push({
171
- key: 'state',
172
- label: 'state',
173
- value: selectedState,
174
- options: stateOptions,
175
- onChange: onStateChange,
176
- className: 'preview-control-state',
177
- disabled: isStateDropdownDisabled,
178
- });
179
- }
180
-
181
- const renderControl = useCallback(({ key, label, value, options, onChange, className, disabled }) => {
182
- // Special handling for state dropdown - use memoized renderer
183
- if (key === 'state') {
184
- return (
185
- <div key={key} className={`preview-control ${className}`}>
186
- {renderStateDropdown}
187
- </div>
188
- );
189
- }
190
-
191
- const controlContent = (
192
- <>
193
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
194
- <FormattedMessage {...messages[label]} />
195
- </CapLabel>
196
- <CapSelect.CapCustomSelect
197
- width={selectWidth}
198
- options={options}
199
- value={value}
200
- onChange={onChange}
201
- />
202
- </>
203
- );
204
-
205
- return (
206
- <div key={key} className={`preview-control ${className}`}>
207
- {disabled ? (
208
- <div style={{ pointerEvents: 'none', opacity: 0.6 }}>
209
- {controlContent}
210
- </div>
211
- ) : (
212
- controlContent
213
- )}
214
- </div>
215
- );
216
- }, [selectWidth, renderStateDropdown]);
217
-
218
- if (layoutMode === LAYOUT_MODE.COMPACT) {
219
- return (
220
- <div className="preview-controls preview-controls-compact">
221
- {controls.map(renderControl)}
222
- </div>
223
- );
224
- }
225
-
226
- return (
227
- <>
228
- <CapRow className="preview-controls">
229
- <CapColumn span={12} className="preview-control-os">
230
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
231
- <FormattedMessage {...messages.operatingSystem} />
232
- </CapLabel>
233
- <CapSelect.CapCustomSelect
234
- width={selectWidth}
235
- options={osOptions}
236
- value={selectedOS}
237
- onChange={handleOSChangeWithCascade}
238
- />
239
- </CapColumn>
240
- <CapColumn span={12} className="preview-control-browser">
241
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
242
- <FormattedMessage {...messages.browser} />
243
- </CapLabel>
244
- <CapSelect.CapCustomSelect
245
- width={selectWidth}
246
- options={browserOptions}
247
- value={selectedBrowser}
248
- onChange={handleBrowserChangeWithCascade}
249
- />
250
- </CapColumn>
251
- </CapRow>
252
- {showStateDropdown && layoutMode === LAYOUT_MODE.NEW_ROW && (
253
- <CapRow className="preview-controls-state">
254
- <CapColumn span={12} className="preview-control-state">
255
- {renderStateDropdown}
256
- </CapColumn>
257
- </CapRow>
258
- )}
259
- {showStateDropdown && layoutMode === LAYOUT_MODE.INLINE && (
260
- <CapRow className="preview-controls">
261
- <CapColumn span={12} className="preview-control-state">
262
- {renderStateDropdown}
263
- </CapColumn>
264
- </CapRow>
265
- )}
266
- </>
267
- );
268
- };
269
-
270
- PreviewControls.propTypes = {
271
- selectedOS: PropTypes.string.isRequired,
272
- selectedBrowser: PropTypes.string.isRequired,
273
- selectedState: PropTypes.string,
274
- osOptions: PropTypes.arrayOf(
275
- PropTypes.shape({
276
- value: PropTypes.string.isRequired,
277
- label: PropTypes.string.isRequired,
278
- }),
279
- ).isRequired,
280
- browserOptions: PropTypes.arrayOf(
281
- PropTypes.shape({
282
- value: PropTypes.string.isRequired,
283
- label: PropTypes.string.isRequired,
284
- }),
285
- ).isRequired,
286
- stateOptions: PropTypes.arrayOf(
287
- PropTypes.shape({
288
- value: PropTypes.string.isRequired,
289
- label: PropTypes.string.isRequired,
290
- }),
291
- ),
292
- onOSChange: PropTypes.func.isRequired,
293
- onBrowserChange: PropTypes.func.isRequired,
294
- onStateChange: PropTypes.func,
295
- layoutMode: PropTypes.oneOf([LAYOUT_MODE.INLINE, LAYOUT_MODE.NEW_ROW, LAYOUT_MODE.COMPACT]),
296
- showStateDropdown: PropTypes.bool,
297
- stateDropdownDisabled: PropTypes.oneOfType([
298
- PropTypes.bool,
299
- PropTypes.func, // (selectedOS, selectedBrowser, stateOptions) => boolean
300
- // Note: Can add PropTypes.shape({ disabled: PropTypes.bool, tooltip: PropTypes.string }) for tooltip support
301
- ]),
302
- };
303
-
304
- export default PreviewControls;
305
-