@capillarytech/creatives-library 8.0.329 → 8.0.330-alpha.1
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/constants/unified.js +4 -0
- package/package.json +1 -1
- package/utils/commonUtils.js +19 -1
- package/utils/templateVarUtils.js +35 -6
- package/utils/tests/tagValidations.test.js +20 -0
- package/utils/tests/templateVarUtils.test.js +44 -0
- package/v2Components/CapActionButton/constants.js +7 -0
- package/v2Components/CapActionButton/index.js +167 -109
- package/v2Components/CapActionButton/index.scss +157 -6
- package/v2Components/CapActionButton/messages.js +19 -3
- package/v2Components/CapActionButton/tests/index.test.js +41 -17
- package/v2Components/CapTagList/index.js +28 -23
- package/v2Components/CapTagList/style.scss +29 -0
- package/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
- package/v2Components/CapTagListWithInput/index.js +4 -0
- package/v2Components/CapWhatsappCTA/index.js +2 -0
- package/v2Components/CommonTestAndPreview/ExistingCustomerModal.js +1 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +160 -15
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +18 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +323 -77
- package/v2Components/CommonTestAndPreview/index.js +49 -57
- package/v2Components/CommonTestAndPreview/messages.js +8 -0
- package/v2Components/CommonTestAndPreview/reducer.js +3 -1
- package/v2Components/CommonTestAndPreview/sagas.js +2 -1
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
- package/v2Components/FormBuilder/index.js +1 -0
- package/v2Components/HtmlEditor/HTMLEditor.js +6 -1
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +927 -2
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +3 -0
- package/v2Components/SmsFallback/smsFallbackUtils.js +14 -3
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +16 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +33 -23
- package/v2Components/TemplatePreview/constants.js +2 -0
- package/v2Components/TemplatePreview/index.js +143 -28
- package/v2Components/TemplatePreview/tests/index.test.js +142 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +5 -0
- package/v2Components/mockdata.js +1 -0
- package/v2Containers/BeeEditor/index.js +19 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +28 -1
- package/v2Containers/CreativesContainer/index.js +9 -3
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -0
- package/v2Containers/Email/index.js +78 -39
- package/v2Containers/Email/reducer.js +2 -2
- package/v2Containers/Email/sagas.js +3 -1
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -2
- package/v2Containers/Email/tests/sagas.test.js +230 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +6 -1
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +20 -2
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +3 -1
- package/v2Containers/EmailWrapper/index.js +4 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +9 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +1 -0
- package/v2Containers/MobilePush/Create/index.js +2 -0
- package/v2Containers/MobilePush/Edit/index.js +2 -0
- package/v2Containers/MobilepushWrapper/index.js +3 -1
- package/v2Containers/Rcs/constants.js +85 -7
- package/v2Containers/Rcs/index.js +1592 -156
- package/v2Containers/Rcs/index.js.rej +1336 -0
- package/v2Containers/Rcs/index.scss +191 -0
- package/v2Containers/Rcs/index.scss.rej +74 -0
- package/v2Containers/Rcs/messages.js +28 -2
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +20 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +69178 -117691
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +128 -0
- package/v2Containers/Rcs/tests/index.test.js +132 -94
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +67 -0
- package/v2Containers/Rcs/tests/utils.test.js +276 -38
- package/v2Containers/Rcs/utils.js +130 -7
- package/v2Containers/Sms/Edit/index.js +2 -0
- package/v2Containers/SmsTrai/Edit/index.js +27 -0
- package/v2Containers/SmsTrai/Edit/messages.js +5 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
- package/v2Containers/SmsWrapper/index.js +2 -0
- package/v2Containers/TagList/index.js +73 -20
- package/v2Containers/TagList/messages.js +4 -0
- package/v2Containers/TagList/tests/TagList.test.js +124 -20
- package/v2Containers/TagList/tests/mockdata.js +17 -0
- package/v2Containers/Templates/_templates.scss +99 -0
- package/v2Containers/Templates/index.js +29 -14
- package/v2Containers/Viber/index.js +3 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -2
- package/v2Containers/WebPush/Create/index.js +10 -2
- package/v2Containers/Whatsapp/index.js +5 -0
- package/v2Containers/Zalo/index.js +2 -0
package/constants/unified.js
CHANGED
|
@@ -168,6 +168,10 @@ export const COMBINED_SMS_TEMPLATE_VAR_REGEX = /\{\{[^}]+\}\}|\{\#[^#]*\#\}/g;
|
|
|
168
168
|
export const MUSTACHE_VAR_TOKEN_FULL_STRING_REGEX = /^\{\{[^}]+\}\}$/;
|
|
169
169
|
/** Full-string check: one DLT hash token. */
|
|
170
170
|
export const DLT_HASH_VAR_TOKEN_FULL_STRING_REGEX = /^\{\#[^#]*\#\}$/;
|
|
171
|
+
/** Full-string with capture group: inner name for `{{ name }}`-style tokens (whitespace-tolerant). */
|
|
172
|
+
export const MUSTACHE_TOKEN_INNER_NAME_REGEX = /^\{\{\s*([^}]+?)\s*\}\}$/;
|
|
173
|
+
/** Full-string with capture group: inner name/body for `{# name #}` DLT tokens (whitespace-tolerant). */
|
|
174
|
+
export const DLT_HASH_TOKEN_INNER_NAME_REGEX = /^\{#\s*(.*?)\s*#\}$/;
|
|
171
175
|
/** Global with capture group: inner name inside `{{name}}`. */
|
|
172
176
|
export const MUSTACHE_VAR_NAME_CAPTURE_REGEX = /\{\{([^}]+)\}\}/g;
|
|
173
177
|
/** Global with capture group: inner body inside `{#body#}`. */
|
package/package.json
CHANGED
package/utils/commonUtils.js
CHANGED
|
@@ -539,4 +539,22 @@ export const isValidMobile = (mobile) => PHONE_REGEX.test(mobile);
|
|
|
539
539
|
export const formatPhoneNumber = (phone) => {
|
|
540
540
|
if (!phone) return '';
|
|
541
541
|
return String(phone).replace(/[^\d]/g, '');
|
|
542
|
-
};
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* TRAI sender IDs on persisted RCS SMS fallback: may live on the merged object, under
|
|
546
|
+
* `templateConfigs`, or (legacy) `templateConfigs.header`. Same resolution order as
|
|
547
|
+
* `createPayload` in `Rcs/index.js`.
|
|
548
|
+
*/
|
|
549
|
+
export function extractRegisteredSenderIdsFromSmsFallbackRecord(record) {
|
|
550
|
+
if (!record || typeof record !== 'object') return null;
|
|
551
|
+
const tc = record.templateConfigs && typeof record.templateConfigs === 'object'
|
|
552
|
+
? record.templateConfigs
|
|
553
|
+
: {};
|
|
554
|
+
const candidates = [record.registeredSenderIds, tc.registeredSenderIds, tc.header];
|
|
555
|
+
for (let i = 0; i < candidates.length; i += 1) {
|
|
556
|
+
const a = candidates[i];
|
|
557
|
+
if (Array.isArray(a) && a.length > 0) return a;
|
|
558
|
+
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
COMBINED_SMS_TEMPLATE_VAR_REGEX,
|
|
8
8
|
DEFAULT_MUSTACHE_VAR_REGEX,
|
|
9
9
|
DLT_HASH_VAR_TOKEN_FULL_STRING_REGEX,
|
|
10
|
+
DLT_HASH_TOKEN_INNER_NAME_REGEX,
|
|
10
11
|
DLT_VAR_BODY_CAPTURE_REGEX,
|
|
12
|
+
MUSTACHE_TOKEN_INNER_NAME_REGEX,
|
|
11
13
|
MUSTACHE_VAR_NAME_CAPTURE_REGEX,
|
|
12
14
|
MUSTACHE_VAR_TOKEN_FULL_STRING_REGEX,
|
|
13
15
|
} from '../constants/unified';
|
|
@@ -115,13 +117,36 @@ export const extractTemplateVariables = (templateStr = '', captureRegex) => {
|
|
|
115
117
|
return variables;
|
|
116
118
|
};
|
|
117
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Looks up the inner name of a `{{name}}` or `{#name#}` token in a flat key→value map.
|
|
122
|
+
* Handles both exact matches and dot-path suffixes (e.g. `tag.FORMAT_1` → name `FORMAT_1`).
|
|
123
|
+
* Returns the resolved string value, or `undefined` if not found / blank.
|
|
124
|
+
*/
|
|
125
|
+
function resolveUserVarForToken(segment, userVarMap) {
|
|
126
|
+
if (!userVarMap || typeof userVarMap !== 'object') return undefined;
|
|
127
|
+
const mMustache = segment.match(MUSTACHE_TOKEN_INNER_NAME_REGEX);
|
|
128
|
+
const mDlt = segment.match(DLT_HASH_TOKEN_INNER_NAME_REGEX);
|
|
129
|
+
const innerName = ((mMustache ? mMustache[1] : (mDlt ? mDlt[1] : '')) ?? '').trim();
|
|
130
|
+
if (!innerName) return undefined;
|
|
131
|
+
const direct = userVarMap[innerName];
|
|
132
|
+
if (direct != null && String(direct).trim() !== '') return String(direct);
|
|
133
|
+
const hit = Object.keys(userVarMap).find((k) => k === innerName || k.endsWith(`.${innerName}`));
|
|
134
|
+
if (hit != null && userVarMap[hit] != null && String(userVarMap[hit]).trim() !== '') return String(userVarMap[hit]);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
118
138
|
/**
|
|
119
139
|
* SMS / DLT template preview: replace `{{…}}` / `{#…#}` tokens using `varMapData` keys `${token}_${index}`.
|
|
120
140
|
* Used by SmsTraiEdit (RCS SMS fallback) and UnifiedPreview fallback SMS bubble.
|
|
121
141
|
* DLT `{#…#}`: empty / unset slot values show the raw token (matches DLT preview UX); mustache `{{…}}` still
|
|
122
142
|
* resolves to empty when the slot is cleared.
|
|
143
|
+
*
|
|
144
|
+
* @param {string} templateStr
|
|
145
|
+
* @param {Object} varMapData - Slot map (`${token}_${index}` → value)
|
|
146
|
+
* @param {Object|null} [userVarMap] - Optional Test & Preview custom values; used as fallback when a slot
|
|
147
|
+
* is absent or blank. When omitted the function behaves identically to its original two-argument form.
|
|
123
148
|
*/
|
|
124
|
-
export const getFallbackResolvedContent = (templateStr = '', varMapData = {}) => {
|
|
149
|
+
export const getFallbackResolvedContent = (templateStr = '', varMapData = {}, userVarMap = null) => {
|
|
125
150
|
const fallbackVarSlotMap = varMapData ?? {};
|
|
126
151
|
const templateSegments = splitTemplateVarString(templateStr, COMBINED_SMS_TEMPLATE_VAR_REGEX);
|
|
127
152
|
return templateSegments
|
|
@@ -132,13 +157,17 @@ export const getFallbackResolvedContent = (templateStr = '', varMapData = {}) =>
|
|
|
132
157
|
if (Object.prototype.hasOwnProperty.call(fallbackVarSlotMap, slotKey)) {
|
|
133
158
|
const slotValue = fallbackVarSlotMap[slotKey];
|
|
134
159
|
if (isDltHashVarToken(segment)) {
|
|
135
|
-
if (slotValue == null)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
160
|
+
if (slotValue == null || String(slotValue).trim() === '') {
|
|
161
|
+
if (userVarMap) { const uv = resolveUserVarForToken(segment, userVarMap); if (uv !== undefined) return uv; }
|
|
162
|
+
return segment;
|
|
163
|
+
}
|
|
164
|
+
return String(slotValue);
|
|
139
165
|
}
|
|
140
|
-
|
|
166
|
+
if (slotValue != null && String(slotValue).trim() !== '') return String(slotValue);
|
|
167
|
+
if (userVarMap) { const uv = resolveUserVarForToken(segment, userVarMap); if (uv !== undefined) return uv; }
|
|
168
|
+
return '';
|
|
141
169
|
}
|
|
170
|
+
if (userVarMap) { const uv = resolveUserVarForToken(segment, userVarMap); if (uv !== undefined) return uv; }
|
|
142
171
|
if (isDltHashVarToken(segment)) return segment;
|
|
143
172
|
return '';
|
|
144
173
|
})
|
|
@@ -360,6 +360,26 @@ describe("validateTags", () => {
|
|
|
360
360
|
expect(resultWhitespace.valid).toBe(true);
|
|
361
361
|
expect(resultWhitespace.unsupportedTags ?? []).toEqual([]);
|
|
362
362
|
});
|
|
363
|
+
|
|
364
|
+
it('should treat tags from waitEventContextTags as supported', () => {
|
|
365
|
+
const content = 'Hello {{waitEvent.orderId}}';
|
|
366
|
+
const tagsParam = [];
|
|
367
|
+
const injectedTagsParams = [];
|
|
368
|
+
const location = { query: { module: 'DEFAULT' } };
|
|
369
|
+
const tagModule = null;
|
|
370
|
+
|
|
371
|
+
const result = validateTags({
|
|
372
|
+
content,
|
|
373
|
+
tagsParam,
|
|
374
|
+
injectedTagsParams,
|
|
375
|
+
location,
|
|
376
|
+
tagModule,
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
expect(result.valid).toEqual(true);
|
|
380
|
+
expect(result.missingTags).toEqual([]);
|
|
381
|
+
expect(result.isBraceError).toEqual(false);
|
|
382
|
+
});
|
|
363
383
|
});
|
|
364
384
|
|
|
365
385
|
describe('validateTags wrapper (v2 consumers)', () => {
|
|
@@ -157,4 +157,48 @@ describe('templateVarUtils', () => {
|
|
|
157
157
|
expect(extractTemplateVariables('{{x}} {{y}}', globalRe)).toEqual(['x', 'y']);
|
|
158
158
|
});
|
|
159
159
|
});
|
|
160
|
+
|
|
161
|
+
describe('getFallbackResolvedContent — userVarMap (third param)', () => {
|
|
162
|
+
it('falls back to userVarMap for mustache slot absent from varMapData', () => {
|
|
163
|
+
expect(getFallbackResolvedContent('Hi {{name}}', {}, { name: 'Alice' })).toBe('Hi Alice');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('falls back to userVarMap for DLT slot absent from varMapData', () => {
|
|
167
|
+
expect(getFallbackResolvedContent('{#city#}', {}, { city: 'Mumbai' })).toBe('Mumbai');
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('falls back to userVarMap when mustache slot is present but blank', () => {
|
|
171
|
+
expect(getFallbackResolvedContent('{{x}}', { '{{x}}_0': '' }, { x: 'val' })).toBe('val');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('falls back to userVarMap when DLT slot is present but blank', () => {
|
|
175
|
+
expect(getFallbackResolvedContent('{#x#}', { '{#x#}_0': '' }, { x: 'val' })).toBe('val');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('slot wins over userVarMap when mustache slot is non-empty', () => {
|
|
179
|
+
expect(getFallbackResolvedContent('{{x}}', { '{{x}}_0': 'slot-val' }, { x: 'user-val' })).toBe('slot-val');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('slot wins over userVarMap when DLT slot is non-empty', () => {
|
|
183
|
+
expect(getFallbackResolvedContent('{#x#}', { '{#x#}_0': 'slot' }, { x: 'user' })).toBe('slot');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('resolves dot-path suffix key from userVarMap', () => {
|
|
187
|
+
expect(
|
|
188
|
+
getFallbackResolvedContent('{{FORMAT_1}}', {}, { 'expiry.FORMAT_1': 'Dec 2025' }),
|
|
189
|
+
).toBe('Dec 2025');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('userVarMap null behaves identically to the two-argument form', () => {
|
|
193
|
+
expect(getFallbackResolvedContent('{{a}}', { '{{a}}_0': 'x' }, null)).toBe('x');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('blank userVarMap value leaves mustache token as empty string', () => {
|
|
197
|
+
expect(getFallbackResolvedContent('{{a}}', {}, { a: '' })).toBe('');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('blank userVarMap value leaves DLT token as raw token', () => {
|
|
201
|
+
expect(getFallbackResolvedContent('{#a#}', {}, { a: '' })).toBe('{#a#}');
|
|
202
|
+
});
|
|
203
|
+
});
|
|
160
204
|
});
|
|
@@ -32,6 +32,13 @@ export const CTA_OPTIONS = [
|
|
|
32
32
|
];
|
|
33
33
|
|
|
34
34
|
export const invalidVarRegex = /{{(.*?)}}/g;
|
|
35
|
+
|
|
36
|
+
/** URL CTA subtype (Figma: URL type dropdown). */
|
|
37
|
+
export const RCS_CTA_URL_TYPE = {
|
|
38
|
+
STATIC: 'STATIC',
|
|
39
|
+
DYNAMIC: 'DYNAMIC',
|
|
40
|
+
};
|
|
41
|
+
|
|
35
42
|
export const BTN_MAX_LENGTH = 25;
|
|
36
43
|
export const PHONE_NUMBER_MAX_LENGTH = 15;
|
|
37
44
|
export const URL_MAX_LENGTH = 2000;
|