@capillarytech/creatives-library 8.0.131 → 8.0.133-alpha.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.131",
4
+ "version": "8.0.133-alpha.0",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -137,6 +137,7 @@ function buildPlatformContent(content, imageSrc, mpushVideoSrcAndPreview, platfo
137
137
  linkType,
138
138
  deepLinkValue,
139
139
  externalLinkValue,
140
+ deepLinkKeysValue = [],
140
141
  } = content || {};
141
142
 
142
143
  const platformContent = {
@@ -148,9 +149,21 @@ function buildPlatformContent(content, imageSrc, mpushVideoSrcAndPreview, platfo
148
149
 
149
150
  // Handle CTA
150
151
  if (actionOnClick) {
152
+ let finalDeepLinkValue = deepLinkValue;
153
+
154
+ if (linkType === DEEP_LINK && deepLinkKeysValue && deepLinkKeysValue.length > 0) {
155
+ // Check if the URL already contains the keys
156
+ const urlHasKeys = deepLinkKeysValue.some((key) => deepLinkValue && deepLinkValue.includes(`${key}={{${key}}}`));
157
+
158
+ // Only append keys if they're not already in the URL
159
+ if (!urlHasKeys) {
160
+ finalDeepLinkValue = appendDeepLinkKeysToUrl(deepLinkValue, deepLinkKeysValue);
161
+ }
162
+ }
163
+
151
164
  platformContent.cta = {
152
165
  type: linkType === DEEP_LINK ? DEEP_LINK : EXTERNAL_URL,
153
- actionLink: linkType === DEEP_LINK ? deepLinkValue : externalLinkValue,
166
+ actionLink: linkType === DEEP_LINK ? finalDeepLinkValue : externalLinkValue,
154
167
  };
155
168
  }
156
169
 
@@ -273,31 +286,11 @@ function buildCustomFields(content) {
273
286
  if (Array.isArray(custom)) {
274
287
  customFields = [...custom];
275
288
  } else if (custom && typeof custom === 'object') {
276
- // If it's an object, map to array
277
- customFields = Object.entries(custom).map(([key, value]) => ({ key, value }));
278
- }
279
- const { deepLinkKeysValue, deepLinkValue, linkType } = custom || {};
280
- // Add deepLinkKeys to custom fields if it exists
281
- if (deepLinkKeysValue && linkType === DEEP_LINK) {
282
- if (Array.isArray(deepLinkKeysValue)) {
283
- // Handle array of deep link keys
284
- deepLinkKeysValue.forEach((key) => {
285
- if (key) {
286
- customFields.push({
287
- key,
288
- value: deepLinkValue,
289
- });
290
- }
291
- });
292
- } else {
293
- // Handle single deep link key
294
- customFields.push({
295
- key: deepLinkKeysValue,
296
- value: deepLinkValue,
297
- });
298
- }
289
+ // If it's an object, map to array, excluding deepLinkKeys
290
+ customFields = Object.entries(custom)
291
+ .filter(([key]) => key !== 'deepLinkKeysValue' && key !== 'deepLinkValue' && key !== 'linkType')
292
+ .map(([key, value]) => ({ key, value }));
299
293
  }
300
-
301
294
  return customFields;
302
295
  }
303
296
 
@@ -307,7 +300,7 @@ function buildCustomFields(content) {
307
300
  * @param {Array} keys - Deep link keys
308
301
  * @returns {string} URL with appended keys
309
302
  */
310
- function appendDeepLinkKeysToUrl(url, keys) {
303
+ export function appendDeepLinkKeysToUrl(url, keys) {
311
304
  if (!url || !keys || !Array.isArray(keys) || keys?.length === 0) return url;
312
305
 
313
306
  const separator = url.includes('?') ? '&' : '?';
@@ -242,17 +242,6 @@ export const CapMpushCTA = (props) => {
242
242
  {urlType === DEEP_LINK ? selectedDeepLink?.label : ''}
243
243
  </CapColumn>
244
244
  <CapColumn>
245
- {urlType === DEEP_LINK && deepLinkKeysFromSelectionArray?.length > 0 && (ctaData[index]?.deepLinkKeys || selectedDeepLink?.keys) ? (
246
- <CapLabel type="label2" className="inapp-saved-cta-deep-link-keys">
247
- {(() => {
248
- const keys = selectedDeepLink?.keys || ctaData[index]?.deepLinkKeys;
249
- if (Array.isArray(keys)) {
250
- return keys.join(', ');
251
- }
252
- return keys;
253
- })()}
254
- </CapLabel>
255
- ) : ''}
256
245
  </CapColumn>
257
246
  {(
258
247
  <CapRow className="cta-action-grp">
@@ -653,7 +653,7 @@
653
653
  margin-top: 0.5rem; // 8px
654
654
 
655
655
  a {
656
- color: $CAP_SECONDARY_base; // #2466ea
656
+ color: $FONT_COLOR_05; // #2466ea
657
657
  font-size: $FONT_SIZE_S; // 12px
658
658
  text-decoration: underline;
659
659
  }
@@ -1096,7 +1096,7 @@
1096
1096
  padding: $CAP_SPACE_12;
1097
1097
  .app-header {
1098
1098
  color: $CAP_G04; // #5D5D5D is closest to CAP_G04
1099
- font-weight: $FONT_WEIGHT_SEMIBOLD; // 600 maps to SEMIBOLD
1099
+ font-weight: 600;
1100
1100
  padding: 0.285rem 0.571rem 0.285rem 0.571rem;
1101
1101
  display: flex;
1102
1102
  align-items: center;
@@ -1171,7 +1171,7 @@
1171
1171
  gap: $CAP_SPACE_08;
1172
1172
  .action {
1173
1173
  font-size: $FONT_SIZE_S;
1174
- font-weight: $FONT_WEIGHT_SEMIBOLD; // 600 maps to SEMIBOLD
1174
+ font-weight: 600;
1175
1175
  color: $CAP_COLOR_03; // #1970DA maps to CAP_COLOR_03 (primary brand color)
1176
1176
  height: 1.25rem;
1177
1177
  }
@@ -549,7 +549,7 @@ const MediaUploaders = ({
549
549
  <FormattedMessage {...messages.actionDescription} />
550
550
  </CapLabel>
551
551
  </CapRow>
552
- {button.actionOnClick && (
552
+ {button?.actionOnClick && (
553
553
  <CapRow style={{ display: "flex", justifyContent: "space-around" }}>
554
554
  <CapColumn span={6}>
555
555
  <CapHeading type="h4" className="buttons-heading">
@@ -563,7 +563,7 @@ const MediaUploaders = ({
563
563
  selectPlaceholder={formatMessage(messages.selectDeepLink)}
564
564
  />
565
565
  </CapColumn>
566
- {button.linkType === DEEP_LINK && (
566
+ {button?.linkType === DEEP_LINK && (
567
567
  <CapColumn span={14}>
568
568
  <CapHeading type="h4" className="buttons-heading">
569
569
  {formatMessage(messages.deepLink)}
@@ -583,7 +583,7 @@ const MediaUploaders = ({
583
583
  )}
584
584
  </CapColumn>
585
585
  )}
586
- {button.linkType === EXTERNAL_LINK && (
586
+ {button?.linkType === EXTERNAL_LINK && (
587
587
  <CapColumn span={14}>
588
588
  <CapHeading type="h4" className="buttons-heading">
589
589
  {formatMessage(messages.externalLink)}
@@ -592,7 +592,7 @@ const MediaUploaders = ({
592
592
  id={`mobile-push-external-link-input-${activeTab}-${cardIndex}`}
593
593
  onChange={(e) => handleCarouselExternalLinkChange(cardIndex, e.target.value)}
594
594
  placeholder={formatMessage(messages.enterExternalLink)}
595
- value={button.externalLinkValue}
595
+ value={button?.externalLinkValue}
596
596
  size="default"
597
597
  isRequired
598
598
  />
@@ -605,8 +605,8 @@ const MediaUploaders = ({
605
605
  )}
606
606
  </CapRow>
607
607
  )}
608
- {button.linkType === DEEP_LINK && button.deepLinkValue && (() => {
609
- const selectedDeepLink = deepLink?.find((link) => link?.value === button.deepLinkValue);
608
+ {button?.linkType === DEEP_LINK && button?.deepLinkValue && button?.actionOnClick && (() => {
609
+ const selectedDeepLink = deepLink?.find((link) => link?.value === button?.deepLinkValue);
610
610
  const deepLinkKeysFromSelection = selectedDeepLink?.keys;
611
611
  let deepLinkKeysFromSelectionArray = [];
612
612
  if (Array.isArray(deepLinkKeysFromSelection)) {
@@ -617,7 +617,7 @@ const MediaUploaders = ({
617
617
  return deepLinkKeysFromSelectionArray?.length > 0;
618
618
  })() && (
619
619
  <CapRow style={{ marginTop: "10px", left: "6%", width: '115%'}}>
620
- <CapColumn span={7}>
620
+ <CapColumn span={14}>
621
621
  <CapHeading type="h4" className="deep-link-keys-heading">
622
622
  {formatMessage(messages.deepLinkKeys)}
623
623
  </CapHeading>
@@ -58,8 +58,6 @@ const PlatformContentFields = ({
58
58
  externalLinkValue,
59
59
  } = linkProps;
60
60
 
61
- // Debug logging removed - issue identified and fixed
62
-
63
61
  // Get the selected deep link object to extract keys
64
62
  const selectedDeepLink = deepLink?.find((link) => link?.value === deepLinkValue);
65
63
  const deepLinkKeysFromSelection = selectedDeepLink?.keys;
@@ -289,7 +287,7 @@ const PlatformContentFields = ({
289
287
  )}
290
288
  {content?.actionOnClick && content?.linkType === DEEP_LINK && deepLinkValue && deepLinkKeysFromSelectionArray?.length > 0 && (
291
289
  <CapRow style={{ marginTop: "10px", left: "6%", width: '115%'}}>
292
- <CapColumn span={7}>
290
+ <CapColumn span={14}>
293
291
  <CapHeading type="h4" className="deep-link-keys-heading">
294
292
  {formatMessage(messages.deepLinkKeys)}
295
293
  </CapHeading>
@@ -629,13 +629,14 @@ const MobilePushNew = ({
629
629
  const androidButtons = androidCtas || [];
630
630
  if (androidButtons.length > 0) {
631
631
  const ctaDataFromAndroid = androidButtons.map((button, index) => {
632
- let deepLinkKeys = [];
633
- if (button?.type === DEEP_LINK && button?.actionLink) {
632
+ // Use deep link keys from the button if available, otherwise try to extract from URL
633
+ let deepLinkKeys = button?.deepLinkKeys || [];
634
+ if (!deepLinkKeys.length && button?.type === DEEP_LINK && button?.actionLink) {
634
635
  try {
635
636
  const url = new URL(button?.actionLink);
636
637
  const extractedKeys = [];
637
638
  url.searchParams.forEach((value, key) => {
638
- if (value === key) {
639
+ if (value === key) { // Only extract keys where value equals key
639
640
  extractedKeys.push(key);
640
641
  }
641
642
  });
@@ -649,7 +650,15 @@ const MobilePushNew = ({
649
650
 
650
651
  return {
651
652
  text: button?.actionText || "",
652
- url: button?.actionLink || "",
653
+ url: (() => {
654
+ const deepLinkValue = button?.actionLink || "";
655
+ if (deepLink?.length > 0 && deepLinkValue && button?.type === DEEP_LINK) {
656
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
657
+ const match = deepLink.find((link) => link.value === baseDeepLinkValue);
658
+ if (match) return match.value;
659
+ }
660
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
661
+ })(),
653
662
  urlType: button?.type || DEEP_LINK,
654
663
  deepLinkKeys,
655
664
  ctaType: index === 0 ? PRIMARY : SECONDARY,
@@ -688,7 +697,7 @@ const MobilePushNew = ({
688
697
  const deepLinkValue = androidMainCta?.type === DEEP_LINK ? androidMainCta?.actionLink : (androidContentType?.cta?.type === DEEP_LINK ? androidContentType?.cta?.actionLink : "");
689
698
 
690
699
  // If we have deep links available, find the matching one
691
- if (deepLink?.length > 0) {
700
+ if (deepLink?.length > 0 && deepLinkValue) {
692
701
  // Try to find exact match first
693
702
  const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
694
703
  if (exactMatch) {
@@ -703,7 +712,8 @@ const MobilePushNew = ({
703
712
  }
704
713
  }
705
714
 
706
- return deepLinkValue;
715
+ // If no match found, return the base URL without query parameters
716
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
707
717
  })(),
708
718
  deepLinkKeysValue: (() => {
709
719
  // Extract deep link keys from the URL
@@ -815,13 +825,14 @@ const MobilePushNew = ({
815
825
  const iosButtons = iosCtas || [];
816
826
  if (iosButtons.length > 0) {
817
827
  const ctaDataFromIos = iosButtons.map((button, index) => {
818
- let deepLinkKeys = [];
819
- if (button?.type === DEEP_LINK && button?.actionLink) {
828
+ // Use deep link keys from the button if available, otherwise try to extract from URL
829
+ let deepLinkKeys = button?.deepLinkKeys || [];
830
+ if (!deepLinkKeys?.length && button?.type === DEEP_LINK && button?.actionLink) {
820
831
  try {
821
832
  const url = new URL(button?.actionLink);
822
833
  const extractedKeys = [];
823
834
  url.searchParams.forEach((value, key) => {
824
- if (value === key) {
835
+ if (value === key) { // Only extract keys where value equals key
825
836
  extractedKeys.push(key);
826
837
  }
827
838
  });
@@ -835,7 +846,15 @@ const MobilePushNew = ({
835
846
 
836
847
  return {
837
848
  text: button?.actionText || "",
838
- url: button?.actionLink || "",
849
+ url: (() => {
850
+ const deepLinkValue = button?.actionLink || "";
851
+ if (deepLink?.length > 0 && deepLinkValue && button?.type === DEEP_LINK) {
852
+ const baseDeepLinkValue = deepLinkValue.split('?')[0];
853
+ const match = deepLink.find((link) => link.value === baseDeepLinkValue);
854
+ if (match) return match.value;
855
+ }
856
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
857
+ })(),
839
858
  urlType: button?.type || DEEP_LINK,
840
859
  deepLinkKeys,
841
860
  ctaType: index === 0 ? PRIMARY : SECONDARY,
@@ -872,9 +891,9 @@ const MobilePushNew = ({
872
891
  deepLinkValue: (() => {
873
892
  // Get the deep link value
874
893
  const deepLinkValue = iosMainCta?.type === DEEP_LINK ? iosMainCta?.actionLink : (iosContentType?.cta?.type === DEEP_LINK ? iosContentType?.cta?.actionLink : "");
875
-
894
+
876
895
  // If we have deep links available, find the matching one
877
- if (deepLink?.length > 0) {
896
+ if (deepLink?.length > 0 && deepLinkValue) {
878
897
  // Try to find exact match first
879
898
  const exactMatch = deepLink.find((link) => link.value === deepLinkValue);
880
899
  if (exactMatch) {
@@ -889,7 +908,8 @@ const MobilePushNew = ({
889
908
  }
890
909
  }
891
910
 
892
- return deepLinkValue;
911
+ // If no match found, return the base URL without query parameters
912
+ return deepLinkValue ? deepLinkValue.split('?')[0] : "";
893
913
  })(),
894
914
  deepLinkKeysValue: (() => {
895
915
  // Extract deep link keys from the URL
@@ -1429,9 +1449,54 @@ const MobilePushNew = ({
1429
1449
  setAndroidDeepLinkError(androidDeepLinkUrlError || "");
1430
1450
  setIosDeepLinkError(iosDeepLinkUrlError || "");
1431
1451
 
1432
- // Validate deep link keys
1433
- const androidDeepLinkKeysErrorMsg = androidContent?.linkType === DEEP_LINK && androidContent?.deepLinkValue && (!Array.isArray(androidContent?.deepLinkKeysValue) || androidContent?.deepLinkKeysValue?.length === 0) ? formatMessage(messages.deepLinkKeysRequired) : "";
1434
- const iosDeepLinkKeysErrorMsg = iosContent?.linkType === DEEP_LINK && iosContent?.deepLinkValue && (!Array.isArray(iosContent?.deepLinkKeysValue) || iosContent?.deepLinkKeysValue?.length === 0) ? formatMessage(messages.deepLinkKeysRequired) : "";
1452
+ // Validate deep link keys - only require keys if the selected deep link has keys defined
1453
+ const androidDeepLinkKeysErrorMsg = (() => {
1454
+ if (androidContent?.linkType === DEEP_LINK && androidContent?.deepLinkValue) {
1455
+ // Use the same matching logic as deep link value extraction
1456
+ let selectedDeepLink = null;
1457
+
1458
+ // Try to find exact match first
1459
+ selectedDeepLink = deepLink?.find((link) => link.value === androidContent?.deepLinkValue);
1460
+
1461
+ // If no exact match, try to find match without query params
1462
+ if (!selectedDeepLink && androidContent?.deepLinkValue) {
1463
+ const baseDeepLinkValue = androidContent?.deepLinkValue.split('?')[0];
1464
+ selectedDeepLink = deepLink?.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1465
+ }
1466
+
1467
+ const hasKeysDefined = selectedDeepLink?.keys && selectedDeepLink.keys.length > 0;
1468
+
1469
+ // Only require keys if the selected deep link has keys defined
1470
+ if (hasKeysDefined && (!Array.isArray(androidContent?.deepLinkKeysValue) || androidContent?.deepLinkKeysValue?.length === 0)) {
1471
+ return formatMessage(messages.deepLinkKeysRequired);
1472
+ }
1473
+ }
1474
+ return "";
1475
+ })();
1476
+
1477
+ const iosDeepLinkKeysErrorMsg = (() => {
1478
+ if (iosContent?.linkType === DEEP_LINK && iosContent?.deepLinkValue) {
1479
+ // Use the same matching logic as deep link value extraction
1480
+ let selectedDeepLink = null;
1481
+
1482
+ // Try to find exact match first
1483
+ selectedDeepLink = deepLink?.find((link) => link.value === iosContent?.deepLinkValue);
1484
+
1485
+ // If no exact match, try to find match without query params
1486
+ if (!selectedDeepLink && iosContent?.deepLinkValue) {
1487
+ const baseDeepLinkValue = iosContent?.deepLinkValue.split('?')[0];
1488
+ selectedDeepLink = deepLink?.find((link) => link.value === baseDeepLinkValue || link.value.split('?')[0] === baseDeepLinkValue);
1489
+ }
1490
+
1491
+ const hasKeysDefined = selectedDeepLink?.keys && selectedDeepLink.keys.length > 0;
1492
+
1493
+ // Only require keys if the selected deep link has keys defined
1494
+ if (hasKeysDefined && (!Array.isArray(iosContent?.deepLinkKeysValue) || iosContent?.deepLinkKeysValue?.length === 0)) {
1495
+ return formatMessage(messages.deepLinkKeysRequired);
1496
+ }
1497
+ }
1498
+ return "";
1499
+ })();
1435
1500
 
1436
1501
  setAndroidDeepLinkKeysError(androidDeepLinkKeysErrorMsg || "");
1437
1502
  setIosDeepLinkKeysError(iosDeepLinkKeysErrorMsg || "");
@@ -1460,12 +1525,26 @@ const MobilePushNew = ({
1460
1525
  if (savedCtas?.length > 0) {
1461
1526
  processedAndroidContent.expandableDetails = {
1462
1527
  ...processedAndroidContent.expandableDetails,
1463
- ctas: savedCtas.map((cta) => ({
1464
- actionText: cta.text,
1465
- type: cta.urlType || DEEP_LINK,
1466
- actionLink: cta.url,
1467
- deepLinkKeys: cta.deepLinkKeys, // Keep deepLinkKeys for createMobilePushPayload.js to process
1468
- })),
1528
+ ctas: savedCtas.map((cta) => {
1529
+ let actionLink = cta?.url;
1530
+
1531
+ // Append deep link keys to URL if they exist
1532
+ if (cta?.urlType === DEEP_LINK && cta?.deepLinkKeys?.length > 0) {
1533
+ const deepLinkKeysArray = Array.isArray(cta?.deepLinkKeys) ? cta?.deepLinkKeys : [cta?.deepLinkKeys];
1534
+ const validKeys = deepLinkKeysArray.filter((key) => typeof key === 'string' && key?.length > 0);
1535
+ if (validKeys?.length > 0) {
1536
+ const separator = actionLink.includes('?') ? '&' : '?';
1537
+ const keyParams = validKeys.map((key) => `${key}={{${key}}}`).join('&');
1538
+ actionLink = `${actionLink}${separator}${keyParams}`;
1539
+ }
1540
+ }
1541
+
1542
+ return {
1543
+ actionText: cta?.text,
1544
+ type: cta?.urlType || DEEP_LINK,
1545
+ actionLink,
1546
+ };
1547
+ }),
1469
1548
  };
1470
1549
  }
1471
1550
  }
@@ -1474,19 +1553,32 @@ const MobilePushNew = ({
1474
1553
  if (savedCtas?.length > 0) {
1475
1554
  processedIosContent.expandableDetails = {
1476
1555
  ...processedIosContent.expandableDetails,
1477
- ctas: savedCtas.map((cta) => ({
1478
- actionText: cta.text,
1479
- type: cta.urlType || DEEP_LINK,
1480
- actionLink: cta.url,
1481
- deepLinkKeys: cta.deepLinkKeys, // Keep deepLinkKeys for createMobilePushPayload.js to process
1482
- })),
1556
+ ctas: savedCtas.map((cta) => {
1557
+ let actionLink = cta?.url;
1558
+
1559
+ // Append deep link keys to URL if they exist
1560
+ if (cta?.urlType === DEEP_LINK && cta?.deepLinkKeys?.length > 0) {
1561
+ const deepLinkKeysArray = Array.isArray(cta?.deepLinkKeys) ? cta?.deepLinkKeys : [cta?.deepLinkKeys];
1562
+ const validKeys = deepLinkKeysArray.filter((key) => typeof key === 'string' && key?.length > 0);
1563
+ if (validKeys?.length > 0) {
1564
+ const separator = actionLink.includes('?') ? '&' : '?';
1565
+ const keyParams = validKeys.map((key) => `${key}={{${key}}}`).join('&');
1566
+ actionLink = `${actionLink}${separator}${keyParams}`;
1567
+ }
1568
+ }
1569
+
1570
+ return {
1571
+ actionText: cta?.text,
1572
+ type: cta?.urlType || DEEP_LINK,
1573
+ actionLink,
1574
+ };
1575
+ }),
1483
1576
  };
1484
1577
  }
1485
1578
  }
1486
1579
 
1487
- // Fix: Only include enabled platform content in payload and pass intl
1488
- const createPayload = createMobilePushPayloadWithIntl.WrappedComponent;
1489
- const payload = createPayload({
1580
+ // Create payload with enabled platform content and intl
1581
+ const payload = createMobilePushPayloadWithIntl({
1490
1582
  templateName: finalTemplateName,
1491
1583
  androidContent: isAndroidSupported ? processedAndroidContent : undefined,
1492
1584
  iosContent: isIosSupported ? processedIosContent : undefined,
@@ -117,7 +117,7 @@ export default defineMessages({
117
117
  },
118
118
  deepLinkKeysPlaceholder: {
119
119
  id: `${scope}.deepLinkKeysPlaceholder`,
120
- defaultMessage: 'Please input {key}',
120
+ defaultMessage: 'Please input {key} here',
121
121
  },
122
122
  deepLinkKeysRequired: {
123
123
  id: `${scope}.deepLinkKeysRequired`,