@antscorp/antsomi-ui 1.3.5-beta.967 → 1.3.5-beta.969

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.
@@ -0,0 +1,23 @@
1
+ /// <reference types="react" />
2
+ export type ValueType = 'input' | 'select';
3
+ type Value = string | {
4
+ source: string;
5
+ code: string;
6
+ } | null;
7
+ type Option = {
8
+ [key: string]: any;
9
+ label: string;
10
+ value: string;
11
+ };
12
+ export interface InputSelectAttributeProps {
13
+ sourceOptions: Option[];
14
+ codeOptions: Option[];
15
+ errorMsg?: string;
16
+ value: Value;
17
+ onChange: (newValueData: {
18
+ value: Value;
19
+ valueType: ValueType;
20
+ }) => void;
21
+ }
22
+ declare const _default: import("react").MemoExoticComponent<(props: InputSelectAttributeProps) => import("react/jsx-runtime").JSX.Element>;
23
+ export default _default;
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Libraries
3
+ import { memo, useCallback, useState } from 'react';
4
+ // Translations
5
+ import { translate, translations } from '@antscorp/antsomi-ui/es/locales';
6
+ // Components
7
+ import Icon from '@antscorp/icons';
8
+ import { StyledTag as Tag } from '@antscorp/antsomi-ui/es/components/molecules/SelectV2/styled';
9
+ import { Flex, Select, Typography } from 'antd';
10
+ import { StyledSelect } from './styled';
11
+ import { Modal } from '../Modal';
12
+ // Constants
13
+ import { THEME } from '@antscorp/antsomi-ui/es/constants';
14
+ const InputSelectAttribute = (props) => {
15
+ const { value, errorMsg, sourceOptions, codeOptions, onChange } = props;
16
+ // States
17
+ const [openModal, setOpenModal] = useState(false);
18
+ const [attributeState, setAttributeState] = useState(() => {
19
+ if (value && typeof value !== 'string') {
20
+ return value;
21
+ }
22
+ return {
23
+ source: '',
24
+ code: '',
25
+ };
26
+ });
27
+ const onOpenModal = useCallback(() => {
28
+ setOpenModal(true);
29
+ }, []);
30
+ const onDeselect = useCallback(() => {
31
+ onChange({ value: '', valueType: 'input' });
32
+ }, [onChange]);
33
+ const onHideModal = useCallback(() => {
34
+ setOpenModal(false);
35
+ }, []);
36
+ const onOk = useCallback(() => {
37
+ setOpenModal(false);
38
+ onChange({ value: attributeState, valueType: 'select' });
39
+ }, [attributeState, onChange]);
40
+ const onChangeInput = useCallback((val) => {
41
+ onChange({ value: val, valueType: 'input' });
42
+ }, [onChange]);
43
+ const renderInput = () => {
44
+ let element = null;
45
+ const isObjValue = value && typeof value !== 'string';
46
+ if (openModal || isObjValue) {
47
+ element = (_jsxs("div", { style: {
48
+ display: 'flex',
49
+ alignItems: 'center',
50
+ justifyContent: 'space-between',
51
+ height: 32,
52
+ padding: '4px 12px 4px 4px',
53
+ borderBottom: `1px solid ${errorMsg ? THEME.token?.colorError : THEME.token?.blue1}`,
54
+ }, children: [_jsx("div", { style: { width: '100%', cursor: 'pointer' }, onClick: onOpenModal, children: isObjValue && _jsx(Tag, { children: value.code }) }), _jsx(Icon, { type: "icon-ants-remove", style: { fontSize: 10, color: '#222', cursor: 'pointer' }, onClick: onDeselect })] }));
55
+ }
56
+ else {
57
+ element = (_jsx(StyledSelect, { mode: "multiple", options: [{ value: '', label: translate(translations.orSelectAField.title) }], notFoundContent: null, onSelect: onOpenModal, style: { width: '100%', borderTop: 'none', borderLeft: 'none', borderRight: 'none' }, onDeselect: onDeselect, autoClearSearchValue: false, searchValue: typeof value === 'string' ? value : '', onSearch: onChangeInput, status: errorMsg ? 'error' : undefined, placeholder: typeof value === 'string' ? value : translate(translations.inputYourValue.title), "$isPlaceholder": !value, "$isError": !!errorMsg, dropdownStyle: {
58
+ ...(openModal ? { display: 'none' } : {}),
59
+ } }));
60
+ }
61
+ return element;
62
+ };
63
+ return (_jsxs(_Fragment, { children: [renderInput(), errorMsg ? (_jsx(Typography.Text, { style: { marginLeft: 8, color: THEME.token?.red8, marginTop: 5 }, children: errorMsg })) : null, _jsx(Modal, { title: translate(translations._PREDICT_MODEL_SELECT_ATTRIBUTE, 'Select attribute'), okText: translate(translations._ACT_APPLY, 'Apply'), open: openModal, onOk: onOk, onCancel: onHideModal, children: _jsxs(Flex, { vertical: true, gap: 15, children: [_jsxs(Flex, { gap: 10, children: [_jsxs(Typography.Text, { style: { lineHeight: '30px', flexBasis: 130 }, children: [translate(translations._TITL_PERSONALIZATION_TYPE, 'Content Source'), _jsx("span", { style: { color: THEME.token?.red8 }, children: "\u00A0 *" })] }), _jsx(Select, { suffixIcon: _jsx(Icon, { type: "icon-ants-expand-more", style: { fontSize: '20px', color: THEME.token?.colorIcon } }), style: { flex: 1 }, options: sourceOptions, value: attributeState.source, onChange: newValue => {
64
+ setAttributeState(state => ({ ...state, source: newValue }));
65
+ } })] }), _jsxs(Flex, { gap: 10, children: [_jsxs(Typography.Text, { style: { lineHeight: '30px', flexBasis: 130 }, children: ["Allocated Code", _jsx("span", { style: { color: THEME.token?.red8 }, children: "\u00A0 *" })] }), _jsx(Select, { suffixIcon: _jsx(Icon, { type: "icon-ants-expand-more", style: { fontSize: '20px', color: THEME.token?.colorIcon } }), style: { flex: 1 }, value: attributeState.code, options: codeOptions, onChange: newValue => {
66
+ setAttributeState(state => ({ ...state, code: newValue }));
67
+ } })] })] }) })] }));
68
+ };
69
+ export default memo(InputSelectAttribute);
@@ -0,0 +1,14 @@
1
+ export declare const StyledSelect: import("styled-components").StyledComponent<{
2
+ (props: import("@antscorp/antsomi-ui/es/components/molecules").SelectV2Props): import("react/jsx-runtime").JSX.Element;
3
+ defaultProps: {
4
+ suffixIcon: import("react/jsx-runtime").JSX.Element;
5
+ filterOption: (input: any, option: any) => boolean;
6
+ tagRender: (props: any) => import("react/jsx-runtime").JSX.Element;
7
+ containerStyle: {};
8
+ labelStyle: {};
9
+ clearIcon: import("react/jsx-runtime").JSX.Element;
10
+ };
11
+ }, any, {
12
+ $isPlaceholder?: any;
13
+ $isError?: boolean | undefined;
14
+ }, never>;
@@ -0,0 +1,28 @@
1
+ // Libraries
2
+ import styled, { css } from 'styled-components';
3
+ // Components
4
+ import { SelectV2 as Select } from '@antscorp/antsomi-ui/es/components/molecules';
5
+ // Constants
6
+ import { THEME } from '@antscorp/antsomi-ui/es/constants';
7
+ export const StyledSelect = styled(Select) `
8
+ .antsomi-select-selection-search {
9
+ width: fit-content !important;
10
+ }
11
+
12
+ ${({ $isError }) => $isError
13
+ ? css `
14
+ .antsomi-select-selector {
15
+ box-shadow: none !important;
16
+ }
17
+ `
18
+ : css ``}
19
+
20
+ .antsomi-select-selection-placeholder {
21
+ ${props => !props.$isPlaceholder
22
+ ? css `
23
+ color: rgba(0, 0, 0, 0.85);
24
+ font-size: ${THEME.token?.fontSize}px;
25
+ `
26
+ : css ``}
27
+ }
28
+ `;
@@ -23,7 +23,7 @@ import { DETECT_LINK, EMOJI, ERROR_TAG, FORCE_SHOW_TOOLTIP, INVALID_TAG, MESSAGE
23
23
  const { CUSTOM_TAG } = TAG_TYPE;
24
24
  const TagifyInput = forwardRef((props, ref) => {
25
25
  // 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, onTagRemove, 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, onTagRemove, onChange, } = props;
27
27
  // States
28
28
  const [isLineBreak, setIsLineBreak] = useState(hasLineBreak(initialValue));
29
29
  const [tooltipRefresher, setTooltipRefresher] = useState(1);
@@ -534,7 +534,7 @@ const TagifyInput = forwardRef((props, ref) => {
534
534
  /*
535
535
  * Any map attribute change will sync label of the tags
536
536
  */
537
- const makeValidLabelTags = useCallback((attributes, errorAttributes) => {
537
+ const makeValidLabelTags = useCallback((attributes, errorAttributes, tagProperties) => {
538
538
  if (tagifyRef.current && labelTagRefreshness) {
539
539
  const tagElements = tagifyRef.current.getTagElms();
540
540
  const { pattern, name: cachePatternName, acceptablePattern: acceptableType, } = patternHandlers[PERSONALIZE_PTN];
@@ -558,7 +558,7 @@ const TagifyInput = forwardRef((props, ref) => {
558
558
  while ((match = regex.exec(value)) !== null) {
559
559
  const [, personalizeContent] = match;
560
560
  const [tagCode] = personalizeContent.split('||');
561
- const { label: tagLabel, isValid, message, type, isRemoved, canView, isArchived, isActive, isExpired, } = getPersonalizeTagInfo(tagCode, attributes, errorAttributes);
561
+ const { label: tagLabel, isValid, message, type, isRemoved, canView, isArchived, isActive, isExpired, } = getPersonalizeTagInfo(tagCode, attributes, errorAttributes, tagProperties);
562
562
  const isPromotionCode = type === PROMOTION_CODE;
563
563
  const tagTextNode = tagifyRef.current?.getTagTextNode(tagElement);
564
564
  /*
@@ -579,7 +579,7 @@ const TagifyInput = forwardRef((props, ref) => {
579
579
  tagElement.removeAttribute(READONLY_TAG);
580
580
  tagElement.removeAttribute(MESSAGE_TAG);
581
581
  // In case promotion pool has something wrong
582
- if (isPromotionCode && message) {
582
+ if (message) {
583
583
  if (isRemoved || isArchived || !isActive || isExpired) {
584
584
  tagElement.setAttribute(ERROR_TAG, 'true');
585
585
  tagElement.setAttribute(MESSAGE_TAG, message);
@@ -594,10 +594,6 @@ const TagifyInput = forwardRef((props, ref) => {
594
594
  tagElement.setAttribute(MESSAGE_TAG, message);
595
595
  }
596
596
  }
597
- else if ((isArchived || !isActive || isExpired) && message) {
598
- tagElement.setAttribute(ERROR_TAG, 'true');
599
- tagElement.setAttribute(MESSAGE_TAG, message);
600
- }
601
597
  }
602
598
  }
603
599
  }
@@ -837,10 +833,8 @@ const TagifyInput = forwardRef((props, ref) => {
837
833
  * Need to sync label of the tags if any map attribute is changed to make correct label
838
834
  * */
839
835
  useDeepCompareEffect(() => {
840
- if (!_.isEmpty(mapAttributes)) {
841
- makeValidLabelTags(mapAttributes, mapErrorAttributes);
842
- }
843
- }, [mapAttributes, mapErrorAttributes, makeValidLabelTags]);
836
+ makeValidLabelTags(mapAttributes, mapErrorAttributes, tagProperties);
837
+ }, [mapAttributes, mapErrorAttributes, tagProperties, makeValidLabelTags]);
844
838
  useLayoutEffect(() => {
845
839
  if (tagProperties) {
846
840
  executeTagProperties(tagProperties);
@@ -895,9 +889,7 @@ const TagifyInput = forwardRef((props, ref) => {
895
889
  const content = parseTagStringToTagify(textValue, acceptableTagPattern);
896
890
  tagifyRef.current.loadOriginalValues(content);
897
891
  // Need to sync label of the tags if any map attribute is changed to make correct label
898
- if (!_.isEmpty(mapAttributes)) {
899
- makeValidLabelTags(mapAttributes, mapErrorAttributes);
900
- }
892
+ makeValidLabelTags(mapAttributes, mapErrorAttributes, tagProperties);
901
893
  }
902
894
  }
903
895
  }, [
@@ -906,6 +898,7 @@ const TagifyInput = forwardRef((props, ref) => {
906
898
  mapErrorAttributes,
907
899
  escapeHTML,
908
900
  acceptableTagPattern,
901
+ tagProperties,
909
902
  makeValidLabelTags,
910
903
  ]);
911
904
  useEffect(() => {
@@ -57,6 +57,7 @@ export const tagifyDefaultProps = {
57
57
  placeholder: undefined,
58
58
  minWidthPlaceholder: 130,
59
59
  acceptableTagPattern: DEFAULT_ACCEPT_TAGS,
60
+ mapErrorAttributes: {},
60
61
  onChange: () => { },
61
62
  };
62
63
  export const TAG_TYPE = {
@@ -1,4 +1,4 @@
1
- import type { AcceptablePattern, MapAttributesProps, PatterTagName, PatternHandlerWrapper, TagTypeProperty } from './types';
1
+ import type { AcceptablePattern, MapAttributesProps, PatterTagName, PatternHandlerWrapper, TagProperties, TagTypeProperty } from './types';
2
2
  interface TagInfo {
3
3
  label: string;
4
4
  type: string;
@@ -29,7 +29,7 @@ export declare function acceptablePatternChecking(pattern: AcceptablePattern, ac
29
29
  * @returns {string} The extracted custom tag ID if the tag type is a custom tag; otherwise, empty string.
30
30
  */
31
31
  export declare const getCustomTagId: (tagType: TagTypeProperty, mergeCode: string) => string;
32
- export declare const getPersonalizeTagInfo: (originalTag: string, mapAttributes?: MapAttributesProps, mapErrorAttributes?: MapAttributesProps) => TagInfo;
32
+ export declare const getPersonalizeTagInfo: (originalTag: string, mapAttributes: MapAttributesProps, mapErrorAttributes: MapAttributesProps, tagProperties: TagProperties) => TagInfo;
33
33
  export declare const getShortLinkTagInfo: (params: {
34
34
  type: string;
35
35
  label: string;
@@ -244,7 +244,7 @@ const getLabelAttribute = (type, attributeName, subAttributeName, mapAttributes)
244
244
  mapping[combineAttribute]?.template_name ||
245
245
  combineAttribute);
246
246
  };
247
- export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttributes) => {
247
+ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttributes, tagProperties) => {
248
248
  try {
249
249
  const [type, attributeName, subAttributeName] = originalTag.split('.');
250
250
  const isCsGroup = type === CONTENT_SOURCE_GROUP;
@@ -261,12 +261,13 @@ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttrib
261
261
  true,
262
262
  false,
263
263
  ];
264
- if (!mapAttributes || (!mapAttributes[type] && !isCsGroup)) {
264
+ if (!has(mapAttributes, type) && !has(tagProperties, combineAttribute) && !isCsGroup) {
265
265
  // return fallback if no mapping
266
266
  return {
267
267
  type,
268
268
  label: attributeName || type,
269
269
  isValid: false,
270
+ message: 'This tag does not exist anymore',
270
271
  isRemoved,
271
272
  canView,
272
273
  isArchived,
@@ -281,60 +282,54 @@ export const getPersonalizeTagInfo = (originalTag, mapAttributes, mapErrorAttrib
281
282
  switch (type) {
282
283
  case PROMOTION_CODE: {
283
284
  // Check if the code is exist in the map
284
- if (mapAttributes[type] && attributeName) {
285
- const isExistPromotionPool = has(mapAttributes[type], attributeName);
286
- if (!isExistPromotionPool) {
287
- isValid = false;
288
- message = 'This pool does not exist anymore';
289
- if (mapErrorAttributes &&
290
- mapErrorAttributes[type] &&
291
- 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] || {};
295
- if (!isExist) {
296
- // Case Pool Removed
297
- isRemoved = !isExist;
298
- message = translate(translations._PERSONALIZATION_TAG_ERR_REMOVED, 'This pool is removed');
299
- }
300
- else if (_isArchived) {
301
- // Case Pool is Archived
302
- isArchived = true;
303
- message = translate(translations._PERSONALIZATION_TAG_ERR_ATT_ARCHIVE, 'This attribute has been archived');
304
- }
305
- else if (!_isActive) {
306
- // Case Pool is Inactive
307
- isActive = false;
308
- message = translate(translations._PERSONALIZATION_TAG_ERR_POOL_DEACTIVATE, 'This pool has been deactivated. You have to turn it on to use');
309
- }
310
- else if (_isExpired) {
311
- // Case Pool is Expired
312
- isExpired = true;
313
- message = translate(translations._PERSONALIZATION_TAG_ERR_POOL_EXPIRE, 'This pool has expired, new codes could not be allocated');
314
- }
315
- else if (!isView) {
316
- // Case Pool Can't View
317
- canView = isView;
318
- message = translate(translations._PERMISSION_ERR_POOL, 'You do not have permission on this pool');
319
- }
285
+ const isExistPromotionPool = has(mapAttributes, [type, attributeName]) || has(tagProperties, attributeName);
286
+ if (!isExistPromotionPool) {
287
+ isValid = false;
288
+ message = 'This pool does not exist anymore';
289
+ if (has(mapErrorAttributes, [type, attributeName])) {
290
+ const {
291
+ // isEdit = false,
292
+ isView = false, isExist = true, isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes?.[type]?.[attributeName] || {};
293
+ if (!isExist) {
294
+ // Case Pool Removed
295
+ isRemoved = !isExist;
296
+ message = translate(translations._PERSONALIZATION_TAG_ERR_REMOVED, 'This pool is removed');
297
+ }
298
+ else if (_isArchived) {
299
+ // Case Pool is Archived
300
+ isArchived = true;
301
+ message = translate(translations._PERSONALIZATION_TAG_ERR_ATT_ARCHIVE, 'This attribute has been archived');
302
+ }
303
+ else if (!_isActive) {
304
+ // Case Pool is Inactive
305
+ isActive = false;
306
+ message = translate(translations._PERSONALIZATION_TAG_ERR_POOL_DEACTIVATE, 'This pool has been deactivated. You have to turn it on to use');
307
+ }
308
+ else if (_isExpired) {
309
+ // Case Pool is Expired
310
+ isExpired = true;
311
+ message = translate(translations._PERSONALIZATION_TAG_ERR_POOL_EXPIRE, 'This pool has expired, new codes could not be allocated');
312
+ }
313
+ else if (!isView) {
314
+ // Case Pool Can't View
315
+ canView = isView;
316
+ message = translate(translations._PERMISSION_ERR_POOL, 'You do not have permission on this pool');
320
317
  }
321
318
  }
322
319
  }
323
320
  break;
324
321
  }
325
322
  default: {
326
- if (mapAttributes[type] &&
327
- combineAttribute &&
328
- !has(mapAttributes[type], combineAttribute)) {
323
+ if (combineAttribute &&
324
+ (!has(mapAttributes, [type, combineAttribute]) ||
325
+ !has(tagProperties, [type, combineAttribute]))) {
329
326
  isValid = false;
330
327
  message = 'This attribute does not exist anymore';
331
328
  }
332
- if (mapErrorAttributes &&
333
- mapErrorAttributes[type] &&
334
- mapErrorAttributes[type][combineAttribute]) {
335
- const { isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes[type][combineAttribute] || {};
329
+ if (has(mapErrorAttributes, [type, combineAttribute])) {
330
+ const { isArchived: _isArchived = false, isActive: _isActive = true, isExpired: _isExpired = false, } = mapErrorAttributes?.[type]?.[combineAttribute] || {};
336
331
  if (_isArchived) {
337
- // Case Pool is Archived
332
+ // Case Tag is Archived
338
333
  isArchived = true;
339
334
  message = translate(translations._PERSONALIZATION_TAG_ERR_ATT_ARCHIVE, 'This attribute has been archived');
340
335
  }
@@ -65,6 +65,7 @@ export * from './TagifyInput';
65
65
  export * from './EmojiCollections';
66
66
  export * from './EmojiPopover';
67
67
  export * from './DisplayFormat';
68
+ export * from './InputSelectAttribute';
68
69
  export { EditorScript } from './EditorScript';
69
70
  export { EditorTab } from './EditorTab';
70
71
  export { SelectAccount } from './SelectAccount';
@@ -65,6 +65,7 @@ export * from './TagifyInput';
65
65
  export * from './EmojiCollections';
66
66
  export * from './EmojiPopover';
67
67
  export * from './DisplayFormat';
68
+ export * from './InputSelectAttribute';
68
69
  export { EditorScript } from './EditorScript';
69
70
  export { EditorTab } from './EditorTab';
70
71
  export { SelectAccount } from './SelectAccount';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antscorp/antsomi-ui",
3
- "version": "1.3.5-beta.967",
3
+ "version": "1.3.5-beta.969",
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-locales": "1.0.31",
64
+ "@antscorp/antsomi-locales": "1.0.32",
65
65
  "@ant-design/cssinjs": "^1.6.2",
66
66
  "@antscorp/icons": "0.27.54",
67
67
  "@antscorp/image-editor": "1.0.2",