@capillarytech/creatives-library 9.0.15-alpha.1 → 9.0.15-alpha.3
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/CapActionButton/constants.js +1 -1
- package/v2Components/CapActionButton/index.js +38 -39
- package/v2Components/CapActionButton/index.scss +82 -15
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +76 -74
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +103 -81
- package/v2Components/CommonTestAndPreview/messages.js +3 -3
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +4 -4
- package/v2Components/TemplatePreview/_templatePreview.scss +5 -4
- package/v2Components/TemplatePreview/index.js +4 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +1 -0
- package/v2Containers/Rcs/index.js +145 -87
- package/v2Containers/Rcs/index.scss +156 -2
- package/v2Containers/Rcs/messages.js +11 -3
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +412 -643
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +10 -66
- package/v2Containers/Rcs/tests/index.test.js +4 -4
- package/v2Containers/Rcs/tests/utils.test.js +18 -21
- package/v2Containers/Rcs/utils.js +35 -48
- package/v2Containers/Templates/_templates.scss +52 -27
- package/v2Containers/Templates/index.js +6 -4
|
@@ -206,6 +206,7 @@ export const Rcs = (props) => {
|
|
|
206
206
|
showTestAndPreviewSlidebox: propsShowTestAndPreviewSlidebox,
|
|
207
207
|
handleTestAndPreview: propsHandleTestAndPreview,
|
|
208
208
|
handleCloseTestAndPreview: propsHandleCloseTestAndPreview,
|
|
209
|
+
handleClose,
|
|
209
210
|
} = props || {};
|
|
210
211
|
const { formatMessage } = intl;
|
|
211
212
|
const { TextArea } = CapInput;
|
|
@@ -621,31 +622,43 @@ export const Rcs = (props) => {
|
|
|
621
622
|
<CapRow gutter={16} className="rcs-carousel-dimension-row">
|
|
622
623
|
<CapColumn span={12}>
|
|
623
624
|
<CapHeading type="h4" className="rcs-carousel-dimension-label">Card height</CapHeading>
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
625
|
+
{isEditFlow ? (
|
|
626
|
+
<CapHeading type="h5" className="rcs-creative-name-value">
|
|
627
|
+
{CAROUSEL_HEIGHT_OPTIONS.find((option) => option.value === selectedCarouselHeight)?.label || '-'}
|
|
628
|
+
</CapHeading>
|
|
629
|
+
) : (
|
|
630
|
+
<CapSelect
|
|
631
|
+
id="rcs-carousel-height-select"
|
|
632
|
+
value={selectedCarouselHeight}
|
|
633
|
+
onChange={(val) => {
|
|
634
|
+
// Like rich-card dimension changes: clear media so user re-uploads matching new dimensions.
|
|
635
|
+
resetCarouselMediaForAllCards();
|
|
636
|
+
setSelectedCarouselHeight(val);
|
|
637
|
+
}}
|
|
638
|
+
options={CAROUSEL_HEIGHT_OPTIONS}
|
|
639
|
+
disabled={!isFullMode}
|
|
640
|
+
/>
|
|
641
|
+
)}
|
|
635
642
|
</CapColumn>
|
|
636
643
|
<CapColumn span={12}>
|
|
637
644
|
<CapHeading type="h4" className="rcs-carousel-dimension-label">Card width</CapHeading>
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
645
|
+
{isEditFlow ? (
|
|
646
|
+
<CapHeading type="h5" className="rcs-creative-name-value">
|
|
647
|
+
{CAROUSEL_WIDTH_OPTIONS.find((option) => option.value === selectedCarouselWidth)?.label || '-'}
|
|
648
|
+
</CapHeading>
|
|
649
|
+
) : (
|
|
650
|
+
<CapSelect
|
|
651
|
+
id="rcs-carousel-width-select"
|
|
652
|
+
value={selectedCarouselWidth}
|
|
653
|
+
onChange={(val) => {
|
|
654
|
+
// Like rich-card dimension changes: clear media so user re-uploads matching new dimensions.
|
|
655
|
+
resetCarouselMediaForAllCards();
|
|
656
|
+
setSelectedCarouselWidth(val);
|
|
657
|
+
}}
|
|
658
|
+
options={CAROUSEL_WIDTH_OPTIONS}
|
|
659
|
+
disabled={!isFullMode}
|
|
660
|
+
/>
|
|
661
|
+
)}
|
|
649
662
|
</CapColumn>
|
|
650
663
|
</CapRow>
|
|
651
664
|
{!!selectedCarousel && (
|
|
@@ -672,7 +685,7 @@ export const Rcs = (props) => {
|
|
|
672
685
|
</CapHeading>
|
|
673
686
|
</CapRow>
|
|
674
687
|
)}
|
|
675
|
-
description={(
|
|
688
|
+
description={!isEditFlow && (
|
|
676
689
|
<CapLabel type="label3">{formatMessage(messages.btnDesc)}</CapLabel>
|
|
677
690
|
)}
|
|
678
691
|
/>
|
|
@@ -771,7 +784,7 @@ export const Rcs = (props) => {
|
|
|
771
784
|
// Default: IMAGE
|
|
772
785
|
return (
|
|
773
786
|
<>
|
|
774
|
-
<CapHeading type="h4" className="rcs-image-dimensions-label">
|
|
787
|
+
<CapHeading type="h4" className="rcs-image-dimensions-label">{formatMessage(messages.mediaImage)}</CapHeading>
|
|
775
788
|
<CapImageUpload
|
|
776
789
|
allowedExtensionsRegex={ALLOWED_IMAGE_EXTENSIONS_REGEX}
|
|
777
790
|
imgWidth={RCS_CAROUSEL_IMAGE_DIMENSIONS?.[dimKey]?.width}
|
|
@@ -838,41 +851,50 @@ export const Rcs = (props) => {
|
|
|
838
851
|
className="rcs-carousel-card"
|
|
839
852
|
>
|
|
840
853
|
{/* Media selection should be at top of card */}
|
|
841
|
-
|
|
842
|
-
<
|
|
854
|
+
{isEditFlow ? (
|
|
855
|
+
<div className="rcs-creative-name-readonly">
|
|
843
856
|
<CapHeading type="h4">{formatMessage(messages.mediaTypeLabel)}</CapHeading>
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
857
|
+
<CapHeading type="h5" className="rcs-creative-name-value">
|
|
858
|
+
{mediaRadioOptions.find((option) => option.value === card.mediaType)?.label || '-'}
|
|
859
|
+
</CapHeading>
|
|
860
|
+
</div>
|
|
861
|
+
) : (
|
|
862
|
+
<CapRow className="rcs-carousel-media-selection">
|
|
863
|
+
<CapColumn className="rcs-carousel-media-selection-heading">
|
|
864
|
+
<CapHeading type="h4">{formatMessage(messages.mediaTypeLabel)}</CapHeading>
|
|
865
|
+
</CapColumn>
|
|
866
|
+
<CapColumn>
|
|
867
|
+
<CapRadioGroup
|
|
868
|
+
id={`rcs-carousel-media-radio-${index}`}
|
|
869
|
+
options={mediaRadioOptions}
|
|
870
|
+
value={card.mediaType}
|
|
871
|
+
onChange={({ target: { value } }) => {
|
|
872
|
+
// Reset media fields when switching type
|
|
873
|
+
if (value === RCS_MEDIA_TYPES.IMAGE) {
|
|
874
|
+
// Switching to IMAGE: clear video + thumbnail uploads so they don't auto-restore.
|
|
875
|
+
clearCarouselCardMedia(index, { clearImage: false, clearVideo: true, clearThumb: true });
|
|
876
|
+
handleCarouselValueChange(index, [
|
|
877
|
+
{ fieldName: 'mediaType', value },
|
|
878
|
+
{ fieldName: 'videoAsset', value: {} },
|
|
879
|
+
{ fieldName: 'thumbnailSrc', value: '' },
|
|
880
|
+
]);
|
|
881
|
+
} else {
|
|
882
|
+
// Switching to VIDEO: clear image upload so it doesn't auto-restore.
|
|
883
|
+
clearCarouselCardMedia(index, { clearImage: true, clearVideo: false, clearThumb: false });
|
|
884
|
+
handleCarouselValueChange(index, [
|
|
885
|
+
{ fieldName: 'mediaType', value },
|
|
886
|
+
{ fieldName: 'imageSrc', value: '' },
|
|
887
|
+
]);
|
|
888
|
+
}
|
|
889
|
+
}}
|
|
890
|
+
disabled={!isFullMode}
|
|
891
|
+
className="rcs-radio"
|
|
892
|
+
/>
|
|
893
|
+
</CapColumn>
|
|
894
|
+
</CapRow>
|
|
895
|
+
)}
|
|
874
896
|
|
|
875
|
-
<CapRow className=
|
|
897
|
+
<CapRow className={`rcs-carousel-media-upload ${isEditFlow ? 'rcs-carousel-media-upload--readonly-above' : ''}`}>
|
|
876
898
|
{renderCarouselCardMedia(index)}
|
|
877
899
|
</CapRow>
|
|
878
900
|
|
|
@@ -1015,27 +1037,41 @@ export const Rcs = (props) => {
|
|
|
1015
1037
|
const renderCarouselSection = () => {
|
|
1016
1038
|
if (!isCarouselType) return null;
|
|
1017
1039
|
|
|
1018
|
-
const
|
|
1040
|
+
const isMaxCarouselCardsReached = MAX_RCS_CAROUSEL_ALLOWED === (carouselData?.length || 0);
|
|
1041
|
+
const addCardTooltipTitle = isMaxCarouselCardsReached
|
|
1042
|
+
? formatMessage(messages.rcsCarouselMaxCardTooltip, { max: MAX_RCS_CAROUSEL_ALLOWED })
|
|
1043
|
+
// "Set up the first card" only makes sense while creating a new template —
|
|
1044
|
+
// in edit flow the cards already exist, so don't show it there.
|
|
1045
|
+
: (!isEditFlow && checkDisableAddCarouselButton() ? formatMessage(messages.rcsCarouselAddCardDisabledTooltip) : '');
|
|
1046
|
+
|
|
1047
|
+
// No "+" in edit flow (cards can't be added there) — and with no "+", the
|
|
1048
|
+
// divider before it has nothing to separate, so skip both together instead
|
|
1049
|
+
// of rendering a dangling divider.
|
|
1050
|
+
const operations = isEditFlow ? null : (
|
|
1019
1051
|
<>
|
|
1020
1052
|
<CapDivider type="vertical" />
|
|
1021
|
-
<
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1053
|
+
<CapTooltip title={addCardTooltipTitle}>
|
|
1054
|
+
<span className="button-disabled-tooltip-wrapper">
|
|
1055
|
+
<CapButton
|
|
1056
|
+
onClick={addCarouselCard}
|
|
1057
|
+
type="flat"
|
|
1058
|
+
className="add-carousel-content-button"
|
|
1059
|
+
disabled={
|
|
1060
|
+
isEditFlow ||
|
|
1061
|
+
!isFullMode ||
|
|
1062
|
+
isMaxCarouselCardsReached ||
|
|
1063
|
+
checkDisableAddCarouselButton()
|
|
1064
|
+
}
|
|
1065
|
+
>
|
|
1066
|
+
<CapIcon type="plus" />
|
|
1067
|
+
</CapButton>
|
|
1068
|
+
</span>
|
|
1069
|
+
</CapTooltip>
|
|
1034
1070
|
</>
|
|
1035
1071
|
);
|
|
1036
1072
|
|
|
1037
1073
|
return (
|
|
1038
|
-
<CapRow className=
|
|
1074
|
+
<CapRow className={`rcs-carousel-section ${isEditFlow ? 'rcs-carousel-section--readonly-above' : ''}`}>
|
|
1039
1075
|
{renderCarouselDimensionSelection()}
|
|
1040
1076
|
<CapRow className="rcs-carousel-tab">
|
|
1041
1077
|
<CapTab
|
|
@@ -1617,11 +1653,19 @@ export const Rcs = (props) => {
|
|
|
1617
1653
|
|
|
1618
1654
|
setTemplateType(contentType.carousel);
|
|
1619
1655
|
setTemplateMediaType(RCS_MEDIA_TYPES.NONE);
|
|
1620
|
-
|
|
1656
|
+
// Library/campaign payloads can store cardSettings/cardContent at the flat top-level
|
|
1657
|
+
// `rcsContent` instead of nested under versions.base.content.RCS (same fallback already
|
|
1658
|
+
// used for the rich_card media lookup below, line ~1793). Without it, cardWidth/height
|
|
1659
|
+
// silently fall back to SMALL/MEDIUM, mismatching the dimensions the thumbnail was
|
|
1660
|
+
// actually uploaded at and causing object-fit:cover to crop the preview image.
|
|
1661
|
+
const cardSettings = rcsContent?.cardSettings
|
|
1662
|
+
|| get(details, 'rcsContent.cardSettings', {});
|
|
1621
1663
|
const cardWidth = cardSettings?.cardWidth || SMALL;
|
|
1622
1664
|
setSelectedCarouselWidth(cardWidth);
|
|
1623
1665
|
|
|
1624
|
-
const cards = Array.isArray(rcsContent?.cardContent)
|
|
1666
|
+
const cards = Array.isArray(rcsContent?.cardContent)
|
|
1667
|
+
? rcsContent.cardContent
|
|
1668
|
+
: get(details, 'rcsContent.cardContent', []);
|
|
1625
1669
|
const firstHeight = cards?.[0]?.media?.height || MEDIUM;
|
|
1626
1670
|
setSelectedCarouselHeight(firstHeight);
|
|
1627
1671
|
setSelectedCarousel(`${firstHeight}_${cardWidth}`);
|
|
@@ -2502,10 +2546,12 @@ const onTitleAddVar = () => {
|
|
|
2502
2546
|
</CapRow>
|
|
2503
2547
|
}
|
|
2504
2548
|
description={
|
|
2505
|
-
|
|
2549
|
+
!isEditFlow && (
|
|
2550
|
+
<CapLabel type="label3">{formatMessage(messages.btnDesc)}</CapLabel>
|
|
2551
|
+
)
|
|
2506
2552
|
}
|
|
2507
2553
|
/>
|
|
2508
|
-
|
|
2554
|
+
|
|
2509
2555
|
<CapActionButton
|
|
2510
2556
|
buttonType={buttonType}
|
|
2511
2557
|
updateButtonChange={updateButtonChange}
|
|
@@ -4101,17 +4147,29 @@ const onTitleAddVar = () => {
|
|
|
4101
4147
|
/>
|
|
4102
4148
|
)
|
|
4103
4149
|
)}
|
|
4104
|
-
{
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4150
|
+
{isEditFlow ? (
|
|
4151
|
+
<div className="rcs-creative-name-readonly">
|
|
4152
|
+
<CapHeading type="h4">
|
|
4153
|
+
{formatMessage(messages.templateTypeLabel)}
|
|
4154
|
+
</CapHeading>
|
|
4155
|
+
<CapHeading type="h5" className="rcs-creative-name-value">
|
|
4156
|
+
{TEMPLATE_TYPE_OPTIONS.find((option) => option.value === templateType)?.label || '-'}
|
|
4157
|
+
</CapHeading>
|
|
4158
|
+
</div>
|
|
4159
|
+
) : (
|
|
4160
|
+
<>
|
|
4161
|
+
{renderLabel('templateTypeLabel')}
|
|
4162
|
+
<ConfigProvider theme={{ components: { Radio: { radioSize: 20, dotSize: 8 } } }}>
|
|
4163
|
+
<CapRadioGroup
|
|
4164
|
+
id="select-rcs-template-type"
|
|
4165
|
+
options={TEMPLATE_TYPE_OPTIONS}
|
|
4166
|
+
onChange={onTemplateTypeChange}
|
|
4167
|
+
value={templateType}
|
|
4168
|
+
disabled={!isFullMode}
|
|
4169
|
+
/>
|
|
4170
|
+
</ConfigProvider>
|
|
4171
|
+
</>
|
|
4172
|
+
)}
|
|
4115
4173
|
|
|
4116
4174
|
{templateType === contentType.carousel ? (
|
|
4117
4175
|
renderCarouselSection()
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
.rcs-form-section-heading {
|
|
99
99
|
display: flex;
|
|
100
100
|
margin-top: $CAP_SPACE_20;
|
|
101
|
+
margin-bottom: $CAP_SPACE_08;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
.rcs-image-upload--top-spacing {
|
|
@@ -219,6 +220,7 @@
|
|
|
219
220
|
}
|
|
220
221
|
.rcs-image-dimensions-label{
|
|
221
222
|
margin-top: 1.25rem;
|
|
223
|
+
margin-bottom: $CAP_SPACE_08;
|
|
222
224
|
}
|
|
223
225
|
.rcs-template-title-input {
|
|
224
226
|
.rcs-edit-disabled {
|
|
@@ -229,12 +231,14 @@
|
|
|
229
231
|
}
|
|
230
232
|
.rcs-template-title-label {
|
|
231
233
|
margin-top: 1.25rem;
|
|
234
|
+
margin-bottom: $CAP_SPACE_08;
|
|
232
235
|
}
|
|
233
236
|
#rcs-template-message-label .ant-btn.cap-button-v2 {
|
|
234
237
|
height: 32px;
|
|
235
238
|
}
|
|
236
239
|
#rcs-template-message-label {
|
|
237
240
|
margin-top: 1.25rem;
|
|
241
|
+
margin-bottom: $CAP_SPACE_08;
|
|
238
242
|
}
|
|
239
243
|
.rcs-container-image {
|
|
240
244
|
.image-container {
|
|
@@ -256,6 +260,17 @@
|
|
|
256
260
|
margin-top: 1.25rem;
|
|
257
261
|
}
|
|
258
262
|
|
|
263
|
+
// Edit mode: the readonly Template Type block right above (.rcs-creative-name-readonly)
|
|
264
|
+
// already has its own margin-bottom — stacking these two top-margins on top of that
|
|
265
|
+
// (flex prevents them from collapsing into it) left an oversized gap before Card height.
|
|
266
|
+
.rcs-carousel-section--readonly-above {
|
|
267
|
+
margin-top: 0;
|
|
268
|
+
|
|
269
|
+
.rcs-carousel-dimension-section {
|
|
270
|
+
margin-top: 0;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
259
274
|
.rcs-carousel-selected-dimension {
|
|
260
275
|
display: block;
|
|
261
276
|
margin-top: 8px;
|
|
@@ -264,7 +279,7 @@
|
|
|
264
279
|
|
|
265
280
|
.rcs-carousel-dimension-label {
|
|
266
281
|
display: inline-block;
|
|
267
|
-
margin-bottom:
|
|
282
|
+
margin-bottom: $CAP_SPACE_08;
|
|
268
283
|
}
|
|
269
284
|
|
|
270
285
|
#rcs-carousel-height-select,
|
|
@@ -274,6 +289,112 @@
|
|
|
274
289
|
|
|
275
290
|
.rcs-carousel-tab {
|
|
276
291
|
margin-top: 0.75rem;
|
|
292
|
+
|
|
293
|
+
// Tab list (.ant-tabs-nav-wrap) defaults to flex:auto and stretches to fill the row,
|
|
294
|
+
// pushing tabBarExtraContent (the "+" add-card button) to the far right edge. Size it
|
|
295
|
+
// to its own content instead so "+" sits right next to the last tab (Figma reference).
|
|
296
|
+
.ant-tabs-nav-wrap {
|
|
297
|
+
flex: none;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// .ant-tabs-nav already centers its direct children (antd default), but antd
|
|
301
|
+
// also gives .ant-tabs-nav-wrap AND .ant-tabs-nav-operations (an always-present,
|
|
302
|
+
// just visually-hidden, third sibling for the overflow "more" dropdown)
|
|
303
|
+
// `align-self: stretch` — forcing them to the FULL bar height, while
|
|
304
|
+
// .ant-tabs-extra-content has no such override and centers at its own natural
|
|
305
|
+
// (shorter) height. So a divider centered inside the stretched tab list and a
|
|
306
|
+
// divider centered inside the un-stretched extra-content land at different Y
|
|
307
|
+
// positions even though each is individually "centered" — in its own box.
|
|
308
|
+
// Cancel the stretch so every direct child centers the same way.
|
|
309
|
+
.ant-tabs-nav {
|
|
310
|
+
align-items: center;
|
|
311
|
+
|
|
312
|
+
> .ant-tabs-nav-wrap,
|
|
313
|
+
> .ant-tabs-nav-operations {
|
|
314
|
+
align-self: auto;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// antd ALWAYS renders `.ant-tabs-nav-operations` as a flex sibling between the
|
|
319
|
+
// tab list and the right extra-content (it holds the overflow "more" dropdown).
|
|
320
|
+
// With no overflow it's only `visibility:hidden`, so it's invisible but STILL
|
|
321
|
+
// occupies a flex slot with real width — that phantom slot is the extra gap
|
|
322
|
+
// showing up before the "|" and "+". Collapse it to zero width when hidden so
|
|
323
|
+
// the divider sits the same distance from "2" as the 1|2 divider does from "1".
|
|
324
|
+
.ant-tabs-nav-operations.ant-tabs-nav-operations-hidden {
|
|
325
|
+
width: 0;
|
|
326
|
+
padding: 0;
|
|
327
|
+
margin: 0;
|
|
328
|
+
border: none;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// .ant-tabs-extra-content itself is only a flex ITEM (antd sets `flex: none`
|
|
332
|
+
// on it), not a flex CONTAINER — its own children (the CapDivider and the
|
|
333
|
+
// "+" button's tooltip-wrapper span) fall back to inline layout, where
|
|
334
|
+
// CapDivider's antd default `vertical-align: middle` aligns it to the
|
|
335
|
+
// surrounding line box rather than to the button, which is what was making
|
|
336
|
+
// the "|" and "+" drift out of alignment with each other. Make it an
|
|
337
|
+
// explicit flex row so both children center against each other directly.
|
|
338
|
+
.ant-tabs-extra-content {
|
|
339
|
+
display: flex;
|
|
340
|
+
align-items: center;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Vertical divider between the tabs and "+": antd default (0.9em) reads too short.
|
|
344
|
+
// Also pin its own margin explicitly (antd's default didn't match the gap
|
|
345
|
+
// used for the divider between tab numbers below), which was making this
|
|
346
|
+
// divider float away from "2" instead of sitting the same distance from it
|
|
347
|
+
// as the 1|2 divider sits from "1".
|
|
348
|
+
// 12px each side = the same visual gap the 1|2 divider has (that one uses a
|
|
349
|
+
// 24px margin-left with the divider pseudo offset to its center, i.e. ~12px
|
|
350
|
+
// of clear space on each side). Keep these equal so all three gaps match.
|
|
351
|
+
.ant-tabs-extra-content .ant-divider-vertical {
|
|
352
|
+
height: $CAP_SPACE_24;
|
|
353
|
+
margin: 0 $CAP_SPACE_12;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Same divider treatment between each numbered tab (1 | 2 | ...), not just
|
|
357
|
+
// before the "+" button (Figma reference). antd's own `.ant-tabs-tab` rule
|
|
358
|
+
// already applies `margin: 0 0 0 var(--ant-tabs-horizontal-item-gutter)`
|
|
359
|
+
// (~32px) to every tab — our earlier `margin-right` was ADDING to that
|
|
360
|
+
// instead of replacing it, stacking both gaps into one huge gutter before
|
|
361
|
+
// "2". Zero out antd's own margin first so this is the only gap in play.
|
|
362
|
+
.ant-tabs-tab {
|
|
363
|
+
margin: 0 !important;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// `:not(:last-of-type)` matched more than intended: antd renders
|
|
367
|
+
// `.ant-tabs-ink-bar` as another <div> sibling AFTER the last tab inside the
|
|
368
|
+
// same nav list, so that ink-bar div — not tab "2" — was `:last-of-type`,
|
|
369
|
+
// leaving tab "2" wrongly matched and given its own extra divider on top of
|
|
370
|
+
// the real one before "+". Target adjacency to a PRECEDING tab instead
|
|
371
|
+
// (`.ant-tabs-tab + .ant-tabs-tab`), which only ever matches actual tabs
|
|
372
|
+
// regardless of what non-tab siblings antd adds elsewhere in the list.
|
|
373
|
+
.ant-tabs-tab + .ant-tabs-tab {
|
|
374
|
+
position: relative;
|
|
375
|
+
margin-left: $CAP_SPACE_24 !important;
|
|
376
|
+
|
|
377
|
+
&::before {
|
|
378
|
+
content: '';
|
|
379
|
+
position: absolute;
|
|
380
|
+
top: 50%;
|
|
381
|
+
left: -$CAP_SPACE_12;
|
|
382
|
+
transform: translateY(-50%);
|
|
383
|
+
width: 1px;
|
|
384
|
+
height: $CAP_SPACE_24;
|
|
385
|
+
background-color: $CAP_G07;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// The "+" wrapper reuses .button-disabled-tooltip-wrapper from CapActionButton
|
|
390
|
+
// (display: inline-block; margin-top: 1.25rem) — that margin was meant for a
|
|
391
|
+
// different context and pushes the "+" button below the tab row/divider baseline
|
|
392
|
+
// here. Re-align it inline with the tabs and vertical divider.
|
|
393
|
+
.button-disabled-tooltip-wrapper {
|
|
394
|
+
display: inline-flex;
|
|
395
|
+
align-items: center;
|
|
396
|
+
margin-top: 0;
|
|
397
|
+
}
|
|
277
398
|
}
|
|
278
399
|
|
|
279
400
|
.rcs-carousel-card {
|
|
@@ -330,6 +451,13 @@
|
|
|
330
451
|
|
|
331
452
|
.rcs-carousel-card-row {
|
|
332
453
|
margin-bottom: $CAP_SPACE_12;
|
|
454
|
+
|
|
455
|
+
// Card title / Card body text headers sit directly above their input —
|
|
456
|
+
// CapHeader itself has no bottom margin, so without this the input hugged
|
|
457
|
+
// the header text with no gap.
|
|
458
|
+
.cap-header-v2 {
|
|
459
|
+
margin-bottom: $CAP_SPACE_08;
|
|
460
|
+
}
|
|
333
461
|
}
|
|
334
462
|
|
|
335
463
|
.rcs-carousel-media-selection {
|
|
@@ -338,9 +466,28 @@
|
|
|
338
466
|
align-items: center;
|
|
339
467
|
}
|
|
340
468
|
|
|
469
|
+
.rcs-carousel-media-selection-heading {
|
|
470
|
+
margin-bottom: $CAP_SPACE_08;
|
|
471
|
+
}
|
|
472
|
+
|
|
341
473
|
// Carousel upload previews: keep media preview compact (CapImageUpload uses height=400 by default)
|
|
342
474
|
.rcs-carousel-media-upload {
|
|
343
475
|
padding-top: $CAP_SPACE_20;
|
|
476
|
+
|
|
477
|
+
// Edit mode: the readonly Media type block right above (.rcs-creative-name-readonly)
|
|
478
|
+
// already has its own margin-bottom, plus .rcs-image-dimensions-label's own
|
|
479
|
+
// margin-top — stacking this padding-top on top of both left an oversized gap.
|
|
480
|
+
&.rcs-carousel-media-upload--readonly-above {
|
|
481
|
+
padding-top: 0;
|
|
482
|
+
|
|
483
|
+
// Only the first heading (Upload Video, or Image) sits right below the
|
|
484
|
+
// readonly block above — the video variant's second heading (Upload
|
|
485
|
+
// Thumbnail) still needs its own margin-top to separate it from the
|
|
486
|
+
// video upload widget above it.
|
|
487
|
+
> .rcs-image-dimensions-label:first-child {
|
|
488
|
+
margin-top: 0;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
344
491
|
.image-container {
|
|
345
492
|
background-image: none;
|
|
346
493
|
border: 0;
|
|
@@ -385,8 +532,15 @@
|
|
|
385
532
|
}
|
|
386
533
|
}
|
|
387
534
|
|
|
535
|
+
// The divider's own margin already provides the gap before "+" — this button's
|
|
536
|
+
// extra left padding was stacking on top of that margin, making the gap after
|
|
537
|
+
// the divider visibly bigger than the gap before it (between "2" and the
|
|
538
|
+
// divider). Drop the left padding so both sides of the divider match; keep a
|
|
539
|
+
// little on the right as breathing room since nothing follows "+".
|
|
388
540
|
.add-carousel-content-button {
|
|
389
|
-
padding: 0 $CAP_SPACE_08;
|
|
541
|
+
padding: 0 $CAP_SPACE_08 0 0;
|
|
542
|
+
display: inline-flex;
|
|
543
|
+
align-items: center;
|
|
390
544
|
}
|
|
391
545
|
}
|
|
392
546
|
.rcs-fallback-preview > .cap-slide-box-v2-container.size-r{
|
|
@@ -206,6 +206,14 @@ export default defineMessages({
|
|
|
206
206
|
id: `${prefix}.rcsCarouselMinCardDeleteTooltip`,
|
|
207
207
|
defaultMessage: 'At least 1 card needs to be added in the carousel template',
|
|
208
208
|
},
|
|
209
|
+
rcsCarouselAddCardDisabledTooltip: {
|
|
210
|
+
id: `${prefix}.rcsCarouselAddCardDisabledTooltip`,
|
|
211
|
+
defaultMessage: 'Please set-up the first card before creating the next ones',
|
|
212
|
+
},
|
|
213
|
+
rcsCarouselMaxCardTooltip: {
|
|
214
|
+
id: `${prefix}.rcsCarouselMaxCardTooltip`,
|
|
215
|
+
defaultMessage: 'RCS carousel cannot contain more than {max} content cards.',
|
|
216
|
+
},
|
|
209
217
|
templateNamePlaceholder: {
|
|
210
218
|
id: `${prefix}.templateNamePlaceholder`,
|
|
211
219
|
defaultMessage: 'Enter template name',
|
|
@@ -244,15 +252,15 @@ export default defineMessages({
|
|
|
244
252
|
},
|
|
245
253
|
text_message: {
|
|
246
254
|
id: `${prefix}.text_message`,
|
|
247
|
-
defaultMessage: '
|
|
255
|
+
defaultMessage: 'Text message',
|
|
248
256
|
},
|
|
249
257
|
richCard: {
|
|
250
258
|
id: `${prefix}.richCard`,
|
|
251
|
-
defaultMessage: '
|
|
259
|
+
defaultMessage: 'Rich card',
|
|
252
260
|
},
|
|
253
261
|
carousel: {
|
|
254
262
|
id: `${prefix}.carousel`,
|
|
255
|
-
defaultMessage: '
|
|
263
|
+
defaultMessage: 'Carousel',
|
|
256
264
|
},
|
|
257
265
|
rcsDoneBtnToolTip: {
|
|
258
266
|
id: `${prefix}.rcsDoneBtnToolTip`,
|