@antscorp/antsomi-ui 1.3.5-beta.917 → 1.3.5-beta.919

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.
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import type { PayloadInfo } from '@antscorp/antsomi-ui/es/types';
3
2
  export type TDisplayFormat = 'number' | 'percentage' | 'currency' | 'datetime';
4
3
  type DisplayFormatProps = {
@@ -16,13 +16,13 @@ import '@yaireo/tagify/dist/tagify.css';
16
16
  // Styled
17
17
  import { TagTextArea, TagifyWrapper, WrapperPlaceHolder } from './styled';
18
18
  // Utils
19
- import { parseTagStringToTagify, convertInputStringToOriginal, emojiManufacturer, getEmojiTag, isPersonalizeTagType, generateTagContent, unescapeString, hasLineBreak, selectRange, isTagClickable, findURLInTextNodes, getAttributesString, isAnchorNodeChildOfElement, } from './utils';
20
- import { acceptablePatternChecking, detectURLRegex, getCachedRegex, getPersonalizeTagInfo, patternHandlers, } from './patternHandlers';
19
+ import { parseTagStringToTagify, convertInputStringToOriginal, emojiManufacturer, getEmojiTag, isPersonalizeTagType, generateTagContent, unescapeString, hasLineBreak, selectRange, isTagClickable, findURLInTextNodes, getAttributesString, isAnchorNodeChildOfElement, isShortLinkTagType, } from './utils';
20
+ import { acceptablePatternChecking, detectURLRegex, getCachedRegex, getPersonalizeTagInfo, getShortLinkTagInfo, patternHandlers, } from './patternHandlers';
21
21
  // Constants
22
- import { DETECT_LINK, EMOJI, FORCE_SHOW_TOOLTIP, INVALID_TAG, MESSAGE_TAG, NO_VIEW_TAG, PERSONALIZE_PTN, PROMOTION_CODE, READONLY_TAG, REMOVED_TAG, SHORT_LINK, SHORT_LINK_PTN, defaultCssVariables, tagifyDefaultProps, } from './constants';
22
+ import { DETECT_LINK, EMOJI, FORCE_SHOW_TOOLTIP, INVALID_TAG, MESSAGE_TAG, NO_VIEW_TAG, PERSONALIZE_PTN, PROMOTION_CODE, READONLY_TAG, REMOVED_TAG, SHORT_LINK, SHORT_LINK_PTN, SHORT_LINK_V2, defaultCssVariables, tagifyDefaultProps, } from './constants';
23
23
  const TagifyInput = forwardRef((props, ref) => {
24
24
  // Props
25
- const { initialValue, escapeHTML, status, readonly, readonlyTag, realtime, disabled, maxLength, maxHeight, minWidth, placeholder, isSingleLineText, acceptableTagPattern, mapAttributes, mapErrorAttributes, maxPersonalizeTags, name, children, cssTagifyVariables, onTagClick, onChange, } = props;
25
+ const { initialValue, escapeHTML, status, readonly, readonlyTag, realtime, disabled, maxLength, maxHeight, minWidth, placeholder, minWidthPlaceholder, isSingleLineText, acceptableTagPattern, mapAttributes, mapErrorAttributes, maxPersonalizeTags, name, children, cssTagifyVariables, onTagClick, onChange, } = props;
26
26
  // States
27
27
  const [isLineBreak, setIsLineBreak] = useState(hasLineBreak(initialValue));
28
28
  const [tooltipRefresher, setTooltipRefresher] = useState(1);
@@ -351,7 +351,7 @@ const TagifyInput = forwardRef((props, ref) => {
351
351
  if (newTag && tagifyRef.current) {
352
352
  const { settings, value: currentTags } = tagifyRef.current;
353
353
  const { readonly, maxTags } = settings;
354
- const currentPersonalizeTags = currentTags.filter(tag => ![EMOJI, SHORT_LINK].includes(tag.type));
354
+ const currentPersonalizeTags = currentTags.filter(tag => ![EMOJI, SHORT_LINK, SHORT_LINK_V2].includes(tag.type));
355
355
  const currentPersonalizeTagsLength = currentPersonalizeTags.length;
356
356
  // Check readonly
357
357
  if (readonly)
@@ -367,7 +367,7 @@ const TagifyInput = forwardRef((props, ref) => {
367
367
  * Validate the max limit before add new tag
368
368
  * For emoji and short link, it will be passed
369
369
  */
370
- if (![EMOJI, SHORT_LINK].includes(type) &&
370
+ if (![EMOJI, SHORT_LINK, SHORT_LINK_V2].includes(type) &&
371
371
  currentPersonalizeTagsLength >= maxTags)
372
372
  return;
373
373
  // Create new tag
@@ -403,7 +403,30 @@ const TagifyInput = forwardRef((props, ref) => {
403
403
  tagifyRef.current.removeAllTags();
404
404
  }
405
405
  },
406
- }), [onInjectTagAtCaret, placeCaretAfterNode]);
406
+ onReload: (newValue) => {
407
+ if (!tagifyRef.current) {
408
+ throw new Error('Tagify instance is not initialized');
409
+ }
410
+ if (!_.isString(newValue)) {
411
+ throw new Error('Reload value should be string');
412
+ }
413
+ if (newValue === '') {
414
+ tagifyRef.current.loadOriginalValues(newValue);
415
+ return;
416
+ }
417
+ if (!escapeHTML) {
418
+ const newContent = parseTagStringToTagify(newValue, acceptableTagPattern);
419
+ tagifyRef.current.loadOriginalValues(newContent);
420
+ }
421
+ else {
422
+ // Sometimes the input value has html tags, it makes the input rendered incorrectly -> it rendered html
423
+ // -> need to escape the html tags to render correctly
424
+ const escapeContent = htmlEntities.escape(newValue);
425
+ const newContent = parseTagStringToTagify(escapeContent, acceptableTagPattern);
426
+ tagifyRef.current.loadOriginalValues(newContent);
427
+ }
428
+ },
429
+ }), [acceptableTagPattern, escapeHTML, onInjectTagAtCaret, placeCaretAfterNode]);
407
430
  const onTagItemClick = useCallback((event) => {
408
431
  event.stopPropagation();
409
432
  event.preventDefault();
@@ -503,6 +526,8 @@ const TagifyInput = forwardRef((props, ref) => {
503
526
  if (tagData) {
504
527
  const { type, value } = tagData;
505
528
  const isPersonalTag = isPersonalizeTagType(type);
529
+ const isShortLinkTag = isShortLinkTagType(type);
530
+ /** Case Personalize */
506
531
  if (isPersonalTag && value) {
507
532
  const isAccepted = acceptablePatternChecking(acceptableType, acceptableTagPattern);
508
533
  // No need to continue if pattern is not accepted
@@ -565,6 +590,45 @@ const TagifyInput = forwardRef((props, ref) => {
565
590
  }
566
591
  }
567
592
  }
593
+ /** Case Short Link V2 Tag */
594
+ if (isShortLinkTag) {
595
+ const isAccepted = acceptablePatternChecking(SHORT_LINK_PTN, acceptableTagPattern);
596
+ if (!isAccepted)
597
+ return;
598
+ const { url, shortener, label } = tagData;
599
+ const { label: tagLabel, isValid, message, type: tagType, } = getShortLinkTagInfo({
600
+ type,
601
+ label,
602
+ shortener,
603
+ url,
604
+ mapAttributes: attributes,
605
+ mapErrorAttributes: errorAttributes,
606
+ });
607
+ const tagTextNode = tagifyRef.current?.getTagTextNode(tagElement);
608
+ /*
609
+ * Just only update to the correct text of the tag
610
+ * NOTE: Do not actually affect raw data
611
+ */
612
+ if (tagTextNode) {
613
+ tagTextNode.textContent = tagLabel;
614
+ // Clear all previous attributes
615
+ tagElement.removeAttribute(REMOVED_TAG);
616
+ tagElement.removeAttribute(NO_VIEW_TAG);
617
+ tagElement.removeAttribute(INVALID_TAG);
618
+ tagElement.removeAttribute(READONLY_TAG);
619
+ tagElement.removeAttribute(MESSAGE_TAG);
620
+ // In case promotion pool has something wrong
621
+ if (!isValid && message) {
622
+ tagElement.setAttribute(REMOVED_TAG, 'true');
623
+ tagElement.setAttribute(MESSAGE_TAG, message);
624
+ tagifyRef.current?.getSetTagData(tagElement, {
625
+ ...tagData,
626
+ status: 'error',
627
+ statusMsg: message,
628
+ });
629
+ }
630
+ }
631
+ }
568
632
  }
569
633
  });
570
634
  setTooltipRefresher(prev => prev + 1);
@@ -755,7 +819,7 @@ const TagifyInput = forwardRef((props, ref) => {
755
819
  detectReplaceURLToTag();
756
820
  }, [detectReplaceURLToTag]);
757
821
  // CAVEAT: Some case need to "FORCE" sync the original values to Tagify instance
758
- useEffect(() => {
822
+ useDeepCompareEffect(() => {
759
823
  if (tagifyRef.current) {
760
824
  const { DOM, settings } = tagifyRef.current;
761
825
  const { empty } = settings.classNames;
@@ -891,7 +955,7 @@ const TagifyInput = forwardRef((props, ref) => {
891
955
  }
892
956
  };
893
957
  }, [tooltipRefresher]);
894
- return (_jsxs(TagifyWrapper, { ref: tagifyWrapperRef, "$cssTagifyVariables": cssVariablesMemoized, className: "tagify-container", id: "tagify-container", "data-test": "tagify-wrapper", "$status": status, "$maxHeight": maxHeight, "$minWidth": minWidth, "$tagifyFullWidth": isLineBreak, "$placeholder": placeholder, "$isSingleLineText": isSingleLineText, "$tagInvalidIcon": iconWarning, "$tagErrorIcon": iconError, onClick: onTagifyWrapperClick, children: [_jsx(TagTextArea, { id: "tagify-textarea", ref: inputRef, name: name, defaultValue: parsedDefaultValue, "data-test": "tagify-input" }), _jsx(WrapperPlaceHolder, { "data-test": "wrapper-placeholder", ref: placeholderRef, "$isShow": !!children, children: children })] }));
958
+ return (_jsxs(TagifyWrapper, { ref: tagifyWrapperRef, "$cssTagifyVariables": cssVariablesMemoized, className: "tagify-container", id: "tagify-container", "data-test": "tagify-wrapper", "$status": status, "$maxHeight": maxHeight, "$minWidth": minWidth, "$minWidthPlaceholder": minWidthPlaceholder, "$tagifyFullWidth": isLineBreak, "$placeholder": placeholder, "$isSingleLineText": isSingleLineText, "$tagInvalidIcon": iconWarning, "$tagErrorIcon": iconError, onClick: onTagifyWrapperClick, children: [_jsx(TagTextArea, { id: "tagify-textarea", ref: inputRef, name: name, defaultValue: parsedDefaultValue, "data-test": "tagify-input" }), _jsx(WrapperPlaceHolder, { "data-test": "wrapper-placeholder", ref: placeholderRef, "$isShow": !!children, children: children })] }));
895
959
  });
896
960
  TagifyInput.defaultProps = tagifyDefaultProps;
897
961
  export default memo(TagifyInput);
@@ -33,11 +33,13 @@ export declare const PATTERN_CACHE_TYPE: {
33
33
  readonly SHORT_LINK_PTN: "shortlink_pattern";
34
34
  readonly SHORT_LINK_INDIVIDUAL_PTN: "shortlink_individual_pattern";
35
35
  readonly SHORT_LINK_GENERAL_PTN: "shortlink_general_pattern";
36
+ readonly SHORT_LINK_V2_INDIVIDUAL_PTN: "shortlink_v2_individual_pattern";
37
+ readonly SHORT_LINK_V2_GENERAL_PTN: "shortlink_v2_general_pattern";
36
38
  readonly LINE_EMOJI_PTN: "line_emoji_pattern";
37
39
  readonly PERSONALIZE_PTN: "personalize_pattern";
38
40
  readonly VIBER_EMOJI_PTN: "viber_emoji_pattern";
39
41
  };
40
- export declare const SHORT_LINK_PTN: "shortlink_pattern", SHORT_LINK_INDIVIDUAL_PTN: "shortlink_individual_pattern", SHORT_LINK_GENERAL_PTN: "shortlink_general_pattern", LINE_EMOJI_PTN: "line_emoji_pattern", PERSONALIZE_PTN: "personalize_pattern", VIBER_EMOJI_PTN: "viber_emoji_pattern";
42
+ export declare const SHORT_LINK_PTN: "shortlink_pattern", SHORT_LINK_INDIVIDUAL_PTN: "shortlink_individual_pattern", SHORT_LINK_GENERAL_PTN: "shortlink_general_pattern", SHORT_LINK_V2_INDIVIDUAL_PTN: "shortlink_v2_individual_pattern", SHORT_LINK_V2_GENERAL_PTN: "shortlink_v2_general_pattern", LINE_EMOJI_PTN: "line_emoji_pattern", PERSONALIZE_PTN: "personalize_pattern", VIBER_EMOJI_PTN: "viber_emoji_pattern";
41
43
  export declare const DEFAULT_ACCEPT_TAGS: ("shortlink_pattern" | "line_emoji_pattern" | "personalize_pattern" | "viber_emoji_pattern")[];
42
44
  export declare const tagifyDefaultProps: TagifyInputProps;
43
45
  export declare const TAG_TYPE: {
@@ -52,14 +54,19 @@ export declare const TAG_TYPE: {
52
54
  readonly CUSTOM_FN: "custom";
53
55
  readonly EMOJI: "emoji";
54
56
  readonly SHORT_LINK: "shortlink";
57
+ readonly SHORT_LINK_V2: "shortlink_v2";
55
58
  readonly DETECT_LINK: "detect_link";
56
59
  readonly CONTENT_SOURCE_GROUP: "groups";
57
60
  };
58
- export declare const CUSTOMER: "customer", VISITOR: "visitor", EVENT: "event", JOURNEY: "story", CAMPAIGN: "campaign", VARIANT: "variant", PROMOTION_CODE: "promotion_code", CUSTOM_FN: "custom", EMOJI: "emoji", DETECT_LINK: "detect_link", SHORT_LINK: "shortlink", OBJECT_WIDGET: "objectWidget", CONTENT_SOURCE_GROUP: "groups";
61
+ export declare const CUSTOMER: "customer", VISITOR: "visitor", EVENT: "event", JOURNEY: "story", CAMPAIGN: "campaign", VARIANT: "variant", PROMOTION_CODE: "promotion_code", CUSTOM_FN: "custom", EMOJI: "emoji", DETECT_LINK: "detect_link", SHORT_LINK: "shortlink", SHORT_LINK_V2: "shortlink_v2", OBJECT_WIDGET: "objectWidget", CONTENT_SOURCE_GROUP: "groups";
59
62
  export declare const SHORT_LINK_TYPE: {
60
63
  readonly INDIVIDUAL: "shortlink";
61
64
  readonly GENERAL: "shortlink_static";
62
65
  };
66
+ export declare const SHORT_LINK_TYPE_V2: {
67
+ readonly INDIVIDUAL: "shortlink_v2";
68
+ readonly GENERAL: "shortlink_v2_static";
69
+ };
63
70
  export declare const TAG_COLOR: {
64
71
  readonly customer: string | undefined;
65
72
  readonly detect_link: "#e8feca";
@@ -67,6 +74,10 @@ export declare const TAG_COLOR: {
67
74
  readonly shortlink: "#CAFEDD";
68
75
  readonly shortlink_static: "#EFE2D9";
69
76
  };
77
+ readonly shortlink_v2: {
78
+ readonly shortlink: "#CAFEDD";
79
+ readonly shortlink_static: "#EFE2D9";
80
+ };
70
81
  readonly visitor: "#e8feca";
71
82
  readonly event: "#fecaca";
72
83
  readonly story: "#FAFAAF";
@@ -34,11 +34,13 @@ export const PATTERN_CACHE_TYPE = {
34
34
  SHORT_LINK_PTN: 'shortlink_pattern',
35
35
  SHORT_LINK_INDIVIDUAL_PTN: 'shortlink_individual_pattern',
36
36
  SHORT_LINK_GENERAL_PTN: 'shortlink_general_pattern',
37
+ SHORT_LINK_V2_INDIVIDUAL_PTN: 'shortlink_v2_individual_pattern',
38
+ SHORT_LINK_V2_GENERAL_PTN: 'shortlink_v2_general_pattern',
37
39
  LINE_EMOJI_PTN: 'line_emoji_pattern',
38
40
  PERSONALIZE_PTN: 'personalize_pattern',
39
41
  VIBER_EMOJI_PTN: 'viber_emoji_pattern',
40
42
  };
41
- export const { SHORT_LINK_PTN, SHORT_LINK_INDIVIDUAL_PTN, SHORT_LINK_GENERAL_PTN, LINE_EMOJI_PTN, PERSONALIZE_PTN, VIBER_EMOJI_PTN, } = PATTERN_CACHE_TYPE;
43
+ export const { SHORT_LINK_PTN, SHORT_LINK_INDIVIDUAL_PTN, SHORT_LINK_GENERAL_PTN, SHORT_LINK_V2_INDIVIDUAL_PTN, SHORT_LINK_V2_GENERAL_PTN, LINE_EMOJI_PTN, PERSONALIZE_PTN, VIBER_EMOJI_PTN, } = PATTERN_CACHE_TYPE;
42
44
  export const DEFAULT_ACCEPT_TAGS = [
43
45
  SHORT_LINK_PTN,
44
46
  PERSONALIZE_PTN,
@@ -51,6 +53,7 @@ export const tagifyDefaultProps = {
51
53
  realtime: true,
52
54
  maxHeight: 266,
53
55
  placeholder: undefined,
56
+ minWidthPlaceholder: 130,
54
57
  acceptableTagPattern: DEFAULT_ACCEPT_TAGS,
55
58
  onChange: () => { },
56
59
  };
@@ -66,14 +69,19 @@ export const TAG_TYPE = {
66
69
  CUSTOM_FN: 'custom',
67
70
  EMOJI: 'emoji',
68
71
  SHORT_LINK: 'shortlink',
72
+ SHORT_LINK_V2: 'shortlink_v2',
69
73
  DETECT_LINK: 'detect_link',
70
74
  CONTENT_SOURCE_GROUP: 'groups',
71
75
  };
72
- export const { CUSTOMER, VISITOR, EVENT, JOURNEY, CAMPAIGN, VARIANT, PROMOTION_CODE, CUSTOM_FN, EMOJI, DETECT_LINK, SHORT_LINK, OBJECT_WIDGET, CONTENT_SOURCE_GROUP, } = TAG_TYPE;
76
+ 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, } = TAG_TYPE;
73
77
  export const SHORT_LINK_TYPE = {
74
78
  INDIVIDUAL: 'shortlink', // Individual link
75
79
  GENERAL: 'shortlink_static', // General link
76
80
  };
81
+ export const SHORT_LINK_TYPE_V2 = {
82
+ INDIVIDUAL: 'shortlink_v2', // Individual link
83
+ GENERAL: 'shortlink_v2_static', // General link
84
+ };
77
85
  export const TAG_COLOR = {
78
86
  [CUSTOMER]: globalToken?.blue2,
79
87
  [DETECT_LINK]: '#e8feca',
@@ -81,6 +89,10 @@ export const TAG_COLOR = {
81
89
  [SHORT_LINK_TYPE.INDIVIDUAL]: '#CAFEDD',
82
90
  [SHORT_LINK_TYPE.GENERAL]: '#EFE2D9',
83
91
  },
92
+ [SHORT_LINK_V2]: {
93
+ [SHORT_LINK_TYPE.INDIVIDUAL]: '#CAFEDD',
94
+ [SHORT_LINK_TYPE.GENERAL]: '#EFE2D9',
95
+ },
84
96
  [VISITOR]: '#e8feca',
85
97
  [EVENT]: '#fecaca',
86
98
  [JOURNEY]: '#FAFAAF',
@@ -19,5 +19,13 @@ export declare const detectURLRegex: RegExp;
19
19
  export declare const tagRegexStringPattern = "\\[\\[({.*?})\\]\\]";
20
20
  export declare function acceptablePatternChecking(pattern: AcceptablePattern, acceptablePattern: Array<AcceptablePattern>): boolean;
21
21
  export declare const getPersonalizeTagInfo: (originalTag: string, mapAttributes?: MapAttributesProps, mapErrorAttributes?: MapAttributesProps) => TagInfo;
22
+ export declare const getShortLinkTagInfo: (params: {
23
+ type: string;
24
+ label: string;
25
+ url: string;
26
+ shortener: string;
27
+ mapAttributes?: MapAttributesProps;
28
+ mapErrorAttributes?: MapAttributesProps;
29
+ }) => TagInfo;
22
30
  export declare const patternHandlers: Record<PatterTagName, PatternHandlerWrapper>;
23
31
  export {};
@@ -2,12 +2,13 @@
2
2
  /* eslint-disable no-console */
3
3
  // Libraries
4
4
  import { has } from 'lodash';
5
+ import { translate, translations } from '@antscorp/antsomi-locales';
5
6
  // Utils
6
7
  import { errorWrapper } from './errorWrapper';
7
8
  import { isViberEmoji } from './iconsViber';
8
9
  import { random } from '@antscorp/antsomi-ui/es/utils';
9
10
  // Constants
10
- 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, VIBER_EMOJI_PTN, } from './constants';
11
+ 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, } from './constants';
11
12
  /*
12
13
  * Usage to cache compiled regular expressions:
13
14
  * const regex = getCachedRegex(pattern, flags);
@@ -254,12 +255,12 @@ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttrib
254
255
  // Case Pool removed
255
256
  if (!isExist) {
256
257
  isRemoved = !isExist;
257
- message = 'This pool is removed';
258
+ message = translate(translations._PERSONALIZATION_TAG_ERR_REMOVED, 'This pool is removed');
258
259
  }
259
260
  else if (!isView) {
260
261
  // Case No permission
261
262
  hasViewPermission = isView;
262
- message = 'You do not have permission on this pool';
263
+ message = translate(translations._PERMISSION_ERR_POOL, 'You do not have permission on this pool');
263
264
  }
264
265
  }
265
266
  }
@@ -284,6 +285,49 @@ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttrib
284
285
  return { label: originalTag, type: originalTag, isValid: false, isRemoved: false };
285
286
  }
286
287
  };
288
+ export const getShortLinkTagInfo = (params) => {
289
+ const { type, label, url, shortener, mapAttributes, mapErrorAttributes } = params;
290
+ try {
291
+ let [isValid, message] = [true, ''];
292
+ switch (type) {
293
+ case SHORT_LINK_V2:
294
+ if (mapAttributes && mapAttributes[type]) {
295
+ const isExistShortLink = has(mapAttributes[type], shortener);
296
+ if (!isExistShortLink) {
297
+ isValid = false;
298
+ message = translate('', 'This shortener is inactivated or removed');
299
+ if (mapErrorAttributes &&
300
+ mapErrorAttributes?.[type] &&
301
+ mapErrorAttributes?.[type]?.[shortener]) {
302
+ const { isView = true, isExist = true } = mapErrorAttributes[type][shortener] || {};
303
+ if (!isExist || !isView) {
304
+ isValid = false;
305
+ message = translate('', 'This shortener is inactivated or removed');
306
+ }
307
+ }
308
+ }
309
+ }
310
+ break;
311
+ default:
312
+ break;
313
+ }
314
+ return {
315
+ type,
316
+ message,
317
+ isValid,
318
+ label,
319
+ };
320
+ }
321
+ catch (error) {
322
+ console.error('Error in getTagLabel', error);
323
+ return {
324
+ label,
325
+ type,
326
+ isValid: false,
327
+ message: translate('', 'This shortener is inactivated or removed'),
328
+ };
329
+ }
330
+ };
287
331
  const createTagPattern = (tagInfo) => `[[${JSON.stringify(tagInfo)}]]`;
288
332
  const generateShortlinkLabel = (params) => {
289
333
  const { type } = params;
@@ -294,6 +338,12 @@ const generateShortlinkLabel = (params) => {
294
338
  case SHORT_LINK_TYPE.GENERAL: {
295
339
  return 'General Shortlink';
296
340
  }
341
+ // case SHORT_LINK_TYPE_V2.INDIVIDUAL: {
342
+ // return 'Individual Shortlink V2';
343
+ // }
344
+ // case SHORT_LINK_TYPE_V2.GENERAL: {
345
+ // return 'General Shortlink V2';
346
+ // }
297
347
  default: {
298
348
  const randomId = random(5);
299
349
  return `https://ants.ly/${randomId}`;
@@ -457,6 +507,81 @@ const handleViberPattern = match => {
457
507
  const tag = createTagPattern(tagData);
458
508
  return { isValid, tag, tagData };
459
509
  };
510
+ /*
511
+ * Function to handle #{shortlink_v2(...)} pattern
512
+ *
513
+ */
514
+ const handleShortlinkV2IndividualPattern = match => {
515
+ const [fullMatch, type, shortener, url = ''] = match;
516
+ const label = generateShortlinkLabel({ type: SHORT_LINK_TYPE.INDIVIDUAL });
517
+ const urlForValidate = url?.replace(new RegExp(PERSONALIZE_PTN_PATTERN, 'g'), 'personalize_pattern');
518
+ const isValid = isValidUrl(urlForValidate, {
519
+ protocols: ['https:'],
520
+ requireTld: false,
521
+ allowFragment: true,
522
+ requireFragment: false,
523
+ allowNumericTld: true,
524
+ allowUnderscores: true,
525
+ allowTrailingDot: true,
526
+ allowIp: true,
527
+ });
528
+ // Validate the URL inside the shortlink pattern
529
+ if (!isValid) {
530
+ console.error(`Invalid URL detected in shortlink individual: Full match: ${fullMatch} - URL: ${url} - Validate URL: ${urlForValidate}`);
531
+ return {
532
+ isValid,
533
+ tag: '[[Invalid URL]]',
534
+ tagData: undefined,
535
+ };
536
+ }
537
+ const tagData = {
538
+ label,
539
+ type: SHORT_LINK_V2,
540
+ shortlinkType: SHORT_LINK_TYPE.INDIVIDUAL,
541
+ value: fullMatch,
542
+ shortener,
543
+ url,
544
+ };
545
+ const tag = createTagPattern(tagData);
546
+ return { isValid, tag, tagData };
547
+ };
548
+ /*
549
+ * Function to handle #{shortlink_v2_static(...)} pattern
550
+ *
551
+ */
552
+ const handleShortlinkV2GeneralPattern = match => {
553
+ const [fullMatch, type, shortener, url] = match;
554
+ const label = generateShortlinkLabel({ type: SHORT_LINK_TYPE.GENERAL });
555
+ const isValid = isValidUrl(url, {
556
+ protocols: ['https:'],
557
+ requireTld: false,
558
+ allowFragment: true,
559
+ requireFragment: false,
560
+ allowNumericTld: true,
561
+ allowUnderscores: true,
562
+ allowTrailingDot: true,
563
+ allowIp: true,
564
+ });
565
+ // Validate the URL inside the shortlink general pattern
566
+ if (!isValid) {
567
+ console.error(`Invalid URL detected in shortlink general: fullMatch:: ${fullMatch}`);
568
+ return {
569
+ isValid,
570
+ tag: '[[Invalid URL]]',
571
+ tagData: undefined,
572
+ };
573
+ }
574
+ const tagData = {
575
+ label,
576
+ type: SHORT_LINK_V2,
577
+ shortlinkType: SHORT_LINK_TYPE.GENERAL,
578
+ value: fullMatch,
579
+ shortener,
580
+ url,
581
+ };
582
+ const tag = createTagPattern(tagData);
583
+ return { isValid, tag, tagData };
584
+ };
460
585
  // Map of regex patterns to their respective wrapped handlers
461
586
  export const patternHandlers = {
462
587
  /*
@@ -477,6 +602,19 @@ export const patternHandlers = {
477
602
  acceptablePattern: SHORT_LINK_PTN,
478
603
  handler: errorWrapper(handleShortlinkGeneralPattern),
479
604
  },
605
+ [SHORT_LINK_V2_INDIVIDUAL_PTN]: {
606
+ pattern: '#\\{(shortlink_v2)\\(([^|]+)\\|\\s*([^)]+)\\)\\}',
607
+ // pattern: '#\\{shortlink_v2\\([^()]+?\\)\\}(?!_static)',
608
+ name: SHORT_LINK_V2_INDIVIDUAL_PTN, // Used to cache the regex, please keep the name unique for each pattern
609
+ acceptablePattern: SHORT_LINK_PTN,
610
+ handler: errorWrapper(handleShortlinkV2IndividualPattern),
611
+ },
612
+ [SHORT_LINK_V2_GENERAL_PTN]: {
613
+ pattern: '#\\{(shortlink_static_v2)\\(([^|]+)\\|\\s*([^)]+)\\)\\}',
614
+ name: SHORT_LINK_V2_GENERAL_PTN, // Used to cache the regex, please keep the name unique for each pattern
615
+ acceptablePattern: SHORT_LINK_PTN,
616
+ handler: errorWrapper(handleShortlinkV2GeneralPattern),
617
+ },
480
618
  /*
481
619
  * NOTE: Line pattern with strict boundaries to ensure it matches only the intended format.
482
620
  */
@@ -82,6 +82,13 @@ export interface TagifyInputProps {
82
82
  * Defines the minimum width of the input.
83
83
  */
84
84
  minWidth?: CSSProperties['minWidth'];
85
+ /**
86
+ * Defines the minimum width of the placeholder.
87
+ * Used for the placeholder when the input is empty.
88
+ *
89
+ * @default 130px
90
+ */
91
+ minWidthPlaceholder?: CSSProperties['minWidth'];
85
92
  /**
86
93
  * Defines the status of the input, used for styling and validation.
87
94
  */
@@ -122,6 +129,7 @@ export interface TagifyInputProps {
122
129
  export interface TagifyInputRef {
123
130
  onAddNewTag: (newTag: TagDataCustomize | string) => void;
124
131
  onReplaceTag: (currentTagEle: HTMLElement, newTag: TagDataCustomize) => void;
132
+ onReload: (newValue: string) => void;
125
133
  }
126
134
  export type EmojiCollection = (typeof EMOJI_COLLECTIONS)[keyof typeof EMOJI_COLLECTIONS];
127
135
  export type TagType = (typeof TAG_TYPE)[keyof typeof TAG_TYPE];
@@ -141,7 +149,7 @@ export interface TagDataEmoji extends Omit<TagDataText, 'type'> {
141
149
  }
142
150
  export interface TagDataShortLink extends Omit<TagDataText, 'type'> {
143
151
  value: string;
144
- type: Extract<TagType, 'shortlink'>;
152
+ type: Extract<TagType, 'shortlink' | 'shortlink_v2'>;
145
153
  shortlinkType: ShortLinkType;
146
154
  }
147
155
  export type TagDataCustomize = TagDataEmoji | TagDataText | TagDataShortLink;
@@ -181,6 +189,7 @@ export interface TagifyWrapperProps {
181
189
  $status?: StatusType;
182
190
  $maxHeight?: number;
183
191
  $minWidth?: CSSProperties['minWidth'];
192
+ $minWidthPlaceholder?: TagifyInputProps['minWidthPlaceholder'];
184
193
  $tagifyFullWidth?: boolean;
185
194
  $tagInvalidIcon?: any;
186
195
  $tagErrorIcon?: any;
@@ -46,6 +46,7 @@ export declare const getImageSourceViberEmoji: (fileName?: string) => any;
46
46
  export declare const emojiManufacturer: (text: string, collectionType: EmojiCollection) => string[];
47
47
  export declare const getEmojiTag: ({ src, emoji, code }: EmojiTag) => string;
48
48
  export declare const isPersonalizeTagType: (type: TagType) => boolean;
49
+ export declare const isShortLinkTagType: (type: TagType) => boolean;
49
50
  export declare const generateTagContent: (params: {
50
51
  tagData: TagDataCustomize;
51
52
  content: string;
@@ -1,7 +1,7 @@
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, TAG_TYPE, } from './constants';
4
+ import { EMOJI_COLLECTIONS, PREFIX_PATTERN_LINE_MESSAGE, READONLY_TAG, SHORT_LINK_V2, TAG_TYPE, } from './constants';
5
5
  import { iconsViber } from './iconsViber';
6
6
  // Utils
7
7
  import { acceptablePatternChecking, detectURLRegex, getCachedRegex, patternHandlers, tagRegexStringPattern, } from './patternHandlers';
@@ -401,6 +401,7 @@ export const isPersonalizeTagType = (type) => [
401
401
  CUSTOM_FN,
402
402
  CONTENT_SOURCE_GROUP,
403
403
  ].includes(type);
404
+ export const isShortLinkTagType = (type) => [SHORT_LINK_V2].includes(type);
404
405
  export const generateTagContent = (params) => {
405
406
  const { tagData, content } = params;
406
407
  let dataAttrsString = '';
@@ -409,6 +410,11 @@ export const generateTagContent = (params) => {
409
410
  const { shortlinkType } = tagData;
410
411
  dataAttrs.set(`tag-${TAG_TYPE.SHORT_LINK}-type`, shortlinkType);
411
412
  }
413
+ /** SHORT_LINK_V2 */
414
+ if (tagData.type === TAG_TYPE.SHORT_LINK_V2) {
415
+ const { shortlinkType } = tagData;
416
+ dataAttrs.set(`tag-${TAG_TYPE.SHORT_LINK_V2}-type`, shortlinkType);
417
+ }
412
418
  dataAttrs.forEach((value, key) => {
413
419
  dataAttrsString = dataAttrsString.concat(` data-${key}="${value}"`);
414
420
  });
@@ -1,6 +1,6 @@
1
1
  import type { StatusType, TagifyWrapperProps } from './types';
2
2
  export declare const getTagifyStyled: ({ $maxHeight, $tagifyFullWidth }: TagifyWrapperProps) => import("styled-components").FlattenSimpleInterpolation;
3
- export declare const getTagifyInputStyled: ({ $minWidth, $placeholder, $isSingleLineText, }: TagifyWrapperProps) => import("styled-components").FlattenSimpleInterpolation;
3
+ export declare const getTagifyInputStyled: ({ $minWidth, $placeholder, $minWidthPlaceholder, $isSingleLineText, }: TagifyWrapperProps) => import("styled-components").FlattenSimpleInterpolation;
4
4
  export declare const getStyledTags: () => string;
5
5
  export declare const getTagifyTagStyled: (_wrapperProps: TagifyWrapperProps) => import("styled-components").FlattenInterpolation<import("styled-components").ThemedStyledProps<TagifyWrapperProps, any>>;
6
6
  export declare const getBackgroundInputStatus: (status?: StatusType) => string;
@@ -3,7 +3,7 @@ import { css } from 'styled-components';
3
3
  import { isString } from 'lodash';
4
4
  // Constants
5
5
  import { globalToken } from '@antscorp/antsomi-ui/es/constants';
6
- import { DETECT_LINK, EMOJI, INVALID_TAG, MIN_H_WRAPPER, NO_VIEW_TAG, READONLY_TAG, REMOVED_TAG, SHORT_LINK, SHORT_LINK_TYPE, TAG_COLOR, TAG_H, TAG_TYPE, } from './constants';
6
+ import { DETECT_LINK, EMOJI, INVALID_TAG, MIN_H_WRAPPER, NO_VIEW_TAG, READONLY_TAG, REMOVED_TAG, SHORT_LINK, SHORT_LINK_TYPE, SHORT_LINK_V2, TAG_COLOR, TAG_H, TAG_TYPE, } from './constants';
7
7
  export const getTagifyStyled = ({ $maxHeight, $tagifyFullWidth }) => css `
8
8
  ${$maxHeight &&
9
9
  css `
@@ -36,12 +36,21 @@ export const getTagifyStyled = ({ $maxHeight, $tagifyFullWidth }) => css `
36
36
  font-size: var(--input-font-size);
37
37
  background: transparent;
38
38
  `;
39
- export const getTagifyInputStyled = ({ $minWidth, $placeholder, $isSingleLineText, }) => css `
39
+ export const getTagifyInputStyled = ({ $minWidth, $placeholder, $minWidthPlaceholder, $isSingleLineText, }) => css `
40
40
  // Because $placeholder depends on $minWidth to display
41
- ${$minWidth &&
42
- !$placeholder &&
43
- css `
44
- min-width: ${isString($minWidth) ? $minWidth : `${$minWidth}px`} !important;
41
+ ${css `
42
+ min-width: ${(() => {
43
+ // Primary check for $minWidth
44
+ if ($minWidth) {
45
+ return isString($minWidth) ? $minWidth : `${$minWidth}px`;
46
+ }
47
+ // Secondary check for $placeholder
48
+ if ($placeholder) {
49
+ return isString($minWidthPlaceholder) ? $minWidthPlaceholder : `${$minWidthPlaceholder}px`;
50
+ }
51
+ // Fallback value
52
+ return 'unset';
53
+ })()} !important;
45
54
  `}
46
55
 
47
56
  ${$isSingleLineText &&
@@ -71,6 +80,12 @@ export const getStyledTags = () => {
71
80
  break;
72
81
  return TAG_COLOR[SHORT_LINK][shortlinkType];
73
82
  }
83
+ case TAG_TYPE.SHORT_LINK_V2: {
84
+ const { shortlinkType } = tag;
85
+ if (!shortlinkType)
86
+ break;
87
+ return TAG_COLOR[SHORT_LINK_V2][shortlinkType];
88
+ }
74
89
  default: {
75
90
  if (!type)
76
91
  return 'white';
@@ -122,6 +137,22 @@ export const getStyledTags = () => {
122
137
  })};
123
138
  };
124
139
  }
140
+
141
+ &[data-tag-type~='${TAG_TYPE.SHORT_LINK_V2}'] {
142
+ &[data-tag-${TAG_TYPE.SHORT_LINK_V2}-type~='${SHORT_LINK_TYPE.INDIVIDUAL}'] {
143
+ background: ${getBackgroundColor({
144
+ type: TAG_TYPE.SHORT_LINK_V2,
145
+ shortlinkType: SHORT_LINK_TYPE.INDIVIDUAL,
146
+ })};
147
+ };
148
+
149
+ &[data-tag-${TAG_TYPE.SHORT_LINK_V2}-type~='${SHORT_LINK_TYPE.GENERAL}'] {
150
+ background: ${getBackgroundColor({
151
+ type: TAG_TYPE.SHORT_LINK_V2,
152
+ shortlinkType: SHORT_LINK_TYPE.GENERAL,
153
+ })};
154
+ };
155
+ }
125
156
  `;
126
157
  };
127
158
  export const getTagifyTagStyled = (_wrapperProps) => css `
@@ -152,8 +183,8 @@ export const getTagifyTagStyled = (_wrapperProps) => css `
152
183
  }
153
184
  }
154
185
  }
155
- > div[data-tag-type='promotion_code'] {
156
- background-color: white;
186
+ > div[data-tag-type] {
187
+ background-color: white !important;
157
188
  border: 1px solid red;
158
189
  }
159
190
  `}
@@ -181,8 +212,8 @@ export const getTagifyTagStyled = (_wrapperProps) => css `
181
212
  }
182
213
  }
183
214
  }
184
- > div[data-tag-type='promotion_code'] {
185
- background-color: white;
215
+ > div[data-tag-type] {
216
+ background-color: white !important;
186
217
  border: 1px solid red;
187
218
  }
188
219
  `}
@@ -211,8 +242,8 @@ export const getTagifyTagStyled = (_wrapperProps) => css `
211
242
  }
212
243
  }
213
244
  }
214
- > div[data-tag-type='promotion_code'] {
215
- background-color: white;
245
+ > div[data-tag-type] {
246
+ background-color: white !important;
216
247
  border: 1px solid red;
217
248
  }
218
249
  `}
@@ -3,5 +3,4 @@
3
3
  * Asynchronously loads the component for TemplateListing
4
4
  *
5
5
  */
6
- /// <reference types="react" />
7
6
  export declare const TemplateListing: (props: import("./types").TemplateListingProps<{}>) => JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.917",
3
+ "version": "1.3.5-beta.919",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",
@@ -253,3 +253,4 @@
253
253
  "react-router-dom": ">= 5.1.0"
254
254
  }
255
255
  }
256
+