@antscorp/antsomi-ui 2.0.113 → 2.0.115
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/CHANGELOG.md +92 -63
- package/es/components/atoms/SelectAssociatedTag/SelectAssociatedTag.d.ts +5 -0
- package/es/components/atoms/SelectAssociatedTag/SelectAssociatedTag.js +15 -0
- package/es/components/atoms/SelectAssociatedTag/SelectTag.d.ts +4 -0
- package/es/components/atoms/SelectAssociatedTag/SelectTag.js +26 -0
- package/es/components/atoms/SelectAssociatedTag/constants.d.ts +11 -0
- package/es/components/atoms/SelectAssociatedTag/constants.js +42 -0
- package/es/components/atoms/SelectAssociatedTag/index.d.ts +3 -0
- package/es/components/atoms/SelectAssociatedTag/index.js +2 -0
- package/es/components/atoms/SelectAssociatedTag/styled.d.ts +7 -0
- package/es/components/atoms/SelectAssociatedTag/styled.js +60 -0
- package/es/components/atoms/SelectAssociatedTag/types.d.ts +76 -0
- package/es/components/atoms/SelectAssociatedTag/types.js +1 -0
- package/es/components/atoms/index.d.ts +1 -0
- package/es/components/atoms/index.js +1 -0
- package/es/components/icons/CircleInfoIcon.js +2 -2
- package/es/components/icons/LazyIcon/LazyIcon.d.ts +2 -0
- package/es/components/icons/LazyIcon/LazyIcon.js +2 -0
- package/es/components/molecules/InputSelectAttribute/index.d.ts +25 -0
- package/es/components/molecules/InputSelectAttribute/index.js +124 -0
- package/es/components/molecules/InputSelectAttribute/styled.d.ts +14 -0
- package/es/components/molecules/InputSelectAttribute/styled.js +33 -0
- package/es/components/molecules/SelectV2/styled.d.ts +3 -1
- package/es/components/molecules/SelectV2/styled.js +2 -2
- package/es/components/molecules/TagifyInput/TagifyInput.js +159 -71
- package/es/components/molecules/TagifyInput/constants.d.ts +24 -2
- package/es/components/molecules/TagifyInput/constants.js +25 -2
- package/es/components/molecules/TagifyInput/patternHandlers.d.ts +12 -6
- package/es/components/molecules/TagifyInput/patternHandlers.js +88 -43
- package/es/components/molecules/TagifyInput/types.d.ts +24 -3
- package/es/components/molecules/TagifyInput/utils.d.ts +10 -1
- package/es/components/molecules/TagifyInput/utils.js +82 -4
- package/es/components/molecules/TagifyInput/utils.style.js +81 -96
- package/es/components/molecules/index.d.ts +1 -0
- package/es/components/molecules/index.js +1 -0
- package/es/components/organism/AccountSharing/AccountSharing.js +18 -10
- package/es/components/organism/ActivityTimeline/utils.js +168 -2
- package/es/components/organism/LeftMenu/hooks/usePermission.js +1 -1
- package/es/components/organism/LeftMenu/utils/index.js +1 -1
- package/es/components/organism/TextEditor/TextEditor.js +17 -1
- package/es/components/organism/TextEditor/types.d.ts +6 -2
- package/es/components/organism/TextEditor/ui/Toolbar/FormattingToolbar.js +11 -6
- package/es/utils/cookie.js +9 -0
- package/package.json +5 -5
|
@@ -5,15 +5,32 @@ export const DIMENSIONS = {
|
|
|
5
5
|
TAG_H: 24,
|
|
6
6
|
};
|
|
7
7
|
export const { MIN_H_WRAPPER, TAG_H } = DIMENSIONS;
|
|
8
|
+
export const TAG_STATUS = {
|
|
9
|
+
REMOVED: 'removed',
|
|
10
|
+
ARCHIVED: 'archived',
|
|
11
|
+
ACTIVE: 'active',
|
|
12
|
+
INACTIVE: 'inactive',
|
|
13
|
+
EXPIRED: 'expired',
|
|
14
|
+
WARNING: 'warning',
|
|
15
|
+
ERROR: 'error',
|
|
16
|
+
INVALID: 'invalid',
|
|
17
|
+
DO_NOT_VIEW: 'do-not-view',
|
|
18
|
+
};
|
|
8
19
|
export const TAG_CUSTOM_ATTRIBUTES = {
|
|
20
|
+
PREPARING_ST: 'preparing-setting',
|
|
9
21
|
READONLY_TAG: 'readonly-tag',
|
|
10
22
|
INVALID_TAG: 'invalid-tag',
|
|
11
23
|
REMOVED_TAG: 'removed-tag',
|
|
12
24
|
NO_VIEW_TAG: 'no-view-tag',
|
|
13
25
|
MESSAGE_TAG: 'message-tag',
|
|
14
26
|
FORCE_SHOW_TOOLTIP: 'force-show-tooltip',
|
|
27
|
+
ERROR_TAG: 'error-tag',
|
|
28
|
+
WARNING_TAG: 'warning-tag',
|
|
29
|
+
PRIORITY_COLOR_TYPE: 'priority-color-type',
|
|
30
|
+
BG_COLOR_PERSONALIZE_TYPE: 'bg-color-personalize-type',
|
|
31
|
+
BG_COLOR_PERSONALIZE_TYPE_V2: 'bgColorPersonalizeType',
|
|
15
32
|
};
|
|
16
|
-
export const { READONLY_TAG, INVALID_TAG, REMOVED_TAG, NO_VIEW_TAG, MESSAGE_TAG, FORCE_SHOW_TOOLTIP, } = TAG_CUSTOM_ATTRIBUTES;
|
|
33
|
+
export const { PREPARING_ST, READONLY_TAG, INVALID_TAG, REMOVED_TAG, NO_VIEW_TAG, MESSAGE_TAG, FORCE_SHOW_TOOLTIP, ERROR_TAG, WARNING_TAG, PRIORITY_COLOR_TYPE, BG_COLOR_PERSONALIZE_TYPE, BG_COLOR_PERSONALIZE_TYPE_V2, } = TAG_CUSTOM_ATTRIBUTES;
|
|
17
34
|
export const defaultCssVariables = {
|
|
18
35
|
'--input-color': globalToken?.colorText,
|
|
19
36
|
'--input-font-size': `${globalToken?.fontSize}px`,
|
|
@@ -58,6 +75,7 @@ export const tagifyDefaultProps = {
|
|
|
58
75
|
placeholder: undefined,
|
|
59
76
|
minWidthPlaceholder: 130,
|
|
60
77
|
acceptableTagPattern: DEFAULT_ACCEPT_TAGS,
|
|
78
|
+
mapErrorAttributes: {},
|
|
61
79
|
onChange: () => { },
|
|
62
80
|
};
|
|
63
81
|
export const TAG_TYPE = {
|
|
@@ -75,9 +93,12 @@ export const TAG_TYPE = {
|
|
|
75
93
|
SHORT_LINK_V2: 'shortlink_v2',
|
|
76
94
|
DETECT_LINK: 'detect_link',
|
|
77
95
|
CONTENT_SOURCE_GROUP: 'groups',
|
|
96
|
+
ALLOCATED_CODE: 'allocated_code',
|
|
97
|
+
CUSTOM_TAG: 'custom_tag', // Refer to all tag type
|
|
78
98
|
UNSUBSCRIBE_WHATSAPP: 'unsubscribe_whatsapp',
|
|
79
99
|
};
|
|
80
|
-
export const { CUSTOMER, VISITOR, EVENT, JOURNEY, CAMPAIGN, VARIANT, PROMOTION_CODE, CUSTOM_FN, EMOJI, DETECT_LINK, SHORT_LINK, SHORT_LINK_V2, OBJECT_WIDGET, CONTENT_SOURCE_GROUP, UNSUBSCRIBE_WHATSAPP, } = TAG_TYPE;
|
|
100
|
+
export const { CUSTOMER, VISITOR, EVENT, JOURNEY, CAMPAIGN, VARIANT, PROMOTION_CODE, CUSTOM_FN, EMOJI, DETECT_LINK, SHORT_LINK, SHORT_LINK_V2, OBJECT_WIDGET, CONTENT_SOURCE_GROUP, ALLOCATED_CODE, CUSTOM_TAG, UNSUBSCRIBE_WHATSAPP, } = TAG_TYPE;
|
|
101
|
+
export const TAG_TYPE_LIST = Object.freeze(Object.values(TAG_TYPE));
|
|
81
102
|
export const SHORT_LINK_TYPE = {
|
|
82
103
|
INDIVIDUAL: 'shortlink', // Individual link
|
|
83
104
|
GENERAL: 'shortlink_static', // General link
|
|
@@ -107,6 +128,8 @@ export const TAG_COLOR = {
|
|
|
107
128
|
[CUSTOM_FN]: '#bbefbe',
|
|
108
129
|
[CONTENT_SOURCE_GROUP]: '#ffdd9f',
|
|
109
130
|
[EMOJI]: 'transparent',
|
|
131
|
+
[ALLOCATED_CODE]: '#DAA7F8',
|
|
132
|
+
[CUSTOM_TAG]: 'transparent',
|
|
110
133
|
[UNSUBSCRIBE_WHATSAPP]: '#cafedd',
|
|
111
134
|
};
|
|
112
135
|
export const EMOJI_COLLECTIONS = {
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import type { AcceptablePattern, MapAttributesProps, PatterTagName, PatternHandlerWrapper } from './types';
|
|
1
|
+
import type { AcceptablePattern, MapAttributesProps, PatterTagName, PatternHandlerWrapper, TagTypeProperty } from './types';
|
|
2
2
|
interface TagInfo {
|
|
3
3
|
label: string;
|
|
4
4
|
type: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
isRemoved?: boolean;
|
|
8
|
-
hasViewPermission?: boolean;
|
|
5
|
+
status: string;
|
|
6
|
+
statusMsg: string;
|
|
9
7
|
}
|
|
10
8
|
/**
|
|
11
9
|
* Retrieves a cached regular expression or compiles and caches it if not found.
|
|
@@ -18,7 +16,15 @@ export declare function getCachedRegex(pattern: string, flags?: string, cacheKey
|
|
|
18
16
|
export declare const detectURLRegex: RegExp;
|
|
19
17
|
export declare const tagRegexStringPattern = "\\[\\[({.*?})\\]\\]";
|
|
20
18
|
export declare function acceptablePatternChecking(pattern: AcceptablePattern, acceptablePattern: Array<AcceptablePattern>): boolean;
|
|
21
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Extracts the custom tag ID from a merge code if the tag type is a custom tag.
|
|
21
|
+
*
|
|
22
|
+
* @param {TagTypeProperty} tagType - The type of the tag to check.
|
|
23
|
+
* @param {string} mergeCode - The merge code containing the tag information, typically in the format "type.customTagId||additionalInfo".
|
|
24
|
+
* @returns {string} The extracted custom tag ID if the tag type is a custom tag; otherwise, empty string.
|
|
25
|
+
*/
|
|
26
|
+
export declare const getCustomTagId: (tagType: TagTypeProperty, mergeCode: string) => string;
|
|
27
|
+
export declare const getPersonalizeTagInfo: (originalTag: string, mapAttributes: MapAttributesProps, mapErrorAttributes: MapAttributesProps) => TagInfo;
|
|
22
28
|
export declare const getShortLinkTagInfo: (params: {
|
|
23
29
|
type: string;
|
|
24
30
|
label: string;
|
|
@@ -9,7 +9,8 @@ import { isViberEmoji } from './iconsViber';
|
|
|
9
9
|
import { random } from '@antscorp/antsomi-ui/es/utils';
|
|
10
10
|
import { containsTagType } from './utils';
|
|
11
11
|
// Constants
|
|
12
|
-
import { CONTENT_SOURCE_GROUP, EMOJI, EMOJI_COLLECTIONS, LINE_EMOJI_PTN, PERSONALIZE_PTN, PREFIX_PATTERN_LINE_MESSAGE, PROMOTION_CODE, SHORT_LINK, SHORT_LINK_GENERAL_PTN, SHORT_LINK_INDIVIDUAL_PTN, SHORT_LINK_PTN, SHORT_LINK_TYPE, SHORT_LINK_V2, SHORT_LINK_V2_GENERAL_PTN, SHORT_LINK_V2_INDIVIDUAL_PTN, VIBER_EMOJI_PTN, UNSUBSCRIBE_WHATSAPP, UNSUBSCRIBE_WHATSAPP_PTN, UNSUBSCRIBE_PTN, } from './constants';
|
|
12
|
+
import { CONTENT_SOURCE_GROUP, EMOJI, EMOJI_COLLECTIONS, LINE_EMOJI_PTN, PERSONALIZE_PTN, PREFIX_PATTERN_LINE_MESSAGE, PROMOTION_CODE, SHORT_LINK, SHORT_LINK_GENERAL_PTN, SHORT_LINK_INDIVIDUAL_PTN, SHORT_LINK_PTN, SHORT_LINK_TYPE, SHORT_LINK_V2, SHORT_LINK_V2_GENERAL_PTN, SHORT_LINK_V2_INDIVIDUAL_PTN, TAG_STATUS, TAG_TYPE, VIBER_EMOJI_PTN, UNSUBSCRIBE_WHATSAPP, UNSUBSCRIBE_WHATSAPP_PTN, UNSUBSCRIBE_PTN, } from './constants';
|
|
13
|
+
const { CUSTOM_TAG } = TAG_TYPE;
|
|
13
14
|
/*
|
|
14
15
|
* Usage to cache compiled regular expressions:
|
|
15
16
|
* const regex = getCachedRegex(pattern, flags);
|
|
@@ -202,6 +203,21 @@ const getContentSourceLabel = (attributeName, subAttributeName, mapAttributes) =
|
|
|
202
203
|
}
|
|
203
204
|
return attributeName;
|
|
204
205
|
};
|
|
206
|
+
/**
|
|
207
|
+
* Extracts the custom tag ID from a merge code if the tag type is a custom tag.
|
|
208
|
+
*
|
|
209
|
+
* @param {TagTypeProperty} tagType - The type of the tag to check.
|
|
210
|
+
* @param {string} mergeCode - The merge code containing the tag information, typically in the format "type.customTagId||additionalInfo".
|
|
211
|
+
* @returns {string} The extracted custom tag ID if the tag type is a custom tag; otherwise, empty string.
|
|
212
|
+
*/
|
|
213
|
+
export const getCustomTagId = (tagType, mergeCode) => {
|
|
214
|
+
const isCustomTag = tagType === CUSTOM_TAG;
|
|
215
|
+
if (!isCustomTag)
|
|
216
|
+
return '';
|
|
217
|
+
const [tagCode] = mergeCode.split('||');
|
|
218
|
+
const [, customTagId] = tagCode.split('.');
|
|
219
|
+
return customTagId;
|
|
220
|
+
};
|
|
205
221
|
/**
|
|
206
222
|
* Retrieves the label for a attribute tag.
|
|
207
223
|
* @param {string} type - The type from the original tag.
|
|
@@ -221,7 +237,9 @@ const getLabelAttribute = (type, attributeName, subAttributeName, mapAttributes)
|
|
|
221
237
|
mapping[attributeName]?.value ||
|
|
222
238
|
type);
|
|
223
239
|
}
|
|
224
|
-
const combineAttribute =
|
|
240
|
+
const combineAttribute = subAttributeName
|
|
241
|
+
? `${attributeName}.${subAttributeName}`
|
|
242
|
+
: attributeName;
|
|
225
243
|
return (mapping[combineAttribute]?.label ||
|
|
226
244
|
mapping[combineAttribute]?.display ||
|
|
227
245
|
mapping[combineAttribute]?.template_name ||
|
|
@@ -231,79 +249,104 @@ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttrib
|
|
|
231
249
|
try {
|
|
232
250
|
const [type, attributeName, subAttributeName] = originalTag.split('.');
|
|
233
251
|
const isCsGroup = type === CONTENT_SOURCE_GROUP;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
252
|
+
const combineAttribute = subAttributeName
|
|
253
|
+
? `${attributeName}.${subAttributeName}`
|
|
254
|
+
: attributeName;
|
|
255
|
+
let status = '';
|
|
256
|
+
let statusMsg = '';
|
|
238
257
|
// Get label based on mapping
|
|
239
258
|
const label = isCsGroup
|
|
240
259
|
? getContentSourceLabel(attributeName, subAttributeName, mapAttributes)
|
|
241
260
|
: getLabelAttribute(type, attributeName, subAttributeName, mapAttributes);
|
|
242
|
-
// Check additional case for each tag type
|
|
243
|
-
let [isValid, message, isRemoved, hasViewPermission] = [true, '', false, true];
|
|
244
261
|
switch (type) {
|
|
245
262
|
case PROMOTION_CODE: {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
if (has(mapErrorAttributes, [type, attributeName])) {
|
|
264
|
+
status = TAG_STATUS.INVALID;
|
|
265
|
+
statusMsg = 'This pool does not exist anymore';
|
|
266
|
+
const {
|
|
267
|
+
// isEdit = false,
|
|
268
|
+
isView = false, isExist = true, isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes?.[type]?.[attributeName] || {};
|
|
269
|
+
if (!isExist) {
|
|
270
|
+
// Case Pool Removed
|
|
271
|
+
status = TAG_STATUS.REMOVED;
|
|
272
|
+
statusMsg = translate(translations._PERSONALIZATION_TAG_ERR_REMOVED, 'This pool is removed');
|
|
273
|
+
}
|
|
274
|
+
else if (_isArchived) {
|
|
275
|
+
// Case Pool is Archived
|
|
276
|
+
status = TAG_STATUS.ARCHIVED;
|
|
277
|
+
statusMsg = translate(translations._PERSONALIZATION_TAG_ERR_ATT_ARCHIVE, 'This attribute has been archived');
|
|
278
|
+
}
|
|
279
|
+
else if (!_isActive) {
|
|
280
|
+
// Case Pool is Inactive
|
|
281
|
+
status = TAG_STATUS.INACTIVE;
|
|
282
|
+
statusMsg = translate(translations._PERSONALIZATION_TAG_ERR_POOL_DEACTIVATE, 'This pool has been deactivated. You have to turn it on to use');
|
|
283
|
+
}
|
|
284
|
+
else if (_isExpired) {
|
|
285
|
+
// Case Pool is Expired
|
|
286
|
+
status = TAG_STATUS.EXPIRED;
|
|
287
|
+
statusMsg = translate(translations._PERSONALIZATION_TAG_ERR_POOL_EXPIRE, 'This pool has expired, new codes could not be allocated');
|
|
288
|
+
}
|
|
289
|
+
else if (!isView) {
|
|
290
|
+
// Case Pool Can't View
|
|
291
|
+
status = TAG_STATUS.DO_NOT_VIEW;
|
|
292
|
+
statusMsg = translate(translations._PERMISSION_ERR_POOL, 'You do not have permission on this pool');
|
|
267
293
|
}
|
|
268
294
|
}
|
|
295
|
+
// }
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
case CUSTOM_TAG: {
|
|
269
299
|
break;
|
|
270
300
|
}
|
|
271
301
|
default: {
|
|
302
|
+
if (has(mapErrorAttributes, [type, combineAttribute])) {
|
|
303
|
+
status = TAG_STATUS.ERROR;
|
|
304
|
+
statusMsg = 'This attribute does not exist anymore';
|
|
305
|
+
const { isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes?.[type]?.[combineAttribute] || {};
|
|
306
|
+
if (_isArchived) {
|
|
307
|
+
// Case Tag is Archived
|
|
308
|
+
status = TAG_STATUS.ARCHIVED;
|
|
309
|
+
statusMsg = translate(translations._PERSONALIZATION_TAG_ERR_ATT_ARCHIVE, 'This attribute has been archived');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
272
312
|
break;
|
|
273
313
|
}
|
|
274
314
|
}
|
|
275
315
|
return {
|
|
276
316
|
type,
|
|
277
|
-
message,
|
|
278
|
-
isValid,
|
|
279
317
|
label: label || type,
|
|
280
|
-
|
|
281
|
-
|
|
318
|
+
status,
|
|
319
|
+
statusMsg,
|
|
282
320
|
};
|
|
283
321
|
}
|
|
284
322
|
catch (error) {
|
|
285
323
|
console.error('Error in getTagLabel', error);
|
|
286
|
-
return {
|
|
324
|
+
return {
|
|
325
|
+
label: originalTag,
|
|
326
|
+
type: originalTag,
|
|
327
|
+
status: TAG_STATUS.ERROR,
|
|
328
|
+
statusMsg: 'This tag does not exist anymore',
|
|
329
|
+
};
|
|
287
330
|
}
|
|
288
331
|
};
|
|
289
332
|
export const getShortLinkTagInfo = (params) => {
|
|
290
333
|
const { type, label, url, shortener, mapAttributes, mapErrorAttributes } = params;
|
|
291
334
|
try {
|
|
292
|
-
let [
|
|
335
|
+
let [status, statusMsg] = ['', ''];
|
|
293
336
|
switch (type) {
|
|
294
337
|
case SHORT_LINK_V2:
|
|
295
338
|
if (mapAttributes && mapAttributes[type]) {
|
|
296
339
|
const isExistShortLink = has(mapAttributes[type], shortener);
|
|
297
340
|
if (!isExistShortLink) {
|
|
298
|
-
|
|
299
|
-
|
|
341
|
+
status = TAG_STATUS.INVALID;
|
|
342
|
+
statusMsg = translate(translations?._PER_TAG_LINK_ERR || '', 'This shortener is inactivated or removed');
|
|
300
343
|
if (mapErrorAttributes &&
|
|
301
344
|
mapErrorAttributes?.[type] &&
|
|
302
345
|
mapErrorAttributes?.[type]?.[shortener]) {
|
|
303
346
|
const { isView = true, isExist = true } = mapErrorAttributes[type][shortener] || {};
|
|
304
347
|
if (!isExist || !isView) {
|
|
305
|
-
|
|
306
|
-
|
|
348
|
+
status = TAG_STATUS.REMOVED;
|
|
349
|
+
statusMsg = translate(translations?._PER_TAG_LINK_ERR || '', 'This shortener is inactivated or removed');
|
|
307
350
|
}
|
|
308
351
|
}
|
|
309
352
|
}
|
|
@@ -314,9 +357,9 @@ export const getShortLinkTagInfo = (params) => {
|
|
|
314
357
|
}
|
|
315
358
|
return {
|
|
316
359
|
type,
|
|
317
|
-
message,
|
|
318
|
-
isValid,
|
|
319
360
|
label,
|
|
361
|
+
status,
|
|
362
|
+
statusMsg,
|
|
320
363
|
};
|
|
321
364
|
}
|
|
322
365
|
catch (error) {
|
|
@@ -324,8 +367,8 @@ export const getShortLinkTagInfo = (params) => {
|
|
|
324
367
|
return {
|
|
325
368
|
label,
|
|
326
369
|
type,
|
|
327
|
-
|
|
328
|
-
|
|
370
|
+
status: TAG_STATUS.ERROR,
|
|
371
|
+
statusMsg: translate(translations._PER_TAG_LINK_ERR, 'This shortener is inactivated or removed'),
|
|
329
372
|
};
|
|
330
373
|
}
|
|
331
374
|
};
|
|
@@ -491,6 +534,8 @@ const handlePersonalizeTagPattern = match => {
|
|
|
491
534
|
type: type,
|
|
492
535
|
value: personalizeTag,
|
|
493
536
|
attributeName,
|
|
537
|
+
subAttributeName,
|
|
538
|
+
key: subAttributeName ? `${attributeName}.${subAttributeName}` : attributeName,
|
|
494
539
|
};
|
|
495
540
|
const tag = createTagPattern(tagData);
|
|
496
541
|
return { isValid: true, tag, tagData };
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/// <reference types="yaireo__tagify" />
|
|
2
2
|
import Tagify, { ClassNameSettings, TagData, TagifySettings } from '@yaireo/tagify';
|
|
3
|
-
import { EMOJI_COLLECTIONS, PATTERN_CACHE_TYPE, SHORT_LINK_TYPE, TAG_TYPE } from './constants';
|
|
3
|
+
import { EMOJI_COLLECTIONS, PATTERN_CACHE_TYPE, SHORT_LINK_TYPE, TAG_COLOR, TAG_STATUS, TAG_TYPE } from './constants';
|
|
4
4
|
import { type CSSProperties } from 'react';
|
|
5
|
+
export type TagType = (typeof TAG_TYPE)[keyof typeof TAG_TYPE];
|
|
6
|
+
export type TagTypeProperty = Exclude<TagType, 'detect_link' | 'emoji' | 'shortlink'>;
|
|
7
|
+
export type TagProperty = {
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
displayName: string;
|
|
10
|
+
type: TagTypeProperty;
|
|
11
|
+
};
|
|
12
|
+
export type TagProperties = Record<string, TagProperty>;
|
|
13
|
+
export type TagAttribute = [string, string];
|
|
14
|
+
export type TagStatus = (typeof TAG_STATUS)[keyof typeof TAG_STATUS];
|
|
5
15
|
export type MapAttributesProps = Record<string, Record<string, any>>;
|
|
6
16
|
export type StatusType = 'error' | 'success' | 'warning';
|
|
17
|
+
export type BackgroundColorPersonalizeType = Exclude<keyof typeof TAG_COLOR, 'detect_link' | 'emoji' | 'shortlink'>;
|
|
7
18
|
/**
|
|
8
19
|
* Interface defining the properties for the Tagify input component.
|
|
9
20
|
* Provides configuration options and event handlers to manage Tagify's behavior and appearance.
|
|
@@ -27,6 +38,11 @@ export interface TagifyInputProps {
|
|
|
27
38
|
* @default true
|
|
28
39
|
*/
|
|
29
40
|
realtime?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Defines the custom properties associated with tags.
|
|
43
|
+
* Allows for additional customization of tag attributes, labels, and types.
|
|
44
|
+
*/
|
|
45
|
+
tagProperties?: TagProperties;
|
|
30
46
|
/**
|
|
31
47
|
* Optional mapping configuration for custom attributes associated with tags.
|
|
32
48
|
* Defines how tag attributes are mapped and processed internally.
|
|
@@ -118,6 +134,11 @@ export interface TagifyInputProps {
|
|
|
118
134
|
* Receives the tag detail as parameter, allowing custom actions on tag click.
|
|
119
135
|
*/
|
|
120
136
|
onTagClick?: (tagDetail: Tagify.ClickEventData<TagDataCustomize>) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Event handler triggered when a tag is removed.
|
|
139
|
+
* Receives the tag detail as parameter, allowing custom actions on tag removal.
|
|
140
|
+
*/
|
|
141
|
+
onTagRemove?: (tagDetail: Tagify.RemoveEventData<TagDataCustomize>) => void;
|
|
121
142
|
/**
|
|
122
143
|
* Event handler triggered when the input value changes.
|
|
123
144
|
* Receives the updated input value as a string, allowing for controlled component updates.
|
|
@@ -136,7 +157,6 @@ export interface TagifyInputRef {
|
|
|
136
157
|
onReload: (newValue: string) => void;
|
|
137
158
|
}
|
|
138
159
|
export type EmojiCollection = (typeof EMOJI_COLLECTIONS)[keyof typeof EMOJI_COLLECTIONS];
|
|
139
|
-
export type TagType = (typeof TAG_TYPE)[keyof typeof TAG_TYPE];
|
|
140
160
|
export type ShortLinkType = (typeof SHORT_LINK_TYPE)[keyof typeof SHORT_LINK_TYPE];
|
|
141
161
|
export type PatternCacheType = (typeof PATTERN_CACHE_TYPE)[keyof typeof PATTERN_CACHE_TYPE];
|
|
142
162
|
export type PatterTagName = Exclude<PatternCacheType, 'shortlink_pattern' | 'unsubscribe_pattern'>;
|
|
@@ -145,8 +165,9 @@ export interface TagDataText extends TagData {
|
|
|
145
165
|
value: string;
|
|
146
166
|
label: string;
|
|
147
167
|
type: TagType;
|
|
168
|
+
bgColorPersonalizeType?: BackgroundColorPersonalizeType;
|
|
148
169
|
}
|
|
149
|
-
export interface TagDataEmoji extends Omit<TagDataText, 'type'> {
|
|
170
|
+
export interface TagDataEmoji extends Omit<TagDataText, 'type' | 'bgColorPersonalizeType'> {
|
|
150
171
|
value: string;
|
|
151
172
|
type: Extract<TagType, 'emoji'>;
|
|
152
173
|
collection: EmojiCollection;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="yaireo__tagify" />
|
|
2
2
|
import Tagify from '@yaireo/tagify';
|
|
3
|
-
import { AcceptablePattern, EmojiCollection, EmojiTag, TagDataCustomize, TagType } from './types';
|
|
3
|
+
import { AcceptablePattern, TagAttribute, EmojiCollection, EmojiTag, TagDataCustomize, TagProperty, TagType } from './types';
|
|
4
4
|
/**
|
|
5
5
|
* Parses the input string and replaces matching patterns with processed tags.
|
|
6
6
|
* This function iterates over predefined regex patterns and replaces each match
|
|
@@ -47,6 +47,12 @@ export declare const emojiManufacturer: (text: string, collectionType: EmojiColl
|
|
|
47
47
|
export declare const getEmojiTag: ({ src, emoji, code }: EmojiTag) => string;
|
|
48
48
|
export declare const isPersonalizeTagType: (type: TagType) => boolean;
|
|
49
49
|
export declare const isShortLinkTagType: (type: TagType) => boolean;
|
|
50
|
+
export declare const isCustomTagType: (type: TagType) => boolean;
|
|
51
|
+
export declare const sanitizeTagAttributes: (tagElement: HTMLElement) => void;
|
|
52
|
+
export declare const applyTagAttributes: (element: HTMLElement, attributes: TagAttribute[]) => void;
|
|
53
|
+
export declare const getStatusTagAttributes: (statusMsg: string) => Record<string, TagAttribute[]>;
|
|
54
|
+
export declare const getTagContentAttributes: (propertyType: string) => TagAttribute[];
|
|
55
|
+
export declare const getTagAttributes: (property: TagProperty) => TagAttribute[];
|
|
50
56
|
export declare const isUnsubscribeTagType: (type: TagType) => boolean;
|
|
51
57
|
export declare const generateTagContent: (params: {
|
|
52
58
|
tagData: TagDataCustomize;
|
|
@@ -196,3 +202,6 @@ export declare const getCurrentSelectionAndCloneRange: () => {
|
|
|
196
202
|
};
|
|
197
203
|
export declare const handleTextNodeBackspace: (range: Range) => void;
|
|
198
204
|
export declare const handleEnterWithNextTag: (range: Range) => void;
|
|
205
|
+
export declare function preventUndoRedo(e: CustomEvent<Tagify.KeydownEventData<TagDataCustomize>>['detail']['event'], { disableRedo }?: {
|
|
206
|
+
disableRedo?: boolean | undefined;
|
|
207
|
+
}): void;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// Libraries
|
|
2
2
|
import stringReplaceToArray from 'string-replace-to-array';
|
|
3
3
|
// Constants
|
|
4
|
-
import { EMOJI_COLLECTIONS, PREFIX_PATTERN_LINE_MESSAGE,
|
|
4
|
+
import { EMOJI_COLLECTIONS, PREFIX_PATTERN_LINE_MESSAGE, SHORT_LINK_V2, TAG_CUSTOM_ATTRIBUTES, TAG_STATUS, TAG_TYPE, UNSUBSCRIBE_WHATSAPP, } from './constants';
|
|
5
5
|
import { iconsViber } from './iconsViber';
|
|
6
6
|
// Utils
|
|
7
7
|
import { acceptablePatternChecking, detectURLRegex, getCachedRegex, patternHandlers, tagRegexStringPattern, } from './patternHandlers';
|
|
8
|
-
const { CUSTOMER, VISITOR, EVENT, JOURNEY, CAMPAIGN, VARIANT, PROMOTION_CODE, CUSTOM_FN, OBJECT_WIDGET, CONTENT_SOURCE_GROUP, } = TAG_TYPE;
|
|
8
|
+
const { CUSTOMER, VISITOR, EVENT, JOURNEY, CAMPAIGN, VARIANT, PROMOTION_CODE, CUSTOM_FN, OBJECT_WIDGET, CONTENT_SOURCE_GROUP, ALLOCATED_CODE, CUSTOM_TAG, } = TAG_TYPE;
|
|
9
|
+
const { PREPARING_ST, READONLY_TAG, INVALID_TAG, MESSAGE_TAG, ERROR_TAG, WARNING_TAG, PRIORITY_COLOR_TYPE, BG_COLOR_PERSONALIZE_TYPE, BG_COLOR_PERSONALIZE_TYPE_V2, } = TAG_CUSTOM_ATTRIBUTES;
|
|
10
|
+
const { REMOVED, ARCHIVED, INACTIVE, INVALID, EXPIRED, WARNING, DO_NOT_VIEW, ERROR } = TAG_STATUS;
|
|
9
11
|
/*
|
|
10
12
|
* Custom error type for JSON parse errors
|
|
11
13
|
*/
|
|
@@ -400,13 +402,76 @@ export const isPersonalizeTagType = (type) => [
|
|
|
400
402
|
OBJECT_WIDGET,
|
|
401
403
|
CUSTOM_FN,
|
|
402
404
|
CONTENT_SOURCE_GROUP,
|
|
405
|
+
ALLOCATED_CODE,
|
|
406
|
+
// CUSTOM_TAG,
|
|
403
407
|
].includes(type);
|
|
404
408
|
export const isShortLinkTagType = (type) => [SHORT_LINK_V2].includes(type);
|
|
409
|
+
export const isCustomTagType = (type) => type === CUSTOM_TAG;
|
|
410
|
+
export const sanitizeTagAttributes = (tagElement) => {
|
|
411
|
+
const attributesToRemove = [INVALID_TAG, ERROR_TAG, WARNING_TAG, READONLY_TAG, MESSAGE_TAG];
|
|
412
|
+
attributesToRemove.forEach(attr => tagElement.removeAttribute(attr));
|
|
413
|
+
};
|
|
414
|
+
export const applyTagAttributes = (element, attributes) => {
|
|
415
|
+
attributes.forEach(([attr, value]) => element.setAttribute(attr, value));
|
|
416
|
+
};
|
|
417
|
+
export const getStatusTagAttributes = (statusMsg) => {
|
|
418
|
+
const statusAttributes = {
|
|
419
|
+
error: [
|
|
420
|
+
[ERROR_TAG, 'true'],
|
|
421
|
+
[MESSAGE_TAG, statusMsg],
|
|
422
|
+
],
|
|
423
|
+
warning: [
|
|
424
|
+
[WARNING_TAG, 'true'],
|
|
425
|
+
[MESSAGE_TAG, statusMsg],
|
|
426
|
+
],
|
|
427
|
+
invalid: [
|
|
428
|
+
[READONLY_TAG, 'true'],
|
|
429
|
+
[INVALID_TAG, 'true'],
|
|
430
|
+
[MESSAGE_TAG, statusMsg],
|
|
431
|
+
],
|
|
432
|
+
};
|
|
433
|
+
return statusAttributes;
|
|
434
|
+
};
|
|
435
|
+
export const getTagContentAttributes = (propertyType) => [
|
|
436
|
+
[`data-${PRIORITY_COLOR_TYPE}`, propertyType],
|
|
437
|
+
[`data-${BG_COLOR_PERSONALIZE_TYPE}`, propertyType],
|
|
438
|
+
];
|
|
439
|
+
export const getTagAttributes = (property) => {
|
|
440
|
+
const { status, statusMsg, type } = property;
|
|
441
|
+
const attributes = [[BG_COLOR_PERSONALIZE_TYPE_V2, type]];
|
|
442
|
+
if (!statusMsg)
|
|
443
|
+
return attributes;
|
|
444
|
+
const statusAttributes = getStatusTagAttributes(statusMsg);
|
|
445
|
+
switch (status) {
|
|
446
|
+
case REMOVED:
|
|
447
|
+
case ARCHIVED:
|
|
448
|
+
case EXPIRED:
|
|
449
|
+
case ERROR:
|
|
450
|
+
case INACTIVE:
|
|
451
|
+
attributes.push(...statusAttributes.error);
|
|
452
|
+
break;
|
|
453
|
+
case WARNING:
|
|
454
|
+
case DO_NOT_VIEW:
|
|
455
|
+
attributes.push(...statusAttributes.warning);
|
|
456
|
+
break;
|
|
457
|
+
case INVALID:
|
|
458
|
+
attributes.push(...statusAttributes.invalid);
|
|
459
|
+
break;
|
|
460
|
+
default: {
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return attributes;
|
|
465
|
+
};
|
|
405
466
|
export const isUnsubscribeTagType = (type) => [UNSUBSCRIBE_WHATSAPP].includes(type);
|
|
406
467
|
export const generateTagContent = (params) => {
|
|
407
468
|
const { tagData, content } = params;
|
|
408
469
|
let dataAttrsString = '';
|
|
409
470
|
const dataAttrs = new Map([['tag-type', tagData.type]]);
|
|
471
|
+
if (tagData.bgColorPersonalizeType) {
|
|
472
|
+
dataAttrs.set(PRIORITY_COLOR_TYPE, tagData.bgColorPersonalizeType);
|
|
473
|
+
dataAttrs.set(BG_COLOR_PERSONALIZE_TYPE, tagData.bgColorPersonalizeType);
|
|
474
|
+
}
|
|
410
475
|
if (tagData.type === TAG_TYPE.SHORT_LINK) {
|
|
411
476
|
const { shortlinkType } = tagData;
|
|
412
477
|
dataAttrs.set(`tag-${TAG_TYPE.SHORT_LINK}-type`, shortlinkType);
|
|
@@ -420,7 +485,7 @@ export const generateTagContent = (params) => {
|
|
|
420
485
|
dataAttrsString = dataAttrsString.concat(` data-${key}="${value}"`);
|
|
421
486
|
});
|
|
422
487
|
return `
|
|
423
|
-
<div ${dataAttrsString}>
|
|
488
|
+
<div ${dataAttrsString} class="tagify__tag-content">
|
|
424
489
|
${content}
|
|
425
490
|
</div>
|
|
426
491
|
`;
|
|
@@ -553,9 +618,12 @@ export function isTagClickable(tagify, tag, tagData) {
|
|
|
553
618
|
return false;
|
|
554
619
|
}
|
|
555
620
|
const isValidType = isValidTagType(type);
|
|
621
|
+
const preparingSetting = tag.getAttribute(PREPARING_ST);
|
|
556
622
|
const readonlyTag = tag.getAttribute(READONLY_TAG);
|
|
623
|
+
const isTagReadonly = readonlyTag && readonlyTag === 'true';
|
|
624
|
+
const isPreparingSetting = preparingSetting && preparingSetting === 'true';
|
|
557
625
|
const { readonly } = tagify.settings;
|
|
558
|
-
return !(readonly ||
|
|
626
|
+
return !(readonly || isTagReadonly || isPreparingSetting || !isValidType);
|
|
559
627
|
}
|
|
560
628
|
/**
|
|
561
629
|
* Finds text nodes within an HTML element that contain URLs.
|
|
@@ -728,3 +796,13 @@ export const handleEnterWithNextTag = (range) => {
|
|
|
728
796
|
return;
|
|
729
797
|
insertZeroWidthSpaceBeforeTag(currentNode);
|
|
730
798
|
};
|
|
799
|
+
export function preventUndoRedo(e, { disableRedo = false } = {}) {
|
|
800
|
+
const key = e.key.toLowerCase();
|
|
801
|
+
const isUndo = (e.ctrlKey || e.metaKey) && key === 'z';
|
|
802
|
+
const isRedo = (disableRedo && (e.ctrlKey || e.metaKey) && key === 'y') ||
|
|
803
|
+
((e.ctrlKey || e.metaKey) && e.shiftKey && key === 'z');
|
|
804
|
+
if (isUndo || isRedo) {
|
|
805
|
+
e.preventDefault();
|
|
806
|
+
e.stopPropagation();
|
|
807
|
+
}
|
|
808
|
+
}
|