@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.
@@ -107,6 +107,14 @@
107
107
  box-shadow: 0 $CAP_SPACE_04 $CAP_SPACE_12 rgba(0, 0, 0, 0.15);
108
108
  overflow: hidden;
109
109
  transition: all 0.3s ease;
110
+ // iOS Safari fails to clip a `transform`ed descendant (.rcs-carousel-panel
111
+ // uses translateX(-50%) to center itself) to this ancestor's border-radius —
112
+ // its white background bleeds past the rounded edge on real devices, even
113
+ // though overflow:hidden clips it correctly everywhere else. Forcing Safari
114
+ // onto its masking render path (instead of the buggy transform+overflow-clip
115
+ // path) fixes this; no-op on every other browser.
116
+ -webkit-mask-image: -webkit-radial-gradient(white, black);
117
+ mask-image: radial-gradient(white, black);
110
118
 
111
119
  // Desktop Frame
112
120
  &.device-frame-desktop {
@@ -785,39 +793,59 @@
785
793
  }
786
794
  }
787
795
 
788
- // RCS-only overrides for SMS-style preview frame (scoped; does not affect SMS channel preview)
796
+ // RCS Carousel card styles scoped to .rcs-carousel-panel (which lives outside the
797
+ // overflow-x:hidden overlay so horizontal scroll events reach .scroll-container freely).
789
798
  .rcs-device-container {
799
+ .rcs-carousel-panel {
800
+ position: absolute;
801
+ // Centered via left/right auto-margins instead of left:50% + translateX(-50%) —
802
+ // a `transform` on this element put every rounded+overflow:hidden box nested
803
+ // inside it (this panel's own corners, the card corners, the image corners...)
804
+ // in a transformed stacking context that iOS Safari fails to clip correctly,
805
+ // letting their square corners/backgrounds bleed past the rounded edges. Plain
806
+ // auto-margin centering has no such bug.
807
+ left: 0;
808
+ right: 0;
809
+ margin-left: auto;
810
+ margin-right: auto;
811
+ width: 100%;
812
+ max-width: 26.786rem;
813
+ box-sizing: border-box;
814
+ top: 4.143rem;
815
+ height: calc(100% - 2.5rem);
816
+ display: flex;
817
+ flex-direction: column;
818
+ padding-top: 5.857rem; // nav (3.428rem) + date separator (~2.429rem)
819
+ padding-bottom: $CAP_SPACE_16;
820
+ padding-left: 0.4rem;
821
+ padding-right: 0.4rem;
822
+ background-color: $CAP_WHITE;
823
+ background-clip: content-box;
824
+ border-bottom-left-radius: 2.429rem;
825
+ border-bottom-right-radius: 2.429rem;
826
+ // background-clip only clips the background fill to these rounded corners —
827
+ // it does NOT clip child content, so message/card boxes could render past the
828
+ // rounded edge regardless of browser. This doesn't affect the horizontal touch
829
+ // scroll .scroll-container needs: that workaround was about not nesting inside
830
+ // the *other* sibling overlay (.sms-content-overlay's overflow-x:hidden), not
831
+ // about this element's own overflow.
832
+ overflow: hidden;
790
833
 
791
- // Carousel panel: sibling of .sms-content-overlay, positioned absolutely within
792
- // .sms-device-container (position:relative). Has NO overflow-x:hidden ancestor,
793
- // mirroring the WhatsApp carousel approach so horizontal scroll events reach the
794
- // inner .scroll-container directly.
795
- &.rcs-device-container-carousel {
796
- // Carousel panel: same geometry as .sms-content-overlay but NO overflow-x:hidden.
797
- // padding-top skips past the nav bar ($CAP_SPACE_48 = 3.428rem) and date separator
798
- // (~2.429rem), placing the carousel right where the original .sms-message-container
799
- // started (which had flex:1 and filled from below the date separator downward).
800
- .rcs-carousel-panel {
801
- position: absolute;
802
- left: 50%;
803
- transform: translateX(-50%);
804
- width: 100%;
805
- max-width: 26.786rem;
806
- box-sizing: border-box;
807
- top: 4.143rem;
808
- height: calc(100% - 4.5rem);
809
- display: flex;
810
- flex-direction: column;
811
- padding-top: 5.857rem; // nav (3.428rem) + date separator (~2.429rem)
812
- padding-bottom: $CAP_SPACE_16;
834
+ &.rcs-carousel-panel-android {
835
+ top: 3.1rem;
836
+ border-radius: 4rem;
837
+ }
813
838
 
814
- &.rcs-carousel-panel-android {
815
- top: 3.1rem;
816
- height: calc(100% - 3.8rem);
817
- }
839
+ &.rcs-carousel-panel-ios {
840
+ height: calc(100% - 4.2rem);
841
+ }
818
842
 
819
- &.rcs-carousel-panel-ios {
820
- height: calc(100% - 5rem);
843
+ .rcs-carousel-timestamp {
844
+ font-size: $FONT_SIZE_S;
845
+ color: #8c8c8c;
846
+ align-self: flex-end;
847
+ padding-right: $CAP_SPACE_04;
848
+ padding-top: $CAP_SPACE_04;
821
849
  }
822
850
 
823
851
  .msg-container-carousel {
@@ -825,52 +853,42 @@
825
853
  flex-direction: column;
826
854
  width: 100%;
827
855
  padding: 0 $CAP_SPACE_16;
828
- }
829
856
 
830
- .scroll-container {
831
- display: flex;
832
- flex-wrap: nowrap;
833
- gap: 0.75rem;
834
- overflow-x: auto;
835
- overflow-y: hidden;
836
- width: 100%;
837
- scrollbar-width: none;
857
+ .scroll-container {
858
+ display: flex;
859
+ flex-wrap: nowrap;
860
+ gap: 0.75rem;
861
+ overflow-x: auto;
862
+ overflow-y: hidden;
863
+ width: 100%;
864
+ scrollbar-width: none;
838
865
 
839
- &::-webkit-scrollbar {
840
- display: none;
866
+ &::-webkit-scrollbar {
867
+ display: none;
868
+ }
841
869
  }
842
870
  }
843
871
 
844
- .rcs-carousel-timestamp {
845
- font-size: $FONT_SIZE_S;
846
- color: #8c8c8c;
847
- align-self: flex-end;
848
- padding-right: $CAP_SPACE_04;
849
- padding-top: $CAP_SPACE_04;
850
- }
851
- }
852
- }
853
-
854
- .rcs-content-overlay {
855
- // no carousel-specific overlay overrides needed (carousel lives outside the overlay now)
856
- }
857
- }
858
-
859
- // RCS Carousel card styles — scoped to .rcs-carousel-panel (which lives outside the
860
- // overflow-x:hidden overlay so horizontal scroll events reach .scroll-container freely).
861
- .rcs-device-container {
862
- .rcs-carousel-panel {
872
+ // Wraps the card + its CTA bar so both scroll horizontally together as one unit,
873
+ // while remaining two visually distinct, separately-rounded elements (Figma reference —
874
+ // the CTA bar is its own floating pill below the card, not part of it).
875
+ .rcs-carousel-item {
876
+ display: flex;
877
+ flex-direction: column;
878
+ gap: $CAP_SPACE_04;
879
+ // Ensure item width is stable and does not shrink to text width
880
+ flex: 0 0 15.375rem; // ~246px; fills container leaving ~50% of next card peeking
881
+ margin-right: 0; // spacing handled by scroll-container gap
882
+ }
863
883
 
864
884
  .message-pop-carousel {
865
885
  // Match TemplatePreview carousel card look (big card + subtle shadow)
866
886
  background-color: $CAP_WHITE;
867
- border-radius: $CAP_SPACE_08;
868
- // Ensure card width is stable and does not shrink to text width
869
- width: 15.375rem; // ~246px; fills container leaving ~50% of next card peeking
870
- min-width: 15.375rem;
871
- flex: 0 0 15.375rem;
887
+ border: 1px solid $CAP_G07; // #dfe2e7 — keeps the card visible against the
888
+ // chat background when there's no photo yet to provide contrast (Figma empty state)
889
+ border-radius: $CAP_SPACE_04; // 4px (Figma RCS carousel card corner)
890
+ width: 100%;
872
891
  padding: 0;
873
- margin-right: 0; // spacing handled by scroll-container gap
874
892
  color: $CAP_G01;
875
893
  overflow: hidden;
876
894
  box-shadow: 0 0 0.625rem 0 rgba(0, 0, 0, 0.08);
@@ -890,7 +908,7 @@
890
908
  aspect-ratio: 1280 / 720; // MEDIUM_MEDIUM image fallback when dimensions not passed
891
909
  display: block;
892
910
  overflow: hidden;
893
- border-radius: 0.5rem 0.5rem 0 0; // 8px
911
+ border-radius: $CAP_SPACE_04 $CAP_SPACE_04 0 0; // 4px (Figma)
894
912
  margin-bottom: 0;
895
913
 
896
914
  // CapImage (antd Image) applies className on wrapper; ensure inner img is constrained too.
@@ -967,12 +985,12 @@
967
985
  .carousel-content {
968
986
  padding: 0.625rem 0.75rem; // 10px 12px
969
987
  width: 100%;
970
- background-color: $CAP_WHITE;
988
+ background-color: $CAP_G08; // #ebecf0 (Figma: grey info panel, not white)
971
989
  white-space: normal; // override scroll-container's nowrap so text can wrap
972
990
  display: flex;
973
991
  flex-direction: column;
974
- border-bottom-left-radius: 0.25rem; // 4px — text panel tucks above CTA gap (Figma)
975
- border-bottom-right-radius: 0.25rem;
992
+ border-bottom-left-radius: 0.25rem; // 4px — this is the card's own bottom edge;
993
+ border-bottom-right-radius: 0.25rem; // the CTA bar below is a separate element (Figma)
976
994
 
977
995
  // Title/body typography via CapLabel type (label1 / label2, etc.)
978
996
  .carousel-title {
@@ -981,6 +999,8 @@
981
999
  overflow: visible;
982
1000
  white-space: normal;
983
1001
  overflow-wrap: anywhere;
1002
+ color: $CAP_G04; // #5e6c84 (Figma)
1003
+ font-weight: $FONT_WEIGHT_BOLD;
984
1004
  }
985
1005
 
986
1006
  .carousel-message {
@@ -988,6 +1008,8 @@
988
1008
  overflow: visible;
989
1009
  white-space: normal;
990
1010
  overflow-wrap: anywhere;
1011
+ color: $FONT_COLOR_03; // #97a0af (Figma)
1012
+ font-weight: $FONT_WEIGHT_REGULAR;
991
1013
  }
992
1014
 
993
1015
  .rcs-carousel-field-placeholder {
@@ -1007,7 +1029,8 @@
1007
1029
  border-top: 1px solid $CAP_WHITE;
1008
1030
  }
1009
1031
 
1010
- // Stacked full-width CTA bars below card copy, separated by white gap (Figma RCS carousel)
1032
+ // Own floating pill(s) below the card (NOT part of .message-pop-carousel) sits in
1033
+ // .rcs-carousel-item, separated from the card by that wrapper's `gap` (Figma reference).
1011
1034
  .rcs-carousel-cta-stack.cap-row-v2 {
1012
1035
  display: flex;
1013
1036
  flex-direction: column;
@@ -1027,18 +1050,13 @@
1027
1050
  margin: 0;
1028
1051
  padding: 0.625rem 0.75rem;
1029
1052
  box-sizing: border-box;
1030
- background-color: $CAP_WHITE;
1053
+ background-color: $CAP_G08; // #ebecf0 (Figma: grey "Call Now" pill, not white)
1031
1054
  border-radius: 0.25rem;
1032
1055
  font-size: $FONT_SIZE_M;
1033
1056
  font-weight: $FONT_WEIGHT_MEDIUM;
1034
- color: $CAP_G01;
1057
+ color: $CAP_G04; // #5e6c84 (Figma)
1035
1058
  text-align: center;
1036
1059
  }
1037
-
1038
- .rcs-cta-preview-phone-icon-end {
1039
- margin-left: 0.25rem;
1040
- flex-shrink: 0;
1041
- }
1042
1060
  }
1043
1061
  }
1044
1062
 
@@ -2715,10 +2733,14 @@
2715
2733
  max-width: 100% !important;
2716
2734
  }
2717
2735
 
2718
- &.device-frame-mobile {
2719
- width: 100% !important;
2720
- max-width: 100% !important;
2721
- }
2736
+ // NOT stretched to 100% here like desktop/tablet — this frame simulates a
2737
+ // phone, so on a narrow (e.g. real iOS) viewport it should stay phone-width
2738
+ // and shrink via its own `max-width: 90%` rule, not stretch to fill the
2739
+ // container. The old `width: 100% !important` made the frame's white
2740
+ // background render far wider than the phone silhouette, visibly eating
2741
+ // into the grey backdrop around it, while the carousel content inside
2742
+ // stayed capped at its normal phone width — a width mismatch, not a
2743
+ // clipping bug.
2722
2744
  }
2723
2745
  }
2724
2746
  }
@@ -222,7 +222,7 @@ export default defineMessages({
222
222
  },
223
223
  smsFallbackTab: {
224
224
  id: `${scope}.smsFallbackTab`,
225
- defaultMessage: 'Fallback SMS',
225
+ defaultMessage: 'SMS Fallback',
226
226
  },
227
227
  previewPlaceholder: {
228
228
  id: `${scope}.previewPlaceholder`,
@@ -338,11 +338,11 @@ export default defineMessages({
338
338
  },
339
339
  rcsCarouselPreviewTitlePlaceholder: {
340
340
  id: `${scope}.rcsCarouselPreviewTitlePlaceholder`,
341
- defaultMessage: 'Card title',
341
+ defaultMessage: 'Your title goes here',
342
342
  },
343
343
  rcsCarouselPreviewBodyPlaceholder: {
344
344
  id: `${scope}.rcsCarouselPreviewBodyPlaceholder`,
345
- defaultMessage: 'Card description',
345
+ defaultMessage: 'Your text message goes here',
346
346
  },
347
347
  toMe: {
348
348
  id: `${scope}.toMe`,
@@ -413,7 +413,7 @@ describe('RcsPreviewContent', () => {
413
413
  };
414
414
  renderRcsPreview(props);
415
415
  expect(screen.getByText('OnlyTitle')).toBeTruthy();
416
- expect(screen.getByText('Card description')).toBeTruthy();
416
+ expect(screen.getByText('Your text message goes here')).toBeTruthy();
417
417
  expect(document.querySelector('.carousel-message.rcs-carousel-field-placeholder')).toBeTruthy();
418
418
  });
419
419
 
@@ -433,7 +433,7 @@ describe('RcsPreviewContent', () => {
433
433
  };
434
434
  renderRcsPreview(props);
435
435
  expect(screen.getByText('OnlyBody')).toBeTruthy();
436
- expect(screen.getByText('Card title')).toBeTruthy();
436
+ expect(screen.getByText('Your title goes here')).toBeTruthy();
437
437
  expect(document.querySelector('.carousel-title.rcs-carousel-field-placeholder')).toBeTruthy();
438
438
  });
439
439
 
@@ -452,8 +452,8 @@ describe('RcsPreviewContent', () => {
452
452
  };
453
453
  const { container } = renderRcsPreview(props);
454
454
  expect(container.querySelector('.carousel-content')).toBeTruthy();
455
- expect(screen.getByText('Card title')).toBeTruthy();
456
- expect(screen.getByText('Card description')).toBeTruthy();
455
+ expect(screen.getByText('Your title goes here')).toBeTruthy();
456
+ expect(screen.getByText('Your text message goes here')).toBeTruthy();
457
457
  expect(container.querySelectorAll('.rcs-carousel-field-placeholder').length).toBe(2);
458
458
  });
459
459
  });
@@ -13,9 +13,7 @@
13
13
 
14
14
  .shell-v2 {
15
15
  position: relative;
16
- -webkit-transform: translate(-50%);
17
- transform: translate(-50%);
18
- left: 50%;
16
+ margin: 0 auto;
19
17
  padding: 0 10px;
20
18
  width: 450px;
21
19
 
@@ -572,6 +570,9 @@
572
570
  margin-top: 0;
573
571
  padding: 4px 8px;
574
572
  }
573
+ &.rcs-desc {
574
+ margin-top: $CAP_SPACE_08;
575
+ }
575
576
  &.rcs-button-text{
576
577
  color: $FONT_COLOR_05;
577
578
  .rcs-icon{
@@ -876,7 +877,7 @@
876
877
  left: 0;
877
878
  flex-shrink: 0;
878
879
  padding: $CAP_SPACE_04 0 $CAP_SPACE_08;
879
- border-radius: 0.428rem;
880
+ border-radius: $CAP_SPACE_04; // 4px (Figma RCS carousel card corner)
880
881
 
881
882
  .carousel-title {
882
883
  font-weight: 700 !important;
@@ -521,7 +521,10 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
521
521
  } else if (suggestion.type === RCS_BUTTON_TYPES.CTA) {
522
522
  renderArray.push(
523
523
  <CapLabel key={`rcs-suggestion-${suggestionKey}`} type="label21" className="rcs-cta-preview">
524
- <CapIcon type="launch" size="xs" />
524
+ {/* "launch" icon's hardcoded SVG <defs>/<mask> ids collide when 2+
525
+ CTA buttons render together, showing as a solid square — "open-in-new"
526
+ is a single flat path with no ids, so it can't collide. */}
527
+ <CapIcon type="open-in-new" size="xs" />
525
528
  {suggestion.text}
526
529
  </CapLabel>,
527
530
  );
@@ -455,6 +455,7 @@ export function SlideBoxContent(props) {
455
455
  getFormData,
456
456
  eventContextTags,
457
457
  waitEventContextTags,
458
+ handleClose,
458
459
  };
459
460
 
460
461
  return (