@capillarytech/creatives-library 8.0.292-alpha.15 → 8.0.292-alpha.18
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.
- package/package.json +1 -1
- package/v2Components/CommonTestAndPreview/UnifiedPreview/InAppPreviewContent.js +95 -59
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +40 -1
- package/v2Components/CommonTestAndPreview/constants.js +39 -0
- package/v2Containers/InApp/index.js +4 -5
package/package.json
CHANGED
|
@@ -15,13 +15,34 @@ import CapImage from '@capillarytech/cap-ui-library/CapImage';
|
|
|
15
15
|
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
16
16
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
17
17
|
import isEmpty from 'lodash/isEmpty';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ANDROID,
|
|
20
|
+
IOS,
|
|
21
|
+
LAYOUT_TYPE_POPUP,
|
|
22
|
+
LAYOUT_TYPE_HEADER,
|
|
23
|
+
LAYOUT_TYPE_FOOTER,
|
|
24
|
+
LAYOUT_TYPE_FULLSCREEN,
|
|
25
|
+
ANDROID_DEVICE_NAME,
|
|
26
|
+
IOS_DEVICE_NAME,
|
|
27
|
+
CHANNELS,
|
|
28
|
+
INAPP_HTML_LAYOUT_POSITIONS,
|
|
29
|
+
} from '../constants';
|
|
19
30
|
import messages from '../messages';
|
|
20
31
|
|
|
21
32
|
// Import device mockup images (same as SMS)
|
|
22
33
|
const smsMobileAndroid = require('../../../assets/Android.png');
|
|
23
34
|
const smsMobileIos = require('../../../assets/iOS.png');
|
|
24
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Detects if a string is HTML content (e.g. from HtmlEditor InApp template).
|
|
38
|
+
* Used to render HTML in an iframe (like InAppPreviewPane/ContentOverlay) instead of as plain text.
|
|
39
|
+
*/
|
|
40
|
+
const isHtmlContent = (str) => {
|
|
41
|
+
if (typeof str !== 'string' || !str.trim()) return false;
|
|
42
|
+
const trimmed = str.trim();
|
|
43
|
+
return trimmed.startsWith('<') && (trimmed.includes('>') || trimmed.includes('/'));
|
|
44
|
+
};
|
|
45
|
+
|
|
25
46
|
const InAppPreviewContent = ({
|
|
26
47
|
content,
|
|
27
48
|
device,
|
|
@@ -51,6 +72,12 @@ const InAppPreviewContent = ({
|
|
|
51
72
|
templateLayoutType: deviceLayoutType = templateLayoutType || LAYOUT_TYPE_POPUP,
|
|
52
73
|
} = deviceContent || {};
|
|
53
74
|
|
|
75
|
+
// When templateMsg is HTML (e.g. from HtmlEditor), render it in an iframe like InAppPreviewPane/ContentOverlay
|
|
76
|
+
const renderAsHtml = isHtmlContent(templateMsg);
|
|
77
|
+
|
|
78
|
+
// Layout positioning for HTML preview (modal, top banner, bottom banner, fullscreen) - match side-by-side ContentOverlay
|
|
79
|
+
const htmlLayoutKey = deviceLayoutType || LAYOUT_TYPE_POPUP;
|
|
80
|
+
const htmlLayoutPosition = INAPP_HTML_LAYOUT_POSITIONS[htmlLayoutKey] || INAPP_HTML_LAYOUT_POSITIONS[LAYOUT_TYPE_POPUP];
|
|
54
81
|
|
|
55
82
|
// Render loading state
|
|
56
83
|
if (isUpdating) {
|
|
@@ -106,76 +133,85 @@ const InAppPreviewContent = ({
|
|
|
106
133
|
alt={`${deviceName} Device`}
|
|
107
134
|
/>
|
|
108
135
|
|
|
109
|
-
{/* Content Overlay - Use TemplatePreview's InApp structure (
|
|
136
|
+
{/* Content Overlay - Use TemplatePreview's InApp structure or iframe for HTML (like InAppPreviewPane) */}
|
|
110
137
|
<CapRow className={`sms-content-overlay inapp-content-overlay-height ${!showHeader ? 'inapp-content-overlay' : ''} sms-${device}`}>
|
|
111
|
-
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
138
|
+
{renderAsHtml ? (
|
|
139
|
+
/* HTML content from HtmlEditor: position by layout (modal/top/bottom/fullscreen) like side-by-side ContentOverlay */
|
|
140
|
+
<div
|
|
141
|
+
className={`inapp-html-preview-iframe-wrapper inapp-html-preview-iframe-wrapper--${(htmlLayoutKey || '').toLowerCase()}`}
|
|
142
|
+
style={{
|
|
143
|
+
position: 'absolute',
|
|
144
|
+
...htmlLayoutPosition,
|
|
145
|
+
}}
|
|
117
146
|
>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
147
|
+
<iframe
|
|
148
|
+
srcDoc={templateMsg}
|
|
149
|
+
title="InApp HTML Preview"
|
|
150
|
+
sandbox="allow-scripts allow-same-origin"
|
|
151
|
+
className="inapp-html-preview-iframe"
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
) : (
|
|
155
|
+
/* TemplatePreview InApp structure - shell-v2 wrapper (template title/message/image/CTA) */
|
|
156
|
+
<CapRow className={`inapp-shell-v2 inapp-${device}`}>
|
|
157
|
+
<CapRow
|
|
158
|
+
className={`inapp-message-container-${deviceLayoutType || LAYOUT_TYPE_POPUP} ${!showHeader && deviceLayoutType === LAYOUT_TYPE_FOOTER ? 'inapp-message-container-FOOTER-no-header' : ''} ${CHANNELS.SMS.toLowerCase()}`}
|
|
159
|
+
>
|
|
160
|
+
<CapRow className="preview-inapp-screen">
|
|
161
|
+
<CapLabel
|
|
162
|
+
type="label16"
|
|
163
|
+
className={`inapp-title-${deviceLayoutType || LAYOUT_TYPE_POPUP} ${
|
|
124
164
|
mediaPreview?.inAppImageSrcAndroid || mediaPreview?.inAppImageSrcIos
|
|
125
165
|
? ''
|
|
126
166
|
: `without-image-title-${deviceLayoutType || LAYOUT_TYPE_POPUP}`
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
<CapLabel
|
|
149
|
-
type="label2"
|
|
150
|
-
className={`align-left inapp-content-${deviceLayoutType || LAYOUT_TYPE_POPUP} ${
|
|
167
|
+
}`}
|
|
168
|
+
>
|
|
169
|
+
{/* eslint-disable-next-line no-unneeded-ternary */}
|
|
170
|
+
{templateTitle ? templateTitle : ' '}
|
|
171
|
+
</CapLabel>
|
|
172
|
+
|
|
173
|
+
{mediaPreview && (mediaPreview?.inAppImageSrcAndroid || mediaPreview?.inAppImageSrcIos) && (
|
|
174
|
+
<CapImage
|
|
175
|
+
src={
|
|
176
|
+
device.toLowerCase() === ANDROID
|
|
177
|
+
? mediaPreview?.inAppImageSrcAndroid
|
|
178
|
+
: mediaPreview?.inAppImageSrcIos
|
|
179
|
+
}
|
|
180
|
+
className={`inapp-image-${deviceLayoutType || LAYOUT_TYPE_POPUP}`}
|
|
181
|
+
alt={formatMessage(messages.previewGenerated)}
|
|
182
|
+
/>
|
|
183
|
+
)}
|
|
184
|
+
|
|
185
|
+
<CapLabel
|
|
186
|
+
type="label2"
|
|
187
|
+
className={`align-left inapp-content-${deviceLayoutType || LAYOUT_TYPE_POPUP} ${
|
|
151
188
|
mediaPreview?.inAppImageSrcAndroid || mediaPreview?.inAppImageSrcIos
|
|
152
189
|
? ''
|
|
153
190
|
: `without-image-content-${deviceLayoutType || LAYOUT_TYPE_POPUP}`
|
|
154
|
-
}`}
|
|
155
|
-
>
|
|
156
|
-
{/* eslint-disable-next-line no-unneeded-ternary */}
|
|
157
|
-
{templateMsg ? templateMsg : ' '}
|
|
158
|
-
{/* this ternary is required here for preview */}
|
|
159
|
-
</CapLabel>
|
|
160
|
-
|
|
161
|
-
{/* CTA Button - Same as TemplatePreview (line 1465-1482) */}
|
|
162
|
-
{ctaData
|
|
163
|
-
&& !isEmpty(ctaData)
|
|
164
|
-
&& (ctaData[0]?.text || ctaData[0]?.actionText) && (
|
|
165
|
-
<CapButton
|
|
166
|
-
type="primary"
|
|
167
|
-
className={`inapp-button-${deviceLayoutType || LAYOUT_TYPE_POPUP} ${
|
|
168
|
-
mediaPreview?.inAppImageSrcAndroid || mediaPreview?.inAppImageSrcIos
|
|
169
|
-
? ''
|
|
170
|
-
: `without-image-button-${deviceLayoutType || LAYOUT_TYPE_POPUP}`
|
|
171
191
|
}`}
|
|
172
192
|
>
|
|
173
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
{/* eslint-disable-next-line no-unneeded-ternary */}
|
|
194
|
+
{templateMsg ? templateMsg : ' '}
|
|
195
|
+
</CapLabel>
|
|
196
|
+
|
|
197
|
+
{ctaData
|
|
198
|
+
&& !isEmpty(ctaData)
|
|
199
|
+
&& (ctaData[0]?.text || ctaData[0]?.actionText) && (
|
|
200
|
+
<CapButton
|
|
201
|
+
type="primary"
|
|
202
|
+
className={`inapp-button-${deviceLayoutType || LAYOUT_TYPE_POPUP} ${
|
|
203
|
+
mediaPreview?.inAppImageSrcAndroid || mediaPreview?.inAppImageSrcIos
|
|
204
|
+
? ''
|
|
205
|
+
: `without-image-button-${deviceLayoutType || LAYOUT_TYPE_POPUP}`
|
|
206
|
+
}`}
|
|
207
|
+
>
|
|
208
|
+
{ctaData[0]?.text || ctaData[0]?.actionText}
|
|
209
|
+
</CapButton>
|
|
210
|
+
)}
|
|
211
|
+
</CapRow>
|
|
176
212
|
</CapRow>
|
|
177
213
|
</CapRow>
|
|
178
|
-
|
|
214
|
+
)}
|
|
179
215
|
</CapRow>
|
|
180
216
|
</CapRow>
|
|
181
217
|
);
|
|
@@ -760,6 +760,45 @@
|
|
|
760
760
|
.inapp-content-overlay {
|
|
761
761
|
width: 24.929rem;
|
|
762
762
|
}
|
|
763
|
+
|
|
764
|
+
// InApp HTML preview (HtmlEditor content) - positioned by layout like side-by-side ContentOverlay
|
|
765
|
+
// Position/dimensions come from inline style (INAPP_HTML_LAYOUT_POSITIONS)
|
|
766
|
+
.inapp-html-preview-iframe-wrapper {
|
|
767
|
+
background: $CAP_WHITE;
|
|
768
|
+
overflow: hidden;
|
|
769
|
+
box-shadow: 0 0.125rem 0.75rem rgba($CAP_G01, 0.15);
|
|
770
|
+
border: 0.0625rem solid $CAP_G07;
|
|
771
|
+
|
|
772
|
+
&--popup {
|
|
773
|
+
border-radius: 0.75rem;
|
|
774
|
+
box-shadow: 0 0.25rem 1.25rem rgba($CAP_G01, 0.2);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
&--header {
|
|
778
|
+
border-radius: 0.5rem 0.5rem 0.75rem 0.75rem;
|
|
779
|
+
box-shadow: 0 0.125rem 0.5rem rgba($CAP_G01, 0.15);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
&--footer {
|
|
783
|
+
border-radius: 0.75rem 0.75rem 0.5rem 0.5rem;
|
|
784
|
+
box-shadow: 0 -0.125rem 0.5rem rgba($CAP_G01, 0.15);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
&--fullscreen {
|
|
788
|
+
border-radius: 0.25rem;
|
|
789
|
+
box-shadow: none;
|
|
790
|
+
border: none;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.inapp-html-preview-iframe {
|
|
795
|
+
width: 100%;
|
|
796
|
+
height: 100%;
|
|
797
|
+
min-height: 10rem;
|
|
798
|
+
border: none;
|
|
799
|
+
display: block;
|
|
800
|
+
background: $CAP_WHITE;
|
|
801
|
+
}
|
|
763
802
|
}
|
|
764
803
|
|
|
765
804
|
// WhatsApp Preview Content Styles (Phase 8)
|
|
@@ -1078,7 +1117,7 @@
|
|
|
1078
1117
|
|
|
1079
1118
|
// InApp message container styles - copied from TemplatePreview
|
|
1080
1119
|
// POPUP/MODAL layout for Android
|
|
1081
|
-
.inapp-message-container-POPUP {
|
|
1120
|
+
.inapp-message-container-POPUP, .inapp-message-container-MODAL {
|
|
1082
1121
|
background-color: $CAP_WHITE;
|
|
1083
1122
|
position: relative;
|
|
1084
1123
|
height: 22.5rem;
|
|
@@ -125,6 +125,45 @@ export const LAYOUT_TYPE_FOOTER = 'FOOTER';
|
|
|
125
125
|
export const LAYOUT_TYPE_MODAL = 'MODAL';
|
|
126
126
|
export const LAYOUT_TYPE_BANNER = 'BANNER';
|
|
127
127
|
|
|
128
|
+
// InApp HTML preview layout positions (match HtmlEditor ContentOverlay for consistent placement)
|
|
129
|
+
// Used when rendering HTML content in Test and Preview so modal/top/bottom/fullscreen match side-by-side preview
|
|
130
|
+
export const INAPP_HTML_LAYOUT_POSITIONS = {
|
|
131
|
+
[LAYOUT_TYPE_POPUP]: {
|
|
132
|
+
top: '50%',
|
|
133
|
+
left: '50%',
|
|
134
|
+
transform: 'translate(-50%, -50%)',
|
|
135
|
+
width: '85%',
|
|
136
|
+
height: '55%',
|
|
137
|
+
maxWidth: '320px',
|
|
138
|
+
maxHeight: '380px',
|
|
139
|
+
minHeight: '180px',
|
|
140
|
+
},
|
|
141
|
+
[LAYOUT_TYPE_HEADER]: {
|
|
142
|
+
top: '2%',
|
|
143
|
+
left: '50%',
|
|
144
|
+
transform: 'translateX(-50%)',
|
|
145
|
+
width: '90%',
|
|
146
|
+
height: '22%',
|
|
147
|
+
maxHeight: '160px',
|
|
148
|
+
minHeight: '100px',
|
|
149
|
+
},
|
|
150
|
+
[LAYOUT_TYPE_FOOTER]: {
|
|
151
|
+
bottom: '2%',
|
|
152
|
+
left: '50%',
|
|
153
|
+
transform: 'translateX(-50%)',
|
|
154
|
+
width: '90%',
|
|
155
|
+
height: '22%',
|
|
156
|
+
maxHeight: '160px',
|
|
157
|
+
minHeight: '100px',
|
|
158
|
+
},
|
|
159
|
+
[LAYOUT_TYPE_FULLSCREEN]: {
|
|
160
|
+
top: '2%',
|
|
161
|
+
left: '2%',
|
|
162
|
+
width: '96%',
|
|
163
|
+
height: '96%',
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
|
|
128
167
|
// ============================================
|
|
129
168
|
// CTA TYPE CONSTANTS
|
|
130
169
|
// ============================================
|
|
@@ -629,10 +629,9 @@ export const InApp = (props) => {
|
|
|
629
629
|
// tag Code end
|
|
630
630
|
|
|
631
631
|
const onTemplateLayoutTypeChange = ({ target: { value } }) => {
|
|
632
|
-
// Update layout type
|
|
633
|
-
//
|
|
632
|
+
// Update layout type only. Do NOT remount HTMLEditor so user edits persist.
|
|
633
|
+
// The editor receives layoutType prop and preview updates without losing content.
|
|
634
634
|
setTemplateLayoutType(value);
|
|
635
|
-
setHtmlEditorContentVersion((prev) => prev + 1);
|
|
636
635
|
};
|
|
637
636
|
|
|
638
637
|
|
|
@@ -1356,8 +1355,8 @@ export const InApp = (props) => {
|
|
|
1356
1355
|
variant={HTML_EDITOR_VARIANTS.INAPP}
|
|
1357
1356
|
layoutType={templateLayoutType}
|
|
1358
1357
|
initialContent={{
|
|
1359
|
-
android: htmlContentAndroidRef.current
|
|
1360
|
-
ios: htmlContentIosRef.current
|
|
1358
|
+
android: htmlContentAndroid ?? htmlContentAndroidRef.current ?? templateMessageAndroid ?? '',
|
|
1359
|
+
ios: htmlContentIos ?? htmlContentIosRef.current ?? templateMessageIos ?? '',
|
|
1361
1360
|
}}
|
|
1362
1361
|
onContentChange={handleHtmlContentChange}
|
|
1363
1362
|
onSave={handleHtmlSave}
|