@capillarytech/creatives-library 8.0.319 → 8.0.320

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 (106) hide show
  1. package/constants/unified.js +14 -0
  2. package/package.json +1 -1
  3. package/utils/templateVarUtils.js +172 -0
  4. package/utils/tests/templateVarUtils.test.js +160 -0
  5. package/v2Components/CapTagList/index.js +10 -0
  6. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  7. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  8. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
  9. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  10. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  11. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  12. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  13. package/v2Components/CommonTestAndPreview/SendTestMessage.js +11 -5
  14. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  15. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  16. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +12 -0
  17. package/v2Components/CommonTestAndPreview/constants.js +38 -0
  18. package/v2Components/CommonTestAndPreview/index.js +693 -155
  19. package/v2Components/CommonTestAndPreview/messages.js +41 -3
  20. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  21. package/v2Components/CommonTestAndPreview/sagas.js +15 -6
  22. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  23. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +269 -1
  24. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  25. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  26. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +25 -4
  27. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  28. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
  29. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  30. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  31. package/v2Components/FormBuilder/index.js +7 -1
  32. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  33. package/v2Components/SmsFallback/constants.js +73 -0
  34. package/v2Components/SmsFallback/index.js +956 -0
  35. package/v2Components/SmsFallback/index.scss +265 -0
  36. package/v2Components/SmsFallback/messages.js +78 -0
  37. package/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  38. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  39. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  40. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  41. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  42. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  43. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  44. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  45. package/v2Components/TestAndPreviewSlidebox/index.js +8 -1
  46. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  47. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  48. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  49. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  50. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  51. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  52. package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
  53. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  54. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  55. package/v2Containers/CreativesContainer/constants.js +9 -0
  56. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  57. package/v2Containers/CreativesContainer/index.js +289 -99
  58. package/v2Containers/CreativesContainer/index.scss +51 -1
  59. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  60. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +104 -0
  61. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  62. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  63. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  64. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -10
  65. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  66. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  67. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  68. package/v2Containers/Rcs/constants.js +32 -1
  69. package/v2Containers/Rcs/index.js +950 -873
  70. package/v2Containers/Rcs/index.scss +85 -6
  71. package/v2Containers/Rcs/messages.js +10 -1
  72. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  73. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +40834 -1963
  74. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  75. package/v2Containers/Rcs/tests/index.test.js +41 -38
  76. package/v2Containers/Rcs/tests/mockData.js +38 -0
  77. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  78. package/v2Containers/Rcs/tests/utils.test.js +379 -1
  79. package/v2Containers/Rcs/utils.js +358 -10
  80. package/v2Containers/Sms/Create/index.js +81 -36
  81. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  82. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  83. package/v2Containers/SmsTrai/Create/index.js +9 -4
  84. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  85. package/v2Containers/SmsTrai/Edit/index.js +609 -128
  86. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  87. package/v2Containers/SmsTrai/Edit/messages.js +9 -4
  88. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4327 -2374
  89. package/v2Containers/SmsWrapper/index.js +37 -8
  90. package/v2Containers/TagList/index.js +6 -0
  91. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  92. package/v2Containers/Templates/_templates.scss +61 -2
  93. package/v2Containers/Templates/actions.js +11 -0
  94. package/v2Containers/Templates/constants.js +2 -0
  95. package/v2Containers/Templates/index.js +90 -40
  96. package/v2Containers/Templates/sagas.js +57 -12
  97. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  98. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  99. package/v2Containers/Templates/tests/sagas.test.js +193 -12
  100. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  101. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  102. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  103. package/v2Containers/TemplatesV2/index.js +86 -23
  104. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  105. package/v2Containers/Whatsapp/index.js +3 -20
  106. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
@@ -5,18 +5,56 @@
5
5
  position: fixed;
6
6
  bottom: 0;
7
7
  width: 100%;
8
- margin-left: -32px;
8
+ margin-left: -2rem;
9
9
  padding: $CAP_SPACE_32 $CAP_SPACE_24;
10
- margin-top: 40px;
10
+ margin-top: 2.5rem;
11
11
  z-index: 1;
12
12
  .ant-btn {
13
13
  margin-right: $CAP_SPACE_16;
14
14
  }
15
+
16
+ .rcs-test-preview-btn {
17
+ margin-left: $CAP_SPACE_08;
18
+ }
15
19
  }
16
20
 
17
21
  .cap-rcs-creatives {
22
+ .rcs-creative-name-readonly {
23
+ margin-bottom: $CAP_SPACE_24;
24
+ }
25
+
26
+ .rcs-creative-name-value {
27
+ margin-top: $CAP_SPACE_08;
28
+ font-weight: 400;
29
+ }
30
+
18
31
  .rcs-scroll-div {
19
- margin-bottom: 150px;
32
+ margin-bottom: 9.375rem;
33
+ }
34
+
35
+ &.rcs-edit-mode {
36
+ .rcs-scroll-div {
37
+ margin-bottom: 15.625rem;
38
+ }
39
+
40
+ .rcs-edit-template-message-input {
41
+ background-color: $CAP_G10;
42
+ padding: $CAP_SPACE_12 $CAP_SPACE_16;
43
+ }
44
+
45
+ .rcs-edit-template-message-split {
46
+ margin-bottom: $CAP_SPACE_08;
47
+ overflow: hidden;
48
+ text-overflow: ellipsis;
49
+ color: $FONT_COLOR_03;
50
+ font-weight: 500;
51
+ }
52
+ }
53
+
54
+ /* Keep message box text lighter across RCS flows */
55
+ .rcs-edit-template-message-split {
56
+ color: $FONT_COLOR_03;
57
+ font-weight: 500;
20
58
  }
21
59
  .rcs-preview-container {
22
60
  .cap-row-v2 {
@@ -24,18 +62,52 @@
24
62
  }
25
63
  }
26
64
  .rcs-optional-label {
27
- margin-left: 8px;
65
+ margin-left: $CAP_SPACE_08;
28
66
  color: $FONT_COLOR_03;
29
67
  font-weight: normal;
30
68
  }
31
69
  .rcs_text_area_wrapper {
32
70
  position: relative;
33
71
  }
72
+ .rcs-edit-template-message-input .ant-input,
73
+ .rcs-edit-template-message-input textarea.ant-input {
74
+ border-color: $CAP_G07;
75
+ box-shadow: none;
76
+ min-height: 2.5rem;
77
+ padding-top: $CAP_SPACE_08;
78
+ padding-bottom: $CAP_SPACE_08;
79
+ overflow: hidden;
80
+ }
81
+ .rcs-edit-template-message-input .ant-input:focus,
82
+ .rcs-edit-template-message-input .ant-input:active,
83
+ .rcs-edit-template-message-input textarea.ant-input:focus,
84
+ .rcs-edit-template-message-input textarea.ant-input:active {
85
+ border-color: $CAP_G07;
86
+ box-shadow: none;
87
+ outline: none;
88
+ }
34
89
  .rcs-button{
35
90
  display: inline-grid;
36
91
  }
37
- .rcs-button-label{
38
- margin-bottom: 17px;
92
+ .rcs-form-field-caption {
93
+ margin-bottom: $CAP_SPACE_16;
94
+ }
95
+
96
+ .rcs-form-section-heading {
97
+ display: flex;
98
+ margin-top: $CAP_SPACE_20;
99
+ }
100
+
101
+ .rcs-image-upload--top-spacing {
102
+ padding-top: $CAP_SPACE_20;
103
+ }
104
+
105
+ .rcs-dimension-select--bottom-spacing {
106
+ margin-bottom: $CAP_SPACE_20;
107
+ }
108
+
109
+ .rcs-fallback-section-divider {
110
+ margin: $CAP_SPACE_28 0;
39
111
  }
40
112
  .disabled-button{
41
113
  opacity: 0.5;
@@ -87,6 +159,7 @@
87
159
  margin-top: 13px;
88
160
  float: right;
89
161
  }
162
+
90
163
  .rcs-fallback-len-error{
91
164
  margin-top: 8px;
92
165
  }
@@ -127,6 +200,12 @@
127
200
  width: 430px;
128
201
  }
129
202
 
203
+ // SMS fallback slidebox / tag popover: see v2Components/SmsFallback/index.scss (loaded with SmsFallback)
204
+
205
+ .template-status-container {
206
+ margin-bottom: $CAP_SPACE_24;
207
+ }
208
+
130
209
  .rcs-button-cta{
131
210
  margin-top: 1.25rem;
132
211
  margin-bottom: 0.75rem;
@@ -262,6 +262,10 @@ export default defineMessages({
262
262
  id: `${prefix}.fallbackLabel`,
263
263
  defaultMessage: 'Fallback SMS message',
264
264
  },
265
+ smsFallbackOptional: {
266
+ id: `${prefix}.smsFallbackOptional`,
267
+ defaultMessage: 'Fallback SMS message (Optional)',
268
+ },
265
269
  fallbackDesc: {
266
270
  id: `${prefix}.fallbackDesc`,
267
271
  defaultMessage: 'We would suggest to add fallback SMS',
@@ -281,7 +285,12 @@ export default defineMessages({
281
285
  },
282
286
  fallbackMsgPlaceholder: {
283
287
  id: `${prefix}.fallbackMsgPlaceholder`,
284
- defaultMessage: 'Enter the text message content for fallback SMS',
288
+ defaultMessage: 'Add labels or text',
289
+ },
290
+ /** Shown only when a {{…}} slot has no value — not the saved text (that uses the input value). */
291
+ rcsVarSlotPlaceholder: {
292
+ id: `${prefix}.rcsVarSlotPlaceholder`,
293
+ defaultMessage: 'Add labels or text',
285
294
  },
286
295
  totalCharacters: {
287
296
  id: `${prefix}.totalCharacters`,
@@ -0,0 +1,205 @@
1
+ import isEmpty from 'lodash/isEmpty';
2
+ import get from 'lodash/get';
3
+ import { RCS_SMS_FALLBACK_VAR_MAPPED_PROP } from '../../v2Components/CommonTestAndPreview/constants';
4
+
5
+ /**
6
+ * Nested `versions…smsFallBackContent` and root `smsFallBackContent` (CreativesContainer mirror)
7
+ * can diverge. Merge explicitly (avoid `get(..., {}) || root` — `{}` is truthy and blocks fallback).
8
+ *
9
+ * When both exist, **nested wins on overlap**: the canonical RCS path is what `createPayload` / submit
10
+ * update; the root mirror can lag behind campaign parent state and would otherwise keep old
11
+ * `message` / `rcsSmsFallbackVarMapped` in hydration and approval payloads.
12
+ */
13
+ export function mergeRcsSmsFallBackContentFromDetails(details) {
14
+ if (!details || typeof details !== 'object') return {};
15
+ const nestedSmsFallback = details?.versions?.base?.content?.RCS?.smsFallBackContent;
16
+ const rootSmsFallback = details?.smsFallBackContent;
17
+ const nestedRecord =
18
+ nestedSmsFallback != null && typeof nestedSmsFallback === 'object' ? nestedSmsFallback : {};
19
+ const rootRecord =
20
+ rootSmsFallback != null && typeof rootSmsFallback === 'object' ? rootSmsFallback : {};
21
+ return { ...rootRecord, ...nestedRecord };
22
+ }
23
+
24
+ /**
25
+ * Merge SMS fallback slot maps from API/templateData (`apiShape`) and editor state (`localShape`).
26
+ * Spreading `{ ...api, ...local }` lets `rcsSmsFallbackVarMapped: {}` on local wipe a populated API map,
27
+ * which keeps Done disabled in DLT campaigns until fixed.
28
+ */
29
+ export function mergeRcsSmsFallbackVarMapLayers(apiShape = {}, localShape = {}) {
30
+ const readMap = (o) => {
31
+ if (!o || typeof o !== 'object') return {};
32
+ const camel = o.rcsSmsFallbackVarMapped;
33
+ const kebab = o['rcs-sms-fallback-var-mapped'];
34
+ const src =
35
+ camel && typeof camel === 'object'
36
+ ? camel
37
+ : kebab && typeof kebab === 'object'
38
+ ? kebab
39
+ : {};
40
+ return { ...src };
41
+ };
42
+ return { ...readMap(apiShape), ...readMap(localShape) };
43
+ }
44
+
45
+ /**
46
+ * First non-empty trimmed string for SMS fallback body used in DLT slot checks / payload `templateContent`.
47
+ * Prefer **raw** template fields before resolved `message` so `{#…#}` / `{{…}}` tokens are not lost
48
+ * when `message` is consumer-resolved text (campaigns).
49
+ */
50
+ /**
51
+ * Whether an SMS fallback object carries template body, name, or var-map data (same rule as Rcs `createPayload`).
52
+ */
53
+ export function hasMeaningfulSmsFallbackShape(s) {
54
+ return !!(
55
+ s
56
+ && (
57
+ String(
58
+ s.content
59
+ || s.templateContent
60
+ || s.message
61
+ || s.smsContent
62
+ || s.smsTemplateContent
63
+ || '',
64
+ ).trim() !== ''
65
+ || String(s.templateName || s.smsTemplateName || '').trim() !== ''
66
+ || (s.rcsSmsFallbackVarMapped && Object.keys(s.rcsSmsFallbackVarMapped).length > 0)
67
+ || (s[RCS_SMS_FALLBACK_VAR_MAPPED_PROP]
68
+ && Object.keys(s[RCS_SMS_FALLBACK_VAR_MAPPED_PROP]).length > 0)
69
+ )
70
+ );
71
+ }
72
+
73
+ /**
74
+ * Library `templateData`: merged root + nested `smsFallBackContent` (nested wins), matching `createPayload`.
75
+ */
76
+ export function getLibrarySmsFallbackApiBaselineFromTemplateData(templateData) {
77
+ const smsFromTemplateRoot = get(
78
+ templateData,
79
+ 'versions.base.content.RCS.smsFallBackContent',
80
+ );
81
+ return {
82
+ ...(templateData?.smsFallBackContent && typeof templateData.smsFallBackContent === 'object'
83
+ ? templateData.smsFallBackContent
84
+ : {}),
85
+ ...(smsFromTemplateRoot && typeof smsFromTemplateRoot === 'object'
86
+ ? smsFromTemplateRoot
87
+ : {}),
88
+ };
89
+ }
90
+
91
+ export function pickFirstSmsFallbackTemplateString(sms = {}) {
92
+ if (!sms || typeof sms !== 'object') return '';
93
+ const keys = [
94
+ 'templateContent',
95
+ 'smsTemplateContent',
96
+ 'content',
97
+ 'smsContent',
98
+ 'message',
99
+ ];
100
+ for (let i = 0; i < keys.length; i += 1) {
101
+ const v = sms[keys[i]];
102
+ if (v == null) continue;
103
+ const s = String(v).trim();
104
+ if (s) return s;
105
+ }
106
+ return '';
107
+ }
108
+
109
+ /**
110
+ * Campaign reopen: payloads often keep tag/label values on numeric keys (`"1"`, `"2"`, …) while
111
+ * semantic keys (`user_name`, …) stay `""`. Copy non-empty slot values onto empty semantic keys so
112
+ * VarSegment editors prepopulate after Done → Edit without changing global resolve behavior.
113
+ */
114
+ export function syncCardVarMappedSemanticsFromSlots(
115
+ cardVarMappedInput,
116
+ templateTitle,
117
+ templateDesc,
118
+ rcsVarRegex,
119
+ ) {
120
+ const cardVarMappedSynced =
121
+ cardVarMappedInput != null && typeof cardVarMappedInput === 'object'
122
+ ? { ...cardVarMappedInput }
123
+ : {};
124
+ const getVarNameFromToken = (token = '') => token.replace(/^\{\{|\}\}$/g, '');
125
+ const templateVarTokens = [
126
+ ...(templateTitle?.match(rcsVarRegex) ?? []),
127
+ ...(templateDesc?.match(rcsVarRegex) ?? []),
128
+ ];
129
+ templateVarTokens.forEach((token, slotIndexZeroBased) => {
130
+ const semanticVarName = getVarNameFromToken(token);
131
+ if (!semanticVarName) return;
132
+ const numericSlotKey = String(slotIndexZeroBased + 1);
133
+ const semanticValueTrimmed = String(cardVarMappedSynced[semanticVarName] ?? '').trim();
134
+ const numericSlotValueTrimmed = String(cardVarMappedSynced[numericSlotKey] ?? '').trim();
135
+ if (!semanticValueTrimmed && numericSlotValueTrimmed) {
136
+ cardVarMappedSynced[semanticVarName] = cardVarMappedSynced[numericSlotKey];
137
+ }
138
+ });
139
+ return cardVarMappedSynced;
140
+ }
141
+
142
+ /**
143
+ * Maps resolved campaign values back to `{{semanticKey}}` using `cardVarMapped` keys.
144
+ * Used when hydrating library/journey RCS edit from payloads without existing `{{…}}` tokens.
145
+ */
146
+ export function getUnmappedDesc(str, mapping) {
147
+ if (!str) return '';
148
+ if (!mapping || Object.keys(mapping).length === 0) return str;
149
+ let result = str;
150
+ const replacements = [];
151
+ Object.entries(mapping).forEach(([key, value]) => {
152
+ const raw = (value ?? '').toString();
153
+ if (!raw || raw?.trim?.() === '') return;
154
+ const braced = /^\{\{[\s\S]*\}\}$/.test(raw) ? raw : `{{${raw}}}`;
155
+ replacements.push({ key, needle: raw });
156
+ if (braced !== raw) replacements.push({ key, needle: braced });
157
+ });
158
+ const seen = new Set();
159
+ const uniq = replacements
160
+ .filter(({ key, needle }) => {
161
+ const id = `${key}::${needle}`;
162
+ if (seen.has(id)) return false;
163
+ seen.add(id);
164
+ return true;
165
+ })
166
+ .sort((a, b) => (b.needle.length - a.needle.length));
167
+
168
+ uniq.forEach(({ key, needle }) => {
169
+ if (!needle) return;
170
+ const escaped = needle.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
171
+ const regex = new RegExp(escaped, 'g');
172
+ result = result.replace(regex, `{{${key}}}`);
173
+ });
174
+ return result;
175
+ }
176
+
177
+ export function hasRcsVarTokens(s, rcsVarRegex) {
178
+ return (s?.match(rcsVarRegex) ?? []).length > 0;
179
+ }
180
+
181
+ /**
182
+ * Library / journey: only run `getUnmappedDesc` when the loaded copy has no `{{…}}` tokens
183
+ * (e.g. fully resolved campaign text). If the API already has numeric or named slots, keep as-is.
184
+ */
185
+ export function normalizeLibraryLoadedTitleDesc({
186
+ loadedTitle,
187
+ loadedDesc,
188
+ isFullMode,
189
+ cardVarMappedAfterHydration,
190
+ rcsVarRegex,
191
+ }) {
192
+ const normalizedTitle =
193
+ !isFullMode
194
+ && !isEmpty(cardVarMappedAfterHydration)
195
+ && !hasRcsVarTokens(loadedTitle, rcsVarRegex)
196
+ ? getUnmappedDesc(loadedTitle, cardVarMappedAfterHydration)
197
+ : loadedTitle;
198
+ const normalizedDesc =
199
+ !isFullMode
200
+ && !isEmpty(cardVarMappedAfterHydration)
201
+ && !hasRcsVarTokens(loadedDesc, rcsVarRegex)
202
+ ? getUnmappedDesc(loadedDesc, cardVarMappedAfterHydration)
203
+ : loadedDesc;
204
+ return { normalizedTitle, normalizedDesc };
205
+ }