@antscorp/antsomi-ui 1.3.5-beta.941 → 1.3.5-beta.943

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.
@@ -17,12 +17,13 @@ import '@yaireo/tagify/dist/tagify.css';
17
17
  import { TagTextArea, TagifyWrapper, WrapperPlaceHolder } from './styled';
18
18
  // Utils
19
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';
20
+ import { acceptablePatternChecking, detectURLRegex, getCachedRegex, getCustomTagId, getPersonalizeTagInfo, getShortLinkTagInfo, patternHandlers, } from './patternHandlers';
21
21
  // Constants
22
- import { DETECT_LINK, EMOJI, ERROR_TAG, FORCE_SHOW_TOOLTIP, INVALID_TAG, MESSAGE_TAG, PERSONALIZE_PTN, PROMOTION_CODE, READONLY_TAG, SHORT_LINK, SHORT_LINK_PTN, SHORT_LINK_V2, WARNING_TAG, defaultCssVariables, tagifyDefaultProps, } from './constants';
22
+ import { DETECT_LINK, EMOJI, ERROR_TAG, FORCE_SHOW_TOOLTIP, INVALID_TAG, MESSAGE_TAG, PERSONALIZE_PTN, PROMOTION_CODE, READONLY_TAG, SHORT_LINK, SHORT_LINK_PTN, SHORT_LINK_V2, WARNING_TAG, TAG_TYPE, defaultCssVariables, tagifyDefaultProps, } from './constants';
23
+ const { CUSTOM_TAG } = TAG_TYPE;
23
24
  const TagifyInput = forwardRef((props, ref) => {
24
25
  // 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
+ const { initialValue, escapeHTML, status, readonly, readonlyTag, realtime, disabled, maxLength, maxHeight, minWidth, placeholder, minWidthPlaceholder, isSingleLineText, acceptableTagPattern, tagProperties, mapAttributes, mapErrorAttributes, maxPersonalizeTags, name, children, cssTagifyVariables, onTagClick, onChange, } = props;
26
27
  // States
27
28
  const [isLineBreak, setIsLineBreak] = useState(hasLineBreak(initialValue));
28
29
  const [tooltipRefresher, setTooltipRefresher] = useState(1);
@@ -629,6 +630,52 @@ const TagifyInput = forwardRef((props, ref) => {
629
630
  setTooltipRefresher(prev => prev + 1);
630
631
  }
631
632
  }, [acceptableTagPattern, labelTagRefreshness]);
633
+ /*
634
+ * Execute tag properties for each tag
635
+ */
636
+ const executeTagProperties = useCallback((properties) => {
637
+ if (tagifyRef.current) {
638
+ let isChangeOccurred = false;
639
+ const tagElements = tagifyRef.current.getTagElms();
640
+ const { pattern, name: cachePatternName } = patternHandlers[PERSONALIZE_PTN];
641
+ tagElements.forEach(tagElement => {
642
+ const tagData = tagifyRef.current?.getSetTagData(tagElement);
643
+ if (tagData) {
644
+ const { type, value } = tagData;
645
+ const isCustomTag = type === CUSTOM_TAG;
646
+ // Skip if it is not a custom tag
647
+ if (!isCustomTag || !value)
648
+ return;
649
+ // Use the cached regex instead of creating a new one each time
650
+ const regex = getCachedRegex(pattern, 'g', cachePatternName);
651
+ let match;
652
+ // Iterate over matches of the current pattern
653
+ // eslint-disable-next-line no-cond-assign
654
+ while ((match = regex.exec(value)) !== null) {
655
+ const [, contentCode] = match;
656
+ const customTagId = getCustomTagId(type, contentCode);
657
+ const property = _.get(properties, customTagId);
658
+ if (!customTagId || !property)
659
+ continue;
660
+ /*
661
+ * Just only update to the correct text of the tag
662
+ * NOTE: Do not actually affect raw data
663
+ */
664
+ tagData.label = property.displayName;
665
+ tagData.bgColorPersonalizeType = property.type;
666
+ tagifyRef.current?.replaceTag(tagElement, tagData);
667
+ // Mark the tag as changed
668
+ isChangeOccurred = true;
669
+ }
670
+ }
671
+ });
672
+ if (isChangeOccurred) {
673
+ setTooltipRefresher(prev => prev + 1);
674
+ // Make silent update -> do not callback data out
675
+ tagifyRef.current?.update({ withoutChangeEvent: true });
676
+ }
677
+ }
678
+ }, []);
632
679
  const initializeTagify = useCallback(() => {
633
680
  if (inputRef.current && !tagifyRef.current) {
634
681
  tagifyRef.current = new Tagify(inputRef.current, {
@@ -784,6 +831,11 @@ const TagifyInput = forwardRef((props, ref) => {
784
831
  makeValidLabelTags(mapAttributes, mapErrorAttributes);
785
832
  }
786
833
  }, [mapAttributes, mapErrorAttributes, makeValidLabelTags]);
834
+ useLayoutEffect(() => {
835
+ if (tagProperties) {
836
+ executeTagProperties(tagProperties);
837
+ }
838
+ }, [tagProperties, executeTagProperties]);
787
839
  // Listen to Tagify events
788
840
  useEffect(() => {
789
841
  const { current: tagifyInstance } = tagifyRef || {};
@@ -921,11 +973,15 @@ const TagifyInput = forwardRef((props, ref) => {
921
973
  const isTooltipVisible = tooltipRect && hasWrongAttribute;
922
974
  const isForceVisible = tooltipRect && forceShowTooltipAttr === 'true';
923
975
  if (isTooltipVisible || isForceVisible) {
976
+ const offsetTop = 30;
977
+ const top = tagRect.y - offsetTop;
924
978
  if (tooltipRect?.width > tagRect.width) {
925
- tooltip?.setAttribute('style', `visibility: visible !important;display: block !important;top:${tagRect.y - tagRect.height - 10}px;left:${tagRect.x - (tooltipRect?.width - tagRect.width) / 2}px;`);
979
+ const left = tagRect.x - (tooltipRect?.width - tagRect.width) / 2;
980
+ tooltip?.setAttribute('style', `visibility: visible !important;display: block !important;top:${top}px;left:${left}px;`);
926
981
  }
927
982
  else {
928
- tooltip?.setAttribute('style', `visibility: visible !important;display: block !important;top:${tagRect.y - tagRect.height - 10}px;left:${tagRect.x + (tagRect?.width - tooltipRect.width) / 2}px;`);
983
+ const left = tagRect.x + (tagRect?.width - tooltipRect.width) / 2;
984
+ tooltip?.setAttribute('style', `visibility: visible !important;display: block !important;top:${top}px;left:${left}px;`);
929
985
  }
930
986
  }
931
987
  };
@@ -75,8 +75,10 @@ export const TAG_TYPE = {
75
75
  DETECT_LINK: 'detect_link',
76
76
  CONTENT_SOURCE_GROUP: 'groups',
77
77
  ALLOCATED_CODE: 'allocated_code',
78
+ CUSTOM_TAG: 'custom_tag', // Refer to all tag type
78
79
  };
79
- 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, } = TAG_TYPE;
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, ALLOCATED_CODE, CUSTOM_TAG, } = TAG_TYPE;
81
+ export const TAG_TYPE_LIST = Object.freeze(Object.values(TAG_TYPE));
80
82
  export const SHORT_LINK_TYPE = {
81
83
  INDIVIDUAL: 'shortlink', // Individual link
82
84
  GENERAL: 'shortlink_static', // General link
@@ -107,6 +109,7 @@ export const TAG_COLOR = {
107
109
  [CONTENT_SOURCE_GROUP]: '#ffdd9f',
108
110
  [EMOJI]: 'transparent',
109
111
  [ALLOCATED_CODE]: '#DAA7F8',
112
+ [CUSTOM_TAG]: 'transparent',
110
113
  };
111
114
  export const EMOJI_COLLECTIONS = {
112
115
  COMMON: 'common',
@@ -8,7 +8,8 @@ import { errorWrapper } from './errorWrapper';
8
8
  import { isViberEmoji } from './iconsViber';
9
9
  import { random } from '@antscorp/antsomi-ui/es/utils';
10
10
  // 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
+ 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_TYPE, VIBER_EMOJI_PTN, } from './constants';
12
+ const { CUSTOM_TAG } = TAG_TYPE;
12
13
  /*
13
14
  * Usage to cache compiled regular expressions:
14
15
  * const regex = getCachedRegex(pattern, flags);
@@ -201,6 +202,21 @@ const getContentSourceLabel = (attributeName, subAttributeName, mapAttributes) =
201
202
  }
202
203
  return attributeName;
203
204
  };
205
+ /**
206
+ * Extracts the custom tag ID from a merge code if the tag type is a custom tag.
207
+ *
208
+ * @param {TagTypeProperty} tagType - The type of the tag to check.
209
+ * @param {string} mergeCode - The merge code containing the tag information, typically in the format "type.customTagId||additionalInfo".
210
+ * @returns {string} The extracted custom tag ID if the tag type is a custom tag; otherwise, empty string.
211
+ */
212
+ export const getCustomTagId = (tagType, mergeCode) => {
213
+ const isCustomTag = tagType === CUSTOM_TAG;
214
+ if (!isCustomTag)
215
+ return '';
216
+ const [tagCode] = mergeCode.split('||');
217
+ const [, customTagId] = tagCode.split('.');
218
+ return customTagId;
219
+ };
204
220
  /**
205
221
  * Retrieves the label for a attribute tag.
206
222
  * @param {string} type - The type from the original tag.
@@ -273,7 +289,9 @@ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttrib
273
289
  if (mapErrorAttributes &&
274
290
  mapErrorAttributes[type] &&
275
291
  mapErrorAttributes[type][attributeName]) {
276
- const { isEdit = false, isView = false, isExist = true, isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes[type][attributeName] || {};
292
+ const {
293
+ // isEdit = false,
294
+ isView = false, isExist = true, isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes[type][attributeName] || {};
277
295
  if (!isExist) {
278
296
  // Case Pool Removed
279
297
  isRemoved = !isExist;
@@ -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, SHORT_LINK_V2, TAG_TYPE, } from './constants';
4
+ import { CUSTOM_TAG, 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,12 +401,17 @@ export const isPersonalizeTagType = (type) => [
401
401
  CUSTOM_FN,
402
402
  CONTENT_SOURCE_GROUP,
403
403
  ALLOCATED_CODE,
404
+ CUSTOM_TAG,
404
405
  ].includes(type);
405
406
  export const isShortLinkTagType = (type) => [SHORT_LINK_V2].includes(type);
406
407
  export const generateTagContent = (params) => {
407
408
  const { tagData, content } = params;
408
409
  let dataAttrsString = '';
409
410
  const dataAttrs = new Map([['tag-type', tagData.type]]);
411
+ if (tagData.bgColorPersonalizeType) {
412
+ dataAttrs.set('priority-color-type', tagData.bgColorPersonalizeType);
413
+ dataAttrs.set('bg-color-personalize-type', tagData.bgColorPersonalizeType);
414
+ }
410
415
  if (tagData.type === TAG_TYPE.SHORT_LINK) {
411
416
  const { shortlinkType } = tagData;
412
417
  dataAttrs.set(`tag-${TAG_TYPE.SHORT_LINK}-type`, shortlinkType);
@@ -420,7 +425,7 @@ export const generateTagContent = (params) => {
420
425
  dataAttrsString = dataAttrsString.concat(` data-${key}="${value}"`);
421
426
  });
422
427
  return `
423
- <div ${dataAttrsString}>
428
+ <div ${dataAttrsString} class="tagify__tag-content">
424
429
  ${content}
425
430
  </div>
426
431
  `;
@@ -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, ERROR_TAG, MIN_H_WRAPPER, READONLY_TAG, SHORT_LINK, SHORT_LINK_TYPE, SHORT_LINK_V2, TAG_COLOR, TAG_H, TAG_TYPE, WARNING_TAG, } from './constants';
6
+ import { DETECT_LINK, EMOJI, ERROR_TAG, MIN_H_WRAPPER, READONLY_TAG, SHORT_LINK, SHORT_LINK_TYPE, SHORT_LINK_V2, TAG_COLOR, TAG_H, TAG_TYPE, WARNING_TAG, TAG_TYPE_LIST, } from './constants';
7
7
  export const getTagifyStyled = ({ $maxHeight, $tagifyFullWidth }) => css `
8
8
  ${$maxHeight &&
9
9
  css `
@@ -70,47 +70,48 @@ export const getTagifyInputStyled = ({ $minWidth, $placeholder, $minWidthPlaceho
70
70
  }
71
71
  `}
72
72
  `;
73
- export const getStyledTags = () => {
74
- const getBackgroundColor = (tag) => {
75
- const { type } = tag;
76
- switch (type) {
77
- case TAG_TYPE.SHORT_LINK: {
78
- const { shortlinkType } = tag;
79
- if (!shortlinkType)
80
- break;
81
- return TAG_COLOR[SHORT_LINK][shortlinkType];
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
- }
89
- default: {
90
- if (!type)
91
- return 'white';
92
- return TAG_COLOR[type];
93
- }
73
+ const getBackgroundColor = (tag) => {
74
+ const { type } = tag;
75
+ switch (type) {
76
+ case TAG_TYPE.SHORT_LINK: {
77
+ const { shortlinkType } = tag;
78
+ if (!shortlinkType)
79
+ break;
80
+ return TAG_COLOR[SHORT_LINK][shortlinkType];
94
81
  }
95
- return null;
96
- };
97
- const tagTypes = Object.values(TAG_TYPE);
98
- const backgroundStyles = tagTypes
99
- .map(type => {
100
- const background = getBackgroundColor({ type });
101
- if (!background)
102
- return '';
103
- return `
104
- &[data-tag-type~='${type}'] {
105
- background: ${getBackgroundColor({ type })};
106
- };
107
- `;
108
- })
109
- .join(' ');
82
+ case TAG_TYPE.SHORT_LINK_V2: {
83
+ const { shortlinkType } = tag;
84
+ if (!shortlinkType)
85
+ break;
86
+ return TAG_COLOR[SHORT_LINK_V2][shortlinkType];
87
+ }
88
+ default: {
89
+ if (!type)
90
+ return 'white';
91
+ return TAG_COLOR[type];
92
+ }
93
+ }
94
+ return null;
95
+ };
96
+ const tagListString = TAG_TYPE_LIST.map(tagType => `[data-tag-type~='${tagType}']`).join(',');
97
+ const backgroundStyles = TAG_TYPE_LIST.map(type => {
98
+ const background = getBackgroundColor({ type });
99
+ if (!background)
100
+ return '';
110
101
  return `
102
+ &[data-tag-type~='${type}'] {
103
+ background: ${background};
104
+ }
105
+
106
+ &[data-priority-color-type~='${type}'][data-bg-color-personalize-type~='${type}'] {
107
+ background: ${background};
108
+ }
109
+ `;
110
+ }).join(' ');
111
+ export const getStyledTags = () => `
111
112
  // For case unknown tag
112
113
  &[data-tag-type]:not(:is(
113
- ${tagTypes.map(tagType => `[data-tag-type~='${tagType}']`).join(',')}
114
+ ${tagListString}
114
115
  )) {
115
116
  background: ${globalToken?.accent7};
116
117
  };
@@ -122,40 +123,54 @@ export const getStyledTags = () => {
122
123
  padding: 0;
123
124
  };
124
125
 
126
+ &[data-tag-type~='${DETECT_LINK}'] {
127
+ border-radius: unset;
128
+ max-height: fit-content;
129
+
130
+ .tagify__tag-text {
131
+ max-width: fit-content;
132
+ white-space: normal;
133
+ }
134
+ };
135
+
125
136
  &[data-tag-type~='${TAG_TYPE.SHORT_LINK}'] {
126
137
  &[data-tag-${TAG_TYPE.SHORT_LINK}-type~='${SHORT_LINK_TYPE.INDIVIDUAL}'] {
127
138
  background: ${getBackgroundColor({
128
- type: TAG_TYPE.SHORT_LINK,
129
- shortlinkType: SHORT_LINK_TYPE.INDIVIDUAL,
130
- })};
139
+ type: TAG_TYPE.SHORT_LINK,
140
+ shortlinkType: SHORT_LINK_TYPE.INDIVIDUAL,
141
+ })};
131
142
  };
132
143
 
133
144
  &[data-tag-${TAG_TYPE.SHORT_LINK}-type~='${SHORT_LINK_TYPE.GENERAL}'] {
134
145
  background: ${getBackgroundColor({
135
- type: TAG_TYPE.SHORT_LINK,
136
- shortlinkType: SHORT_LINK_TYPE.GENERAL,
137
- })};
146
+ type: TAG_TYPE.SHORT_LINK,
147
+ shortlinkType: SHORT_LINK_TYPE.GENERAL,
148
+ })};
138
149
  };
139
150
  }
140
151
 
141
152
  &[data-tag-type~='${TAG_TYPE.SHORT_LINK_V2}'] {
142
153
  &[data-tag-${TAG_TYPE.SHORT_LINK_V2}-type~='${SHORT_LINK_TYPE.INDIVIDUAL}'] {
143
154
  background: ${getBackgroundColor({
144
- type: TAG_TYPE.SHORT_LINK_V2,
145
- shortlinkType: SHORT_LINK_TYPE.INDIVIDUAL,
146
- })};
155
+ type: TAG_TYPE.SHORT_LINK_V2,
156
+ shortlinkType: SHORT_LINK_TYPE.INDIVIDUAL,
157
+ })};
147
158
  };
148
159
 
149
160
  &[data-tag-${TAG_TYPE.SHORT_LINK_V2}-type~='${SHORT_LINK_TYPE.GENERAL}'] {
150
161
  background: ${getBackgroundColor({
151
- type: TAG_TYPE.SHORT_LINK_V2,
152
- shortlinkType: SHORT_LINK_TYPE.GENERAL,
153
- })};
162
+ type: TAG_TYPE.SHORT_LINK_V2,
163
+ shortlinkType: SHORT_LINK_TYPE.GENERAL,
164
+ })};
154
165
  };
155
166
  }
156
167
  `;
157
- };
158
168
  export const getTagifyTagStyled = (_wrapperProps) => css `
169
+ &[type='${DETECT_LINK}'] {
170
+ max-width: fit-content;
171
+ height: fit-content;
172
+ }
173
+
159
174
  &[${READONLY_TAG}='true'] {
160
175
  cursor: not-allowed;
161
176
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.941",
3
+ "version": "1.3.5-beta.943",
4
4
  "description": "An enterprise-class UI design language and React UI library.",
5
5
  "sideEffects": [
6
6
  "dist/*",
@@ -61,7 +61,7 @@
61
61
  "not op_mini all"
62
62
  ],
63
63
  "dependencies": {
64
- "@antscorp/antsomi-genai": "1.0.1-beta-15",
64
+ "@antscorp/antsomi-genai": "1.0.1-beta-16",
65
65
  "@antscorp/antsomi-constants": "1.0.5-beta.2",
66
66
  "@antscorp/antsomi-locales": "1.0.28",
67
67
  "@antscorp/icons": "0.27.54",