@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.
Files changed (44) hide show
  1. package/CHANGELOG.md +92 -63
  2. package/es/components/atoms/SelectAssociatedTag/SelectAssociatedTag.d.ts +5 -0
  3. package/es/components/atoms/SelectAssociatedTag/SelectAssociatedTag.js +15 -0
  4. package/es/components/atoms/SelectAssociatedTag/SelectTag.d.ts +4 -0
  5. package/es/components/atoms/SelectAssociatedTag/SelectTag.js +26 -0
  6. package/es/components/atoms/SelectAssociatedTag/constants.d.ts +11 -0
  7. package/es/components/atoms/SelectAssociatedTag/constants.js +42 -0
  8. package/es/components/atoms/SelectAssociatedTag/index.d.ts +3 -0
  9. package/es/components/atoms/SelectAssociatedTag/index.js +2 -0
  10. package/es/components/atoms/SelectAssociatedTag/styled.d.ts +7 -0
  11. package/es/components/atoms/SelectAssociatedTag/styled.js +60 -0
  12. package/es/components/atoms/SelectAssociatedTag/types.d.ts +76 -0
  13. package/es/components/atoms/SelectAssociatedTag/types.js +1 -0
  14. package/es/components/atoms/index.d.ts +1 -0
  15. package/es/components/atoms/index.js +1 -0
  16. package/es/components/icons/CircleInfoIcon.js +2 -2
  17. package/es/components/icons/LazyIcon/LazyIcon.d.ts +2 -0
  18. package/es/components/icons/LazyIcon/LazyIcon.js +2 -0
  19. package/es/components/molecules/InputSelectAttribute/index.d.ts +25 -0
  20. package/es/components/molecules/InputSelectAttribute/index.js +124 -0
  21. package/es/components/molecules/InputSelectAttribute/styled.d.ts +14 -0
  22. package/es/components/molecules/InputSelectAttribute/styled.js +33 -0
  23. package/es/components/molecules/SelectV2/styled.d.ts +3 -1
  24. package/es/components/molecules/SelectV2/styled.js +2 -2
  25. package/es/components/molecules/TagifyInput/TagifyInput.js +159 -71
  26. package/es/components/molecules/TagifyInput/constants.d.ts +24 -2
  27. package/es/components/molecules/TagifyInput/constants.js +25 -2
  28. package/es/components/molecules/TagifyInput/patternHandlers.d.ts +12 -6
  29. package/es/components/molecules/TagifyInput/patternHandlers.js +88 -43
  30. package/es/components/molecules/TagifyInput/types.d.ts +24 -3
  31. package/es/components/molecules/TagifyInput/utils.d.ts +10 -1
  32. package/es/components/molecules/TagifyInput/utils.js +82 -4
  33. package/es/components/molecules/TagifyInput/utils.style.js +81 -96
  34. package/es/components/molecules/index.d.ts +1 -0
  35. package/es/components/molecules/index.js +1 -0
  36. package/es/components/organism/AccountSharing/AccountSharing.js +18 -10
  37. package/es/components/organism/ActivityTimeline/utils.js +168 -2
  38. package/es/components/organism/LeftMenu/hooks/usePermission.js +1 -1
  39. package/es/components/organism/LeftMenu/utils/index.js +1 -1
  40. package/es/components/organism/TextEditor/TextEditor.js +17 -1
  41. package/es/components/organism/TextEditor/types.d.ts +6 -2
  42. package/es/components/organism/TextEditor/ui/Toolbar/FormattingToolbar.js +11 -6
  43. package/es/utils/cookie.js +9 -0
  44. 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
- isValid: boolean;
6
- message?: string;
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
- export declare const getPersonalizeTagInfo: (originalTag: string, mapAttributes?: MapAttributesProps, mapErrorAttributes?: MapAttributesProps) => TagInfo;
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 = `${attributeName}.${subAttributeName}`;
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
- if (!mapAttributes || (!mapAttributes[type] && !isCsGroup)) {
235
- // return fallback if no mapping
236
- return { type, label: attributeName || type, isValid: false, isRemoved: false };
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
- // Check if the code is exist in the map
247
- if (mapAttributes[type] && attributeName) {
248
- const isExistPromotionPool = has(mapAttributes[type], attributeName);
249
- if (!isExistPromotionPool) {
250
- isValid = false;
251
- message = 'This pool does not exist anymore';
252
- if (mapErrorAttributes &&
253
- mapErrorAttributes[type] &&
254
- mapErrorAttributes[type][attributeName]) {
255
- const { isEdit = false, isView = false, isExist = true, } = mapErrorAttributes[type][attributeName] || {};
256
- // Case Pool removed
257
- if (!isExist) {
258
- isRemoved = !isExist;
259
- message = translate(translations._PERSONALIZATION_TAG_ERR_REMOVED, 'This pool is removed');
260
- }
261
- else if (!isView) {
262
- // Case No permission
263
- hasViewPermission = isView;
264
- message = translate(translations._PERMISSION_ERR_POOL, 'You do not have permission on this pool');
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
- isRemoved,
281
- hasViewPermission,
318
+ status,
319
+ statusMsg,
282
320
  };
283
321
  }
284
322
  catch (error) {
285
323
  console.error('Error in getTagLabel', error);
286
- return { label: originalTag, type: originalTag, isValid: false, isRemoved: false };
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 [isValid, message] = [true, ''];
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
- isValid = false;
299
- message = translate(translations?._PER_TAG_LINK_ERR || '', 'This shortener is inactivated or removed');
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
- isValid = false;
306
- message = translate(translations?._PER_TAG_LINK_ERR || '', 'This shortener is inactivated or removed');
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
- isValid: false,
328
- message: translate('', 'This shortener is inactivated or removed'),
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, READONLY_TAG, SHORT_LINK_V2, TAG_TYPE, UNSUBSCRIBE_WHATSAPP, } from './constants';
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 || (readonlyTag && readonlyTag === 'true') || !isValidType);
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
+ }