@antscorp/antsomi-ui 1.3.5-beta.907 → 1.3.5-beta.909
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/components/molecules/AddDynamicContent/components/DisplayFormat/DisplayFormat.d.ts +0 -1
- package/es/components/molecules/TagifyInput/TagifyInput.js +12 -4
- package/es/components/molecules/TagifyInput/utils.d.ts +9 -0
- package/es/components/molecules/TagifyInput/utils.js +38 -0
- package/es/components/template/TemplateListing/Loadable.d.ts +0 -1
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ 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, } from './utils';
|
|
19
|
+
import { parseTagStringToTagify, convertInputStringToOriginal, emojiManufacturer, getEmojiTag, isPersonalizeTagType, generateTagContent, unescapeString, hasLineBreak, selectRange, isTagClickable, findURLInTextNodes, getAttributesString, isAnchorNodeChildOfElement, } from './utils';
|
|
20
20
|
import { acceptablePatternChecking, detectURLRegex, getCachedRegex, getPersonalizeTagInfo, patternHandlers, } from './patternHandlers';
|
|
21
21
|
// Constants
|
|
22
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';
|
|
@@ -80,8 +80,15 @@ const TagifyInput = forwardRef((props, ref) => {
|
|
|
80
80
|
}, []);
|
|
81
81
|
const onSelectionAfterInjection = useCallback((addRangeAfterInjected) => {
|
|
82
82
|
try {
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
if (!tagifyRef.current) {
|
|
84
|
+
throw new Error('Tagify instance is not initialized');
|
|
85
|
+
}
|
|
86
|
+
const { scope } = tagifyRef.current?.DOM;
|
|
87
|
+
const isValidSelection = isAnchorNodeChildOfElement(scope);
|
|
88
|
+
if (isValidSelection) {
|
|
89
|
+
const selection = window.getSelection();
|
|
90
|
+
if (!selection?.rangeCount)
|
|
91
|
+
return;
|
|
85
92
|
const range = selection.getRangeAt(0);
|
|
86
93
|
if (addRangeAfterInjected) {
|
|
87
94
|
// Need to re-select to keep the caret position
|
|
@@ -107,9 +114,10 @@ const TagifyInput = forwardRef((props, ref) => {
|
|
|
107
114
|
const { settings, DOM } = tagifyRef.current;
|
|
108
115
|
const rangeInstance = _.get(tagifyRef.current, 'state.selection.range', null);
|
|
109
116
|
const { empty } = settings.classNames;
|
|
117
|
+
const isValidSelection = isAnchorNodeChildOfElement(DOM.scope);
|
|
110
118
|
const selection = window.getSelection();
|
|
111
119
|
// In case not have the selection yet or lost the selection,
|
|
112
|
-
if (!selection?.rangeCount || !rangeInstance) {
|
|
120
|
+
if (!selection?.rangeCount || !isValidSelection || !rangeInstance) {
|
|
113
121
|
// need to restore the last range before inject a new tag if the last range exists
|
|
114
122
|
if (lastRange.current) {
|
|
115
123
|
selection?.removeAllRanges();
|
|
@@ -67,6 +67,7 @@ export declare const generateTagContent: (params: {
|
|
|
67
67
|
* // returns 'Hello "world" with spaces'
|
|
68
68
|
*/
|
|
69
69
|
export declare const unescapeString: (str: string) => string;
|
|
70
|
+
export declare function deepUnescape<T = any>(obj: T): T | string;
|
|
70
71
|
/**
|
|
71
72
|
* Checks if the string is a valid tag type.
|
|
72
73
|
* @param str
|
|
@@ -173,3 +174,11 @@ export declare function findURLInTextNodes(element: HTMLSpanElement, minLengthVa
|
|
|
173
174
|
* // Returns: 'class="btn-primary" disabled data-testid="submit-button" aria-label="Submit form" tabindex="0"'
|
|
174
175
|
*/
|
|
175
176
|
export declare const getAttributesString: (map: Map<string, string | boolean | number>) => string;
|
|
177
|
+
/**
|
|
178
|
+
* Checks if the anchor node of the current text selection
|
|
179
|
+
* is a child of a specific DOM element.
|
|
180
|
+
*
|
|
181
|
+
* @param {HTMLElement} element - The parent element to check against
|
|
182
|
+
* @returns {boolean} True if the anchor node is a child of the element, false otherwise
|
|
183
|
+
*/
|
|
184
|
+
export declare const isAnchorNodeChildOfElement: (element: Node) => boolean;
|
|
@@ -447,6 +447,21 @@ export const unescapeString = (str) => str.replace(/"| |nbsp;|'/g
|
|
|
447
447
|
return match;
|
|
448
448
|
}
|
|
449
449
|
});
|
|
450
|
+
export function deepUnescape(obj) {
|
|
451
|
+
// Base case: Return primitives as is
|
|
452
|
+
if (obj === null || typeof obj !== 'object') {
|
|
453
|
+
return typeof obj === 'string' ? unescapeString(obj) : obj;
|
|
454
|
+
}
|
|
455
|
+
// Handle arrays: Map and recurse
|
|
456
|
+
if (Array.isArray(obj)) {
|
|
457
|
+
return obj.map(deepUnescape);
|
|
458
|
+
}
|
|
459
|
+
// Handle objects: Recurse into key-value pairs
|
|
460
|
+
return Object.entries(obj).reduce((result, [key, value]) => {
|
|
461
|
+
result[key] = deepUnescape(value);
|
|
462
|
+
return result;
|
|
463
|
+
}, {});
|
|
464
|
+
}
|
|
450
465
|
/**
|
|
451
466
|
* Checks if the string is a valid tag type.
|
|
452
467
|
* @param str
|
|
@@ -602,3 +617,26 @@ export const getAttributesString = (map) => Array.from(map.entries())
|
|
|
602
617
|
})
|
|
603
618
|
.filter(Boolean)
|
|
604
619
|
.join(' ');
|
|
620
|
+
/**
|
|
621
|
+
* Checks if the anchor node of the current text selection
|
|
622
|
+
* is a child of a specific DOM element.
|
|
623
|
+
*
|
|
624
|
+
* @param {HTMLElement} element - The parent element to check against
|
|
625
|
+
* @returns {boolean} True if the anchor node is a child of the element, false otherwise
|
|
626
|
+
*/
|
|
627
|
+
export const isAnchorNodeChildOfElement = (element) => {
|
|
628
|
+
// Get the current selection
|
|
629
|
+
const selection = window.getSelection();
|
|
630
|
+
// Check if there's an active selection
|
|
631
|
+
if (!selection || selection.rangeCount === 0) {
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
634
|
+
// Get the anchor node (where the selection starts)
|
|
635
|
+
const { anchorNode } = selection;
|
|
636
|
+
// Check if the anchor node exists and the element exists
|
|
637
|
+
if (!anchorNode || !element) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
// Use Node.contains() to check if the element contains the anchor node
|
|
641
|
+
return element.contains(anchorNode);
|
|
642
|
+
};
|