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

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 (216) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/sagas/__tests__/assetPolling.test.js +74 -3
  7. package/sagas/assetPolling.js +8 -1
  8. package/services/api.js +10 -5
  9. package/services/tests/api.test.js +18 -0
  10. package/translations/en.json +0 -1
  11. package/utils/common.js +5 -0
  12. package/utils/commonUtils.js +14 -1
  13. package/utils/tests/commonUtil.test.js +224 -0
  14. package/utils/transformTemplateConfig.js +0 -10
  15. package/utils/transformerUtils.js +0 -42
  16. package/v2Components/CapDeviceContent/index.js +61 -56
  17. package/v2Components/CapImageUpload/constants.js +0 -2
  18. package/v2Components/CapImageUpload/index.js +14 -54
  19. package/v2Components/CapImageUpload/index.scss +1 -4
  20. package/v2Components/CapImageUpload/messages.js +0 -4
  21. package/v2Components/CapTagList/index.js +6 -1
  22. package/v2Components/CapTagListWithInput/index.js +5 -1
  23. package/v2Components/CapTagListWithInput/messages.js +1 -1
  24. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  25. package/v2Components/ErrorInfoNote/index.js +412 -72
  26. package/v2Components/ErrorInfoNote/messages.js +22 -0
  27. package/v2Components/ErrorInfoNote/style.scss +279 -2
  28. package/v2Components/HtmlEditor/HTMLEditor.js +220 -91
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1132 -133
  30. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
  31. package/v2Components/HtmlEditor/_htmlEditor.scss +107 -45
  32. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  33. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
  34. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
  35. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  36. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  37. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
  38. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  39. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  40. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  45. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
  46. package/v2Components/HtmlEditor/components/PreviewPane/index.js +10 -11
  47. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  48. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +70 -72
  49. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
  50. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
  51. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +362 -0
  52. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  53. package/v2Components/HtmlEditor/constants.js +29 -20
  54. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  55. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  56. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  57. package/v2Components/HtmlEditor/index.js +1 -1
  58. package/v2Components/HtmlEditor/messages.js +95 -85
  59. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +99 -101
  60. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  61. package/v2Components/HtmlEditor/utils/validationAdapter.js +34 -41
  62. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  63. package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
  64. package/v2Components/TemplatePreview/index.js +47 -32
  65. package/v2Components/TemplatePreview/messages.js +4 -0
  66. package/v2Components/TestAndPreviewSlidebox/index.js +31 -25
  67. package/v2Containers/App/constants.js +0 -5
  68. package/v2Containers/BeeEditor/index.js +82 -80
  69. package/v2Containers/BeePopupEditor/constants.js +10 -0
  70. package/v2Containers/BeePopupEditor/index.js +193 -0
  71. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  72. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +0 -1
  73. package/v2Containers/CreativesContainer/SlideBoxContent.js +148 -120
  74. package/v2Containers/CreativesContainer/SlideBoxFooter.js +9 -3
  75. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
  76. package/v2Containers/CreativesContainer/constants.js +1 -2
  77. package/v2Containers/CreativesContainer/index.js +173 -193
  78. package/v2Containers/CreativesContainer/messages.js +4 -4
  79. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  80. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +36 -0
  81. package/v2Containers/Email/actions.js +7 -0
  82. package/v2Containers/Email/constants.js +5 -1
  83. package/v2Containers/Email/index.js +13 -0
  84. package/v2Containers/Email/messages.js +32 -0
  85. package/v2Containers/Email/reducer.js +12 -1
  86. package/v2Containers/Email/sagas.js +41 -6
  87. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  88. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1046 -0
  89. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +193 -7
  90. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  91. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  92. package/v2Containers/EmailWrapper/constants.js +2 -0
  93. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +436 -67
  94. package/v2Containers/EmailWrapper/index.js +99 -23
  95. package/v2Containers/EmailWrapper/messages.js +61 -1
  96. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +111 -77
  97. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  98. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  99. package/v2Containers/InApp/actions.js +7 -0
  100. package/v2Containers/InApp/constants.js +20 -4
  101. package/v2Containers/InApp/index.js +801 -357
  102. package/v2Containers/InApp/index.scss +4 -3
  103. package/v2Containers/InApp/messages.js +7 -3
  104. package/v2Containers/InApp/reducer.js +21 -3
  105. package/v2Containers/InApp/sagas.js +29 -9
  106. package/v2Containers/InApp/selectors.js +25 -5
  107. package/v2Containers/InApp/tests/index.test.js +154 -50
  108. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  109. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  110. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  111. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
  112. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  113. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
  114. package/v2Containers/InAppWrapper/constants.js +16 -0
  115. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  116. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  117. package/v2Containers/InAppWrapper/index.js +148 -0
  118. package/v2Containers/InAppWrapper/messages.js +49 -0
  119. package/v2Containers/InappAdvance/index.js +1099 -0
  120. package/v2Containers/InappAdvance/index.scss +10 -0
  121. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  122. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -3
  123. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -2
  124. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -25
  125. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -18
  126. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -46
  127. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +0 -4
  128. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -8
  129. package/v2Containers/TagList/index.js +67 -1
  130. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  131. package/v2Containers/Templates/_templates.scss +56 -200
  132. package/v2Containers/Templates/actions.js +1 -2
  133. package/v2Containers/Templates/constants.js +0 -1
  134. package/v2Containers/Templates/index.js +124 -277
  135. package/v2Containers/Templates/messages.js +4 -24
  136. package/v2Containers/Templates/reducer.js +0 -2
  137. package/v2Containers/Templates/tests/index.test.js +0 -10
  138. package/v2Containers/TemplatesV2/index.js +2 -3
  139. package/v2Containers/TemplatesV2/messages.js +0 -4
  140. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -132
  141. package/v2Components/CapImageUrlUpload/constants.js +0 -19
  142. package/v2Components/CapImageUrlUpload/index.js +0 -455
  143. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  144. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  145. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
  146. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -175
  147. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  148. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -144
  149. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  150. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  151. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  152. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -633
  153. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  154. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  155. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -80
  156. package/v2Containers/WebPush/Create/index.js +0 -1755
  157. package/v2Containers/WebPush/Create/index.scss +0 -123
  158. package/v2Containers/WebPush/Create/messages.js +0 -199
  159. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -241
  160. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -290
  161. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -81
  162. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -240
  163. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
  164. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -144
  165. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  166. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  167. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  168. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  169. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  170. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  171. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  172. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  173. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -44
  174. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -110
  175. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  176. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -72
  177. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -55
  178. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -70
  179. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -512
  180. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -77
  181. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -527
  182. package/v2Containers/WebPush/Create/preview/constants.js +0 -162
  183. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -104
  184. package/v2Containers/WebPush/Create/preview/preview.scss +0 -409
  185. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -300
  186. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  187. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  188. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  189. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -303
  190. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  191. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  192. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  193. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -188
  194. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -106
  195. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  196. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -75
  197. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -174
  198. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  199. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1077
  200. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  201. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -943
  202. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -128
  203. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -121
  204. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  205. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -127
  206. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -116
  207. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  208. package/v2Containers/WebPush/actions.js +0 -60
  209. package/v2Containers/WebPush/constants.js +0 -108
  210. package/v2Containers/WebPush/index.js +0 -2
  211. package/v2Containers/WebPush/reducer.js +0 -104
  212. package/v2Containers/WebPush/sagas.js +0 -119
  213. package/v2Containers/WebPush/selectors.js +0 -65
  214. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  215. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  216. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -1,290 +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
- DUMMY_CTA_BUTTONS,
24
- NOTIFICATION_STATE_COLLAPSED,
25
- NOTIFICATION_STATE_EXPANDED,
26
- } from './constants';
27
-
28
- /**
29
- * Converts OS name to CSS class name format
30
- * @param {string} os - Operating system name (e.g., 'macOS', 'Android (Mobile)')
31
- * @returns {string} CSS class name (e.g., 'macos', 'android-mobile')
32
- */
33
- const getOSClassName = (os) => {
34
- const osMap = {
35
- [OS_MACOS]: 'macos',
36
- [OS_IOS]: 'ios',
37
- [OS_IPADOS]: 'ipados',
38
- [OS_WINDOWS]: 'windows',
39
- [OS_ANDROID_MOBILE]: 'android-mobile',
40
- [OS_ANDROID_TABLET]: 'android-tablet',
41
- };
42
- return osMap[os] || os.toLowerCase().replace(/\s+/g, '-').replace(/[()]/g, '');
43
- };
44
-
45
- /**
46
- * Converts Browser name to CSS class name format
47
- * @param {string} browser - Browser name (e.g., 'Chrome', 'Firefox')
48
- * @returns {string} CSS class name (e.g., 'chrome', 'firefox')
49
- */
50
- const getBrowserClassName = (browser) => {
51
- return browser.toLowerCase();
52
- };
53
-
54
- /**
55
- * Gets the combined platform + browser class name for notification-container
56
- * @param {string} os - Operating system name
57
- * @param {string} browser - Browser name
58
- * @returns {string} Combined class name (e.g., 'macos-chrome', 'windows-firefox')
59
- */
60
- const getNotificationContainerClassName = (os, browser) => {
61
- const osClass = getOSClassName(os);
62
- const browserClass = getBrowserClassName(browser);
63
- return `${osClass}-${browserClass}`;
64
- };
65
-
66
- // preview-only: strip protocol, drop www. only, remove child paths and trailing slashes
67
- const formatUrlForPreview = (rawUrl) => {
68
- if (!rawUrl) return rawUrl;
69
- const withoutProtocol = rawUrl.replace(/^https?:\/\//i, '');
70
- const withoutWww = withoutProtocol.startsWith('www.') ? withoutProtocol.slice(4) : withoutProtocol;
71
- // Remove child paths (everything after the first slash)
72
- const domainOnly = withoutWww.split('/')[0];
73
- return domainOnly.replace(/\/+$/, '');
74
- };
75
-
76
- /**
77
- * NotificationContainer Component
78
- *
79
- * Standalone notification container component that renders the actual notification UI.
80
- * This component is decoupled from any wrapper containers and can be used
81
- * in different contexts (main preview, device frame preview, etc.).
82
- *
83
- * The component renders the notification-container div with all its content:
84
- * - Notification header (icon, title, URL, body)
85
- * - Expanded content (media image, CTA buttons) when state is 'Expanded'
86
- *
87
- * @param {string} notificationTitle - Title of the notification
88
- * @param {string} notificationBody - Body text of the notification
89
- * @param {string} url - URL for the notification
90
- * @param {string} selectedOS - Operating system name
91
- * @param {string} selectedBrowser - Browser name
92
- * @param {string} notificationState - 'Collapsed' or 'Expanded' (default: 'Collapsed')
93
- * @param {string} className - Additional CSS classes to apply to the container
94
- * @param {string} icon - Icon asset for the browser (defaults to Chrome)
95
- * @param {boolean} supportsExpanded - Whether Expanded state is supported for this variant
96
- * @param {boolean} enableMedia - Whether to render media section when expanded
97
- * @param {boolean} enableCtas - Whether to render CTA buttons when expanded
98
- * @param {string} imageSrc - Media/banner image source URL
99
- * @param {string} brandIconSrc - Brand icon image source URL
100
- */
101
- const NotificationContainer = ({
102
- notificationTitle,
103
- notificationBody,
104
- url,
105
- selectedOS,
106
- selectedBrowser,
107
- notificationState = NOTIFICATION_STATE_COLLAPSED,
108
- className = '',
109
- icon = chromeIcon,
110
- supportsExpanded = true,
111
- enableMedia = true,
112
- enableCtas = true,
113
- brandIcon = '',
114
- enableBrandIconPreview = true,
115
- imageSrc = '',
116
- brandIconSrc = '',
117
- }) => {
118
- const isExpanded = supportsExpanded && notificationState === NOTIFICATION_STATE_EXPANDED;
119
- const notificationContainerClass = getNotificationContainerClassName(selectedOS, selectedBrowser);
120
- const stateClass = isExpanded ? 'expanded' : 'collapsed';
121
- const selectedBrowserLower = (selectedBrowser || '').toLowerCase();
122
-
123
- // Platform detection object - provides clean access to all platform/browser checks
124
- const platform = {
125
- parts: notificationContainerClass.split('-'),
126
- get os() { return this.parts[0]; },
127
- get browser() { return this.parts.length === 3 ? this.parts[2] : this.parts[1]; },
128
- get isMacOs() { return selectedOS === OS_MACOS; },
129
- get isIOS() { return selectedOS === OS_IOS; },
130
- get isIPadOS() { return selectedOS === OS_IPADOS; },
131
- get isAndroidMobile() { return this.os === 'android' && this.parts[1] === 'mobile'; },
132
- get isAndroidTablet() { return this.os === 'android' && this.parts[1] === 'tablet'; },
133
- get isIOSBrowser() { return this.os === 'ios'; },
134
- get isIPadOSBrowser() { return this.os === 'ipados'; },
135
- get isWindows() { return this.os === 'windows'; },
136
- get supportsBrandIcon() { return BRAND_ICON_SUPPORTED_BROWSERS.includes(selectedBrowserLower); },
137
- get isMacOsBrandIconBrowser() { return this.isMacOs && this.supportsBrandIcon; },
138
- get isWindowsExpanded() { return this.isWindows && isExpanded; },
139
- get isMacOsExpandedBrand() { return this.isMacOs && isExpanded && this.supportsBrandIcon; },
140
- };
141
-
142
- const displayUrl = formatUrlForPreview(url) || url || '';
143
- // Use real media image from form/props
144
- const mediaImageUrl = imageSrc || '';
145
- // Use real brand icon from form/props, fallback to prop if provided for backward compatibility
146
- const actualBrandIcon = brandIconSrc || brandIcon || '';
147
- const shouldShowBrandIconAndroidExpanded =
148
- (platform.isAndroidMobile || platform.isAndroidTablet) && isExpanded && enableBrandIconPreview && Boolean(actualBrandIcon);
149
- // TODO: Replace with actual CTA buttons from form/props
150
- // For now, using dummy values to show expanded state preview
151
- const ctaButtons = DUMMY_CTA_BUTTONS;
152
-
153
- // Brand icon preview toggle (set enableBrandIconPreview to false to see no-brand state)
154
- const shouldShowBrandIcon = (() => {
155
- // iOS/iPadOS NEVER show brand icons - they use a simple notification style
156
- if (platform.isIOSBrowser || platform.isIPadOSBrowser) return false;
157
-
158
- if (!enableBrandIconPreview || !actualBrandIcon) return false;
159
- if (platform.isAndroidMobile && !isExpanded) return true;
160
- if (platform.isAndroidTablet && !isExpanded) return true;
161
- // macOS: show brand icon for all browsers in collapsed state
162
- if (platform.isMacOs && !isExpanded) return true;
163
- // Windows browsers: show brand icon in collapsed state (same as macOS Chrome)
164
- if (platform.isWindows && !isExpanded) return true;
165
- return false;
166
- })();
167
-
168
- const shouldShowBrandIconInExpandedMac = (() => {
169
- if (!platform.isMacOsExpandedBrand) return false;
170
- if (!enableBrandIconPreview || !actualBrandIcon) return false;
171
- return true;
172
- })();
173
-
174
- const shouldRenderExpandedMedia = (() => {
175
- if (!enableMedia) return false;
176
- if (platform.isMacOsExpandedBrand) {
177
- // For macOS brand browsers, only render if brand icon is available.
178
- return shouldShowBrandIconInExpandedMac;
179
- }
180
- return Boolean(mediaImageUrl);
181
- })();
182
-
183
- const containerClasses = [
184
- 'notification-container',
185
- notificationContainerClass,
186
- stateClass,
187
- className,
188
- platform.isWindowsExpanded ? 'windows-chrome-expanded' : '',
189
- ]
190
- .filter(Boolean)
191
- .join(' ')
192
- .trim();
193
-
194
- // Get browser display name for Windows expanded notifications
195
- const getBrowserDisplayName = (browser) => {
196
- return BROWSER_DISPLAY_NAMES[browser] || browser;
197
- };
198
-
199
- return (
200
- <div className={containerClasses}>
201
- {platform.isWindowsExpanded ? (
202
- <WindowsChromeExpanded
203
- icon={icon}
204
- brandIcon={actualBrandIcon}
205
- enableBrandIconPreview={enableBrandIconPreview}
206
- notificationTitle={notificationTitle}
207
- notificationBody={notificationBody}
208
- displayUrl={displayUrl}
209
- browserName={getBrowserDisplayName(selectedBrowser)}
210
- mediaImageUrl={mediaImageUrl}
211
- />
212
- ) : (platform.isAndroidMobile || platform.isAndroidTablet) && isExpanded ? (
213
- <AndroidMobileExpanded
214
- icon={icon}
215
- selectedBrowser={selectedBrowser}
216
- notificationTitle={notificationTitle}
217
- notificationBody={notificationBody}
218
- displayUrl={displayUrl}
219
- brandIcon={actualBrandIcon}
220
- shouldShowBrandIcon={shouldShowBrandIcon}
221
- shouldShowBrandIconExpanded={shouldShowBrandIconAndroidExpanded}
222
- mediaImageUrl={mediaImageUrl}
223
- />
224
- ) : (
225
- <>
226
- {(platform.isAndroidMobile || platform.isAndroidTablet) && !isExpanded ? (
227
- <AndroidMobileChromeHeader
228
- icon={icon}
229
- selectedBrowser={selectedBrowser}
230
- notificationTitle={notificationTitle}
231
- notificationBody={notificationBody}
232
- brandIcon={actualBrandIcon}
233
- shouldShowBrandIcon={shouldShowBrandIcon}
234
- />
235
- ) : (platform.isIOSBrowser || platform.isIPadOSBrowser) ? (
236
- <IOSHeader
237
- icon={icon}
238
- selectedBrowser={selectedBrowser}
239
- notificationTitle={notificationTitle}
240
- notificationBody={notificationBody}
241
- />
242
- ) : (
243
- <NotificationHeader
244
- icon={icon}
245
- selectedBrowser={selectedBrowser}
246
- notificationTitle={notificationTitle}
247
- displayUrl={displayUrl}
248
- notificationBody={notificationBody}
249
- shouldShowBrandIcon={shouldShowBrandIcon}
250
- brandIcon={actualBrandIcon}
251
- isExpanded={isExpanded}
252
- />
253
- )}
254
-
255
- {isExpanded && (
256
- <NotificationExpandedContent
257
- shouldRenderExpandedMedia={shouldRenderExpandedMedia}
258
- shouldShowBrandIconInExpandedMac={shouldShowBrandIconInExpandedMac}
259
- brandIcon={actualBrandIcon}
260
- mediaImageUrl={mediaImageUrl}
261
- enableCtas={enableCtas}
262
- ctaButtons={ctaButtons}
263
- />
264
- )}
265
- </>
266
- )}
267
- </div>
268
- );
269
- };
270
-
271
- NotificationContainer.propTypes = {
272
- notificationTitle: PropTypes.string,
273
- notificationBody: PropTypes.string,
274
- url: PropTypes.string,
275
- selectedOS: PropTypes.string.isRequired,
276
- selectedBrowser: PropTypes.string.isRequired,
277
- notificationState: PropTypes.oneOf([NOTIFICATION_STATE_COLLAPSED, NOTIFICATION_STATE_EXPANDED]),
278
- className: PropTypes.string,
279
- icon: PropTypes.string,
280
- supportsExpanded: PropTypes.bool,
281
- enableMedia: PropTypes.bool,
282
- enableCtas: PropTypes.bool,
283
- brandIcon: PropTypes.string,
284
- enableBrandIconPreview: PropTypes.bool,
285
- imageSrc: PropTypes.string,
286
- brandIconSrc: PropTypes.string,
287
- };
288
-
289
- export default NotificationContainer;
290
-
@@ -1,81 +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
- }) => {
31
- const resolvedVariant = getResolvedVariant(selectedOS, selectedBrowser, notificationState);
32
-
33
- return (
34
- <div className="preview-content">
35
- <div className="preview-content-wrapper">
36
- <div className={`notification-preview ${resolvedVariant ? '' : 'preview-unavailable'}`.trim()}>
37
- {resolvedVariant && (
38
- <NotificationContainer
39
- notificationTitle={notificationTitle}
40
- notificationBody={notificationBody}
41
- url={url}
42
- selectedOS={selectedOS}
43
- selectedBrowser={selectedBrowser}
44
- notificationState={resolvedVariant.stateKey}
45
- icon={resolvedVariant.variant.icon}
46
- supportsExpanded={resolvedVariant.stateConfig.supportsExpanded}
47
- enableMedia={resolvedVariant.stateConfig.showMedia}
48
- // CTA buttons intentionally disabled per requirement change; do not enable unless confirmed.
49
- enableCtas={false}
50
- className={resolvedVariant.variant.notificationClassName}
51
- imageSrc={imageSrc}
52
- brandIconSrc={brandIconSrc}
53
- />
54
- )}
55
- </div>
56
- </div>
57
- </div>
58
- );
59
- };
60
-
61
- PreviewContent.propTypes = {
62
- notificationTitle: PropTypes.string,
63
- notificationBody: PropTypes.string,
64
- url: PropTypes.string,
65
- selectedOS: PropTypes.string.isRequired,
66
- selectedBrowser: PropTypes.string.isRequired,
67
- notificationState: PropTypes.oneOf([NOTIFICATION_STATE_COLLAPSED, NOTIFICATION_STATE_EXPANDED]),
68
- imageSrc: PropTypes.string,
69
- brandIconSrc: PropTypes.string,
70
- };
71
-
72
- PreviewContent.defaultProps = {
73
- notificationTitle: '',
74
- notificationBody: '',
75
- url: '',
76
- imageSrc: '',
77
- brandIconSrc: '',
78
- };
79
-
80
- export default PreviewContent;
81
-
@@ -1,240 +0,0 @@
1
- import React, { useCallback } 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
- */
26
- const PreviewControls = ({
27
- selectedOS,
28
- selectedBrowser,
29
- selectedState,
30
- osOptions,
31
- browserOptions,
32
- stateOptions,
33
- onOSChange,
34
- onBrowserChange,
35
- onStateChange,
36
- layoutMode = LAYOUT_MODE.NEW_ROW,
37
- showStateDropdown = true,
38
- }) => {
39
- const selectWidth = layoutMode === LAYOUT_MODE.COMPACT ? SELECT_WIDTH.COMPACT : SELECT_WIDTH.FULL;
40
-
41
- /**
42
- * Cascading dropdown reset handler for OS changes
43
- * Resets Browser and State to first available option when OS changes
44
- *
45
- * This implements cascading dropdown behavior: when a parent dropdown (OS) changes,
46
- * dependent dropdowns (Browser, State) reset to their first available option.
47
- */
48
- const handleOSChangeWithCascade = useCallback((value) => {
49
- onOSChange(value);
50
-
51
- // Get browser options for the new OS to ensure we reset to a valid option
52
- const newBrowserOptions = getBrowserOptionsForOS(value);
53
-
54
- // Reset Browser to first available option for the new OS
55
- const newBrowserValue = newBrowserOptions && newBrowserOptions.length > 0
56
- ? newBrowserOptions[0].value
57
- : null;
58
-
59
- if (newBrowserValue && onBrowserChange) {
60
- onBrowserChange(newBrowserValue);
61
- }
62
-
63
- // Compute fresh state options based on new OS and Browser combination
64
- // Only reset state if stateOptions is provided and not empty
65
- if (showStateDropdown && newBrowserValue && onStateChange && stateOptions && stateOptions.length > 0) {
66
- const newSupportedStates = getSupportedStates(value, newBrowserValue);
67
- const newStateOptions = newSupportedStates.length > 0
68
- ? newSupportedStates.map((state) => ({ value: state, label: state }))
69
- : STATE_OPTIONS;
70
-
71
- if (newStateOptions.length > 0) {
72
- onStateChange(newStateOptions[0].value);
73
- }
74
- }
75
- }, [onOSChange, onBrowserChange, onStateChange, stateOptions, showStateDropdown]);
76
-
77
- /**
78
- * Cascading dropdown reset handler for Browser changes
79
- * Resets State to first available option when Browser changes
80
- */
81
- const handleBrowserChangeWithCascade = useCallback((value) => {
82
- onBrowserChange(value);
83
-
84
- // Compute fresh state options based on current OS and new Browser combination
85
- // Only reset state if stateOptions is provided and not empty
86
- if (showStateDropdown && onStateChange && stateOptions && stateOptions.length > 0) {
87
- const newSupportedStates = getSupportedStates(selectedOS, value);
88
- const newStateOptions = newSupportedStates.length > 0
89
- ? newSupportedStates.map((state) => ({ value: state, label: state }))
90
- : STATE_OPTIONS;
91
-
92
- if (newStateOptions.length > 0) {
93
- onStateChange(newStateOptions[0].value);
94
- }
95
- }
96
- }, [onBrowserChange, onStateChange, selectedOS, stateOptions, showStateDropdown]);
97
-
98
- const controls = [
99
- {
100
- key: 'os',
101
- label: 'operatingSystem',
102
- value: selectedOS,
103
- options: osOptions,
104
- onChange: handleOSChangeWithCascade,
105
- className: 'preview-control-os',
106
- },
107
- {
108
- key: 'browser',
109
- label: 'browser',
110
- value: selectedBrowser,
111
- options: browserOptions,
112
- onChange: handleBrowserChangeWithCascade,
113
- className: 'preview-control-browser',
114
- },
115
- ];
116
-
117
- if (showStateDropdown) {
118
- controls.push({
119
- key: 'state',
120
- label: 'state',
121
- value: selectedState,
122
- options: stateOptions,
123
- onChange: onStateChange,
124
- className: 'preview-control-state',
125
- });
126
- }
127
-
128
- const renderControl = ({ key, label, value, options, onChange, className }) => (
129
- <div key={key} className={`preview-control ${className}`}>
130
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
131
- <FormattedMessage {...messages[label]} />
132
- </CapLabel>
133
- <CapSelect.CapCustomSelect
134
- width={selectWidth}
135
- options={options}
136
- value={value}
137
- onChange={onChange}
138
- />
139
- </div>
140
- );
141
-
142
- if (layoutMode === LAYOUT_MODE.COMPACT) {
143
- return (
144
- <div className="preview-controls preview-controls-compact">
145
- {controls.map(renderControl)}
146
- </div>
147
- );
148
- }
149
-
150
- return (
151
- <>
152
- <CapRow className="preview-controls">
153
- <CapColumn span={12} className="preview-control-os">
154
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
155
- <FormattedMessage {...messages.operatingSystem} />
156
- </CapLabel>
157
- <CapSelect.CapCustomSelect
158
- width={selectWidth}
159
- options={osOptions}
160
- value={selectedOS}
161
- onChange={handleOSChangeWithCascade}
162
- />
163
- </CapColumn>
164
- <CapColumn span={12} className="preview-control-browser">
165
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
166
- <FormattedMessage {...messages.browser} />
167
- </CapLabel>
168
- <CapSelect.CapCustomSelect
169
- width={selectWidth}
170
- options={browserOptions}
171
- value={selectedBrowser}
172
- onChange={handleBrowserChangeWithCascade}
173
- />
174
- </CapColumn>
175
- </CapRow>
176
- {showStateDropdown && layoutMode === LAYOUT_MODE.NEW_ROW && (
177
- <CapRow className="preview-controls-state">
178
- <CapColumn span={12} className="preview-control-state">
179
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
180
- <FormattedMessage {...messages.state} />
181
- </CapLabel>
182
- <CapSelect.CapCustomSelect
183
- width={selectWidth}
184
- options={stateOptions}
185
- value={selectedState}
186
- onChange={onStateChange}
187
- />
188
- </CapColumn>
189
- </CapRow>
190
- )}
191
- {showStateDropdown && layoutMode === LAYOUT_MODE.INLINE && (
192
- <CapRow className="preview-controls">
193
- <CapColumn span={12} className="preview-control-state">
194
- <CapLabel type="label1" className="preview-control-label" fontWeight="bold">
195
- <FormattedMessage {...messages.state} />
196
- </CapLabel>
197
- <CapSelect.CapCustomSelect
198
- width={selectWidth}
199
- options={stateOptions}
200
- value={selectedState}
201
- onChange={onStateChange}
202
- />
203
- </CapColumn>
204
- </CapRow>
205
- )}
206
- </>
207
- );
208
- };
209
-
210
- PreviewControls.propTypes = {
211
- selectedOS: PropTypes.string.isRequired,
212
- selectedBrowser: PropTypes.string.isRequired,
213
- selectedState: PropTypes.string,
214
- osOptions: PropTypes.arrayOf(
215
- PropTypes.shape({
216
- value: PropTypes.string.isRequired,
217
- label: PropTypes.string.isRequired,
218
- }),
219
- ).isRequired,
220
- browserOptions: PropTypes.arrayOf(
221
- PropTypes.shape({
222
- value: PropTypes.string.isRequired,
223
- label: PropTypes.string.isRequired,
224
- }),
225
- ).isRequired,
226
- stateOptions: PropTypes.arrayOf(
227
- PropTypes.shape({
228
- value: PropTypes.string.isRequired,
229
- label: PropTypes.string.isRequired,
230
- }),
231
- ),
232
- onOSChange: PropTypes.func.isRequired,
233
- onBrowserChange: PropTypes.func.isRequired,
234
- onStateChange: PropTypes.func,
235
- layoutMode: PropTypes.oneOf([LAYOUT_MODE.INLINE, LAYOUT_MODE.NEW_ROW, LAYOUT_MODE.COMPACT]),
236
- showStateDropdown: PropTypes.bool,
237
- };
238
-
239
- export default PreviewControls;
240
-
@@ -1,23 +0,0 @@
1
- import React from 'react';
2
- import CapRow from '@capillarytech/cap-ui-library/CapRow';
3
- import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
4
- import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
5
- import './preview.scss';
6
-
7
- /**
8
- * PreviewDisclaimer Component
9
- *
10
- * Renders disclaimer text below the preview area.
11
- */
12
- const PreviewDisclaimer = () => (
13
- <CapRow className="preview-disclaimer">
14
- <CapColumn span={24}>
15
- <CapLabel type="label2" className="disclaimer-text">
16
- For the most accurate desktop preview, switch to full screen under &apos;Preview in all devices&apos;.
17
- </CapLabel>
18
- </CapColumn>
19
- </CapRow>
20
- );
21
-
22
- export default PreviewDisclaimer;
23
-