@antscorp/antsomi-ui 1.3.7-beta.2 → 1.3.7-beta.21
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/atoms/index.d.ts +0 -2
- package/es/components/atoms/index.js +0 -2
- package/es/components/molecules/TagifyInput/TagifyInput.js +48 -18
- package/es/components/molecules/TagifyInput/types.d.ts +20 -1
- package/es/components/molecules/TagifyInput/utils.d.ts +3 -1
- package/es/components/molecules/TagifyInput/utils.js +9 -0
- package/es/components/organism/ActivityTimeline/ActivityTimeline.js +3 -3
- package/es/components/organism/ActivityTimeline/components/ItemEvent/ItemEvent.js +7 -1
- package/es/components/organism/ActivityTimeline/components/ItemGroupEvent/ItemGroupEvent.js +14 -2
- package/es/components/organism/ActivityTimeline/constants.d.ts +9 -9
- package/es/components/organism/ActivityTimeline/constants.js +3 -3
- package/es/components/organism/ActivityTimeline/index.d.ts +530 -1
- package/es/components/organism/ActivityTimeline/index.js +9 -1
- package/es/components/organism/ActivityTimeline/utils.d.ts +7 -1
- package/es/components/organism/ActivityTimeline/utils.js +10 -7
- package/es/components/organism/TextEditor/TextEditor.d.ts +8 -2
- package/es/components/organism/TextEditor/TextEditor.js +76 -3
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.js +3 -2
- package/es/components/organism/TextEditor/extensions/Link.js +3 -3
- package/es/components/organism/TextEditor/extensions/SmartTag.d.ts +0 -6
- package/es/components/organism/TextEditor/extensions/SmartTag.js +3 -2
- package/es/components/organism/TextEditor/hooks/useMarkTracking.js +2 -1
- package/es/components/organism/TextEditor/index.d.ts +6 -5
- package/es/components/organism/TextEditor/stories/WithOldDynAndLink/settings.json +95 -0
- package/es/components/organism/TextEditor/types.d.ts +75 -2
- package/es/components/organism/TextEditor/types.js +1 -0
- package/es/components/organism/TextEditor/utils/documentState.d.ts +14 -0
- package/es/components/organism/TextEditor/utils/documentState.js +25 -0
- package/es/components/organism/TextEditor/utils/htmlProcessing.js +60 -0
- package/es/components/organism/TextEditor/utils/link.d.ts +10 -1
- package/es/components/organism/TextEditor/utils/link.js +161 -7
- package/es/components/organism/TextEditor/utils/menu.js +2 -1
- package/es/components/organism/TextEditor/utils/selection.js +3 -2
- package/es/components/organism/TextEditor/utils/smartTag.js +2 -1
- package/es/components/organism/index.d.ts +1 -1
- package/es/hooks/index.d.ts +1 -1
- package/es/hooks/index.js +1 -1
- package/es/services/MediaTemplateDesign/UploadFile/index.js +4 -4
- package/es/types/index.d.ts +1 -1
- package/es/types/index.js +1 -1
- package/es/utils/common.d.ts +1 -1
- package/es/utils/common.js +3 -3
- package/package.json +11 -23
|
@@ -4,6 +4,7 @@ import { isNoSelection } from './selection';
|
|
|
4
4
|
import { isEmpty } from 'lodash';
|
|
5
5
|
import { isLinkMarkRange } from '../types';
|
|
6
6
|
import { CUSTOM_LINK_EXTENSION_NAME } from '../constants';
|
|
7
|
+
import { textBetween } from './documentState';
|
|
7
8
|
/**
|
|
8
9
|
* Kiểm tra xem cursor có đang nằm trong một đoạn text có mark là link hay không
|
|
9
10
|
* @param state EditorState của Tiptap/ProseMirror
|
|
@@ -84,7 +85,60 @@ export const getActiveLinkAttrsFromRange = (params) => {
|
|
|
84
85
|
};
|
|
85
86
|
};
|
|
86
87
|
/**
|
|
87
|
-
*
|
|
88
|
+
* Builds lookup maps for adjacent link search by position
|
|
89
|
+
* @param allLinks All link ranges in document
|
|
90
|
+
* @returns Maps of links indexed by their start/end positions
|
|
91
|
+
*/
|
|
92
|
+
const buildLinkLookupMaps = (allLinks) => {
|
|
93
|
+
const linkEndingAt = new Map();
|
|
94
|
+
const linkStartingAt = new Map();
|
|
95
|
+
allLinks.forEach(link => {
|
|
96
|
+
if (!linkEndingAt.has(link.to)) {
|
|
97
|
+
linkEndingAt.set(link.to, []);
|
|
98
|
+
}
|
|
99
|
+
linkEndingAt.get(link.to).push(link);
|
|
100
|
+
if (!linkStartingAt.has(link.from)) {
|
|
101
|
+
linkStartingAt.set(link.from, []);
|
|
102
|
+
}
|
|
103
|
+
linkStartingAt.get(link.from).push(link);
|
|
104
|
+
});
|
|
105
|
+
return { linkEndingAt, linkStartingAt };
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Finds all adjacent link ranges with the same href
|
|
109
|
+
* @param linkRange Current link range to check
|
|
110
|
+
* @param targetHref Target href to match
|
|
111
|
+
* @param linkEndingAt Map of links ending at each position
|
|
112
|
+
* @param linkStartingAt Map of links starting at each position
|
|
113
|
+
* @param doc Document node
|
|
114
|
+
* @returns Array of adjacent link ranges with same href (includes the input linkRange)
|
|
115
|
+
*/
|
|
116
|
+
const findAdjacentLinksWithSameHref = (linkRange, targetHref, linkEndingAt, linkStartingAt, doc) => {
|
|
117
|
+
const adjacentLinks = [linkRange];
|
|
118
|
+
// Find adjacent links before (links ending where current link starts)
|
|
119
|
+
let currentFrom = linkRange.from;
|
|
120
|
+
while (currentFrom > 0) {
|
|
121
|
+
const linksEndingHere = linkEndingAt.get(currentFrom) || [];
|
|
122
|
+
const adjacentBefore = linksEndingHere.find(range => range.mark.attrs.href === targetHref);
|
|
123
|
+
if (!adjacentBefore)
|
|
124
|
+
break;
|
|
125
|
+
adjacentLinks.unshift(adjacentBefore);
|
|
126
|
+
currentFrom = adjacentBefore.from;
|
|
127
|
+
}
|
|
128
|
+
// Find adjacent links after (links starting where current link ends)
|
|
129
|
+
let currentTo = linkRange.to;
|
|
130
|
+
while (currentTo < doc.content.size) {
|
|
131
|
+
const linksStartingHere = linkStartingAt.get(currentTo) || [];
|
|
132
|
+
const adjacentAfter = linksStartingHere.find(range => range.mark.attrs.href === targetHref);
|
|
133
|
+
if (!adjacentAfter)
|
|
134
|
+
break;
|
|
135
|
+
adjacentLinks.push(adjacentAfter);
|
|
136
|
+
currentTo = adjacentAfter.to;
|
|
137
|
+
}
|
|
138
|
+
return adjacentLinks;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Extends selection to include full link marks and adjacent links with same href
|
|
88
142
|
* @param state EditorState
|
|
89
143
|
* @param from Start position
|
|
90
144
|
* @param to End position
|
|
@@ -93,17 +147,117 @@ export const getActiveLinkAttrsFromRange = (params) => {
|
|
|
93
147
|
export const extendSelectionToFullLinks = (state, from, to) => {
|
|
94
148
|
const { activeAttrs } = getActiveLinkAttrsFromRange({ state, from, to }) || {};
|
|
95
149
|
const linkMarkRanges = getLinkMarkRanges({ state, from, to });
|
|
96
|
-
if (linkMarkRanges.length === 0 || isEmpty(activeAttrs))
|
|
150
|
+
if (linkMarkRanges.length === 0 || isEmpty(activeAttrs)) {
|
|
97
151
|
return { from, to };
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const
|
|
152
|
+
}
|
|
153
|
+
// Get all document links and build lookup maps for adjacent search
|
|
154
|
+
const allDocLinks = getLinkMarkRanges({
|
|
155
|
+
state,
|
|
156
|
+
from: 0,
|
|
157
|
+
to: state.doc.content.size,
|
|
158
|
+
});
|
|
159
|
+
const { linkEndingAt, linkStartingAt } = buildLinkLookupMaps(allDocLinks);
|
|
160
|
+
// Check if single link has adjacents with same href
|
|
161
|
+
if (linkMarkRanges.length === 1) {
|
|
162
|
+
const singleLink = linkMarkRanges[0];
|
|
163
|
+
const { href } = singleLink.mark.attrs;
|
|
164
|
+
if (href) {
|
|
165
|
+
const hasAdjacentBefore = linkEndingAt
|
|
166
|
+
.get(singleLink.from)
|
|
167
|
+
?.some(range => range.mark.attrs.href === href);
|
|
168
|
+
const hasAdjacentAfter = linkStartingAt
|
|
169
|
+
.get(singleLink.to)
|
|
170
|
+
?.some(range => range.mark.attrs.href === href);
|
|
171
|
+
if (!hasAdjacentBefore && !hasAdjacentAfter) {
|
|
172
|
+
return {
|
|
173
|
+
from: singleLink.from,
|
|
174
|
+
to: singleLink.to,
|
|
175
|
+
linkAttrs: singleLink.mark.attrs,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Collect all link ranges including adjacent ones with same href
|
|
181
|
+
const allLinkRanges = [];
|
|
182
|
+
const processedRanges = new Set();
|
|
183
|
+
for (const linkRange of linkMarkRanges) {
|
|
184
|
+
const rangeKey = `${linkRange.from}-${linkRange.to}`;
|
|
185
|
+
if (processedRanges.has(rangeKey))
|
|
186
|
+
continue;
|
|
187
|
+
const { href } = linkRange.mark.attrs;
|
|
188
|
+
if (!href) {
|
|
189
|
+
allLinkRanges.push(linkRange);
|
|
190
|
+
processedRanges.add(rangeKey);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
// Find all adjacent links with same href
|
|
194
|
+
const adjacentLinks = findAdjacentLinksWithSameHref(linkRange, href, linkEndingAt, linkStartingAt, state.doc);
|
|
195
|
+
adjacentLinks.forEach(range => {
|
|
196
|
+
const key = `${range.from}-${range.to}`;
|
|
197
|
+
if (!processedRanges.has(key)) {
|
|
198
|
+
allLinkRanges.push(range);
|
|
199
|
+
processedRanges.add(key);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Calculate final range from all collected links
|
|
204
|
+
const newFrom = Math.min(...allLinkRanges.map(range => range.from), from);
|
|
205
|
+
const newTo = Math.max(...allLinkRanges.map(range => range.to), to);
|
|
101
206
|
return {
|
|
102
207
|
from: newFrom,
|
|
103
208
|
to: newTo,
|
|
104
209
|
linkAttrs: activeAttrs,
|
|
105
210
|
};
|
|
106
211
|
};
|
|
212
|
+
/**
|
|
213
|
+
* Gets all full link groups in the document (adjacent links with same href are grouped)
|
|
214
|
+
* @param state EditorState
|
|
215
|
+
* @returns Array of link groups with attrs and content
|
|
216
|
+
*/
|
|
217
|
+
export const getAllFullLinkGroups = (state) => {
|
|
218
|
+
const { doc } = state;
|
|
219
|
+
// Get all link ranges in document
|
|
220
|
+
const allLinks = getLinkMarkRanges({
|
|
221
|
+
state,
|
|
222
|
+
from: 0,
|
|
223
|
+
to: doc.content.size,
|
|
224
|
+
});
|
|
225
|
+
if (allLinks.length === 0)
|
|
226
|
+
return [];
|
|
227
|
+
// Build lookup maps for adjacent link search
|
|
228
|
+
const { linkEndingAt, linkStartingAt } = buildLinkLookupMaps(allLinks);
|
|
229
|
+
// Track processed ranges to avoid duplicates
|
|
230
|
+
const processedRanges = new Set();
|
|
231
|
+
const linkGroups = [];
|
|
232
|
+
// Process each link and find adjacent links with same href
|
|
233
|
+
for (const link of allLinks) {
|
|
234
|
+
const rangeKey = `${link.from}-${link.to}`;
|
|
235
|
+
if (processedRanges.has(rangeKey))
|
|
236
|
+
continue;
|
|
237
|
+
const { href } = link.mark.attrs;
|
|
238
|
+
if (!href) {
|
|
239
|
+
// Link without href, process individually
|
|
240
|
+
const content = textBetween(state, link.from, link.to);
|
|
241
|
+
linkGroups.push({ attrs: link.mark.attrs, content });
|
|
242
|
+
processedRanges.add(rangeKey);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
// Find all adjacent links with same href
|
|
246
|
+
const adjacentLinks = findAdjacentLinksWithSameHref(link, href, linkEndingAt, linkStartingAt, doc);
|
|
247
|
+
// Mark all adjacent links as processed
|
|
248
|
+
adjacentLinks.forEach(adjLink => {
|
|
249
|
+
processedRanges.add(`${adjLink.from}-${adjLink.to}`);
|
|
250
|
+
});
|
|
251
|
+
// Calculate full link range
|
|
252
|
+
const fullFrom = adjacentLinks[0].from;
|
|
253
|
+
const fullTo = adjacentLinks[adjacentLinks.length - 1].to;
|
|
254
|
+
// Get content from full link range
|
|
255
|
+
const content = textBetween(state, fullFrom, fullTo);
|
|
256
|
+
// Add link group with attrs from first link and full content
|
|
257
|
+
linkGroups.push({ attrs: adjacentLinks[0].mark.attrs, content });
|
|
258
|
+
}
|
|
259
|
+
return linkGroups;
|
|
260
|
+
};
|
|
107
261
|
/**
|
|
108
262
|
* Handles link actions (create or edit)
|
|
109
263
|
* @param view EditorView instance
|
|
@@ -121,7 +275,7 @@ export function handleLinkAction(view, linkHandler) {
|
|
|
121
275
|
view.dispatch(tr.setSelection(TextSelection.create(tr.doc, linkRange.from, linkRange.to)));
|
|
122
276
|
linkHandler?.edit?.({
|
|
123
277
|
attrs: linkMark.attrs,
|
|
124
|
-
selectionText:
|
|
278
|
+
selectionText: textBetween(state, linkRange.from, linkRange.to),
|
|
125
279
|
});
|
|
126
280
|
return;
|
|
127
281
|
}
|
|
@@ -129,7 +283,7 @@ export function handleLinkAction(view, linkHandler) {
|
|
|
129
283
|
const { from: newFrom, to: newTo, linkAttrs } = extendSelectionToFullLinks(state, from, to);
|
|
130
284
|
// Update selection to include full links
|
|
131
285
|
view.dispatch(tr.setSelection(TextSelection.create(tr.doc, newFrom, newTo)));
|
|
132
|
-
const selectedText =
|
|
286
|
+
const selectedText = textBetween(state, newFrom, newTo);
|
|
133
287
|
if (linkAttrs) {
|
|
134
288
|
linkHandler?.edit?.({
|
|
135
289
|
attrs: linkAttrs,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isTextSelection } from '@tiptap/core';
|
|
2
2
|
import { isNoSelection } from './selection';
|
|
3
3
|
import { isCursorInLink } from './link';
|
|
4
|
+
import { textBetween } from './documentState';
|
|
4
5
|
/**
|
|
5
6
|
* Default function to determine if bubble menu should be shown
|
|
6
7
|
* @param params Object containing editor state and view information
|
|
@@ -19,7 +20,7 @@ export const defaultShouldShowBubbleMenu = (params) => {
|
|
|
19
20
|
// Doubleclick an empty paragraph returns a node size of 2.
|
|
20
21
|
// So we check also for an empty text size.
|
|
21
22
|
// BUT: if it's an atom node, we should still show the bubble menu
|
|
22
|
-
const isEmptyTextBlock = !
|
|
23
|
+
const isEmptyTextBlock = !textBetween(state, from, to).length && isTextSelection(state.selection) && !isAtomNode;
|
|
23
24
|
// When clicking on a element inside the bubble menu the editor "blur" event
|
|
24
25
|
// is called and the bubble menu item is focussed. In this case we should
|
|
25
26
|
// consider the menu as part of the editor and keep showing the menu
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isNodeSelection, isTextSelection } from '@tiptap/core';
|
|
2
|
+
import { textBetween } from './documentState';
|
|
2
3
|
/**
|
|
3
4
|
* Kiểm tra xem có selection nào trong tài liệu hay không
|
|
4
5
|
* @param state EditorState của Tiptap/ProseMirror
|
|
@@ -13,7 +14,7 @@ export const isNoSelection = (state) => {
|
|
|
13
14
|
const { from, to } = selection;
|
|
14
15
|
if (from === to)
|
|
15
16
|
return true;
|
|
16
|
-
const selectedText =
|
|
17
|
+
const selectedText = textBetween(state, from, to);
|
|
17
18
|
return selectedText.length === 0;
|
|
18
19
|
}
|
|
19
20
|
// Nếu là node selection, thì có selection
|
|
@@ -29,7 +30,7 @@ export const isNoSelection = (state) => {
|
|
|
29
30
|
export const getSelectionText = (state) => {
|
|
30
31
|
const { selection } = state;
|
|
31
32
|
const { from, to } = selection;
|
|
32
|
-
return
|
|
33
|
+
return textBetween(state, from, to);
|
|
33
34
|
};
|
|
34
35
|
/**
|
|
35
36
|
* Checks if selection spans multiple nodes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { textBetween } from './documentState';
|
|
1
2
|
/**
|
|
2
3
|
* Handles smart tag actions (create or edit)
|
|
3
4
|
* @param event Mouse event from the action
|
|
@@ -13,7 +14,7 @@ export const handleSmartTagAction = (event, view, smartTagHandler) => {
|
|
|
13
14
|
smartTagHandler?.edit?.(smartTagId, event);
|
|
14
15
|
}
|
|
15
16
|
else {
|
|
16
|
-
const selectedText =
|
|
17
|
+
const selectedText = textBetween(state, from, to);
|
|
17
18
|
if (selectedText) {
|
|
18
19
|
smartTagHandler?.setNew?.({
|
|
19
20
|
selectionText: selectedText,
|
|
@@ -17,6 +17,6 @@ export * from './Login';
|
|
|
17
17
|
export * from './BasicLogin';
|
|
18
18
|
export * from './Filter';
|
|
19
19
|
export { ActivityTimeline, type ActivityTimeLineProps } from './ActivityTimeline';
|
|
20
|
-
export { TextEditor, TextEditorProvider, type TextEditorProps, type TextEditorRef, type TextEditorJSONContent, type TextEditorProviderProps, type TextEditorProviderRefHandler, type TextEditorComponentsRender, type FontConfig, CUSTOM_LINK_EXTENSION_NAME, } from './TextEditor';
|
|
20
|
+
export { TextEditor, TextEditorProvider, type TextEditorWithProviderRef, type TextEditorAllProps, type TextEditorProps, type TextEditorRef, type TextEditorJSONContent, type TextEditorProviderProps, type TextEditorProviderRefHandler, type TextEditorComponentsRender, type FontConfig, CUSTOM_LINK_EXTENSION_NAME, } from './TextEditor';
|
|
21
21
|
export { SQLGeneration, SQLGenerationIntegrations, SQLGenerationProvider, useSQLGenerationStore, type SQLGenerationProps, type SQLGenerationProviderProps, } from './SQLGeneration';
|
|
22
22
|
export { WhatsappMobile, SAMPLE_PREVIEW } from './PreviewCollections';
|
package/es/hooks/index.d.ts
CHANGED
package/es/hooks/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export const getListingSavedMedia = async (domainUrl, slug, infos, page = 1) =>
|
|
|
7
7
|
try {
|
|
8
8
|
const { type = '', ...restInfos } = infos || {};
|
|
9
9
|
const { data } = await services.mediaTemplateDesign.getList({
|
|
10
|
-
API_HOST: `${domainUrl}
|
|
10
|
+
API_HOST: `${domainUrl}${slug ? `/${slug}` : ''}/saved-media/index?type=${type}&page=${page}&limit=10`,
|
|
11
11
|
}, restInfos);
|
|
12
12
|
let savedImages = data?.data || [];
|
|
13
13
|
savedImages = savedImages.map((savedImage) => new SavedMedia(savedImage));
|
|
@@ -20,7 +20,7 @@ export const getListingSavedMedia = async (domainUrl, slug, infos, page = 1) =>
|
|
|
20
20
|
export const createSavedMedia = (domainUrl, slug, infos, data) => {
|
|
21
21
|
try {
|
|
22
22
|
return services.mediaTemplateDesign.create({
|
|
23
|
-
API_HOST: `${domainUrl}
|
|
23
|
+
API_HOST: `${domainUrl}${slug ? `/${slug}` : ''}/saved-media/index`,
|
|
24
24
|
...data,
|
|
25
25
|
}, infos);
|
|
26
26
|
}
|
|
@@ -31,7 +31,7 @@ export const createSavedMedia = (domainUrl, slug, infos, data) => {
|
|
|
31
31
|
export const deleteSavedMedia = (domainUrl, slug, infos, id) => {
|
|
32
32
|
try {
|
|
33
33
|
return services.mediaTemplateDesign.create({
|
|
34
|
-
API_HOST: `${domainUrl}
|
|
34
|
+
API_HOST: `${domainUrl}${slug ? `/${slug}` : ''}/saved-media/index/update-status`,
|
|
35
35
|
media_id: [id],
|
|
36
36
|
status: 80,
|
|
37
37
|
}, infos);
|
|
@@ -52,7 +52,7 @@ export const uploadFile = async (domainUrl, slug, infos, files) => {
|
|
|
52
52
|
fileType = 'origin-file';
|
|
53
53
|
}
|
|
54
54
|
const result = await services.mediaTemplateDesign.upload({
|
|
55
|
-
API_HOST: `${domainUrl}
|
|
55
|
+
API_HOST: `${domainUrl}${slug ? `/${slug}` : ''}/file-upload/${fileType}`,
|
|
56
56
|
formData,
|
|
57
57
|
}, restInfos);
|
|
58
58
|
const uploadData = result ? result.data?.data : null;
|
package/es/types/index.d.ts
CHANGED
|
@@ -34,8 +34,8 @@ export * from './actionsButton';
|
|
|
34
34
|
export * from './condition';
|
|
35
35
|
export * from './api';
|
|
36
36
|
export * from './date';
|
|
37
|
-
export * from './unsubscribe';
|
|
38
37
|
export * from './auth';
|
|
38
|
+
export * from './unsubscribe';
|
|
39
39
|
export type PayloadInfo = {
|
|
40
40
|
url?: string;
|
|
41
41
|
userId?: string;
|
package/es/types/index.js
CHANGED
package/es/utils/common.d.ts
CHANGED
|
@@ -171,5 +171,5 @@ export declare const antsomiClsx: (componentName: string) => (className: string)
|
|
|
171
171
|
* @returns A spreadable object of data-attributes
|
|
172
172
|
*/
|
|
173
173
|
export declare const dataAttrArrayToObject: (attributes?: DataAttributes) => Record<string, string>;
|
|
174
|
-
export declare function compareStrings(a: any, b: any): number;
|
|
175
174
|
export declare function arrayToMapByProperty<T extends object, K extends keyof T>(array: T[], propertyName: K): Map<T[K], T>;
|
|
175
|
+
export declare function compareStrings(a: any, b: any): number;
|
package/es/utils/common.js
CHANGED
|
@@ -780,9 +780,6 @@ export const dataAttrArrayToObject = (attributes = []) => attributes.reduce((out
|
|
|
780
780
|
// return the object
|
|
781
781
|
return output;
|
|
782
782
|
}, {});
|
|
783
|
-
export function compareStrings(a, b) {
|
|
784
|
-
return String(a).localeCompare(String(b));
|
|
785
|
-
}
|
|
786
783
|
export function arrayToMapByProperty(array, propertyName) {
|
|
787
784
|
// Đảm bảo đầu vào là một mảng và không rỗng
|
|
788
785
|
if (!Array.isArray(array) || array.length === 0) {
|
|
@@ -798,3 +795,6 @@ export function arrayToMapByProperty(array, propertyName) {
|
|
|
798
795
|
// new Map() có thể nhận mảng này để khởi tạo Map
|
|
799
796
|
return new Map(Object.entries(keyedObject));
|
|
800
797
|
}
|
|
798
|
+
export function compareStrings(a, b) {
|
|
799
|
+
return String(a).localeCompare(String(b));
|
|
800
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antscorp/antsomi-ui",
|
|
3
|
-
"version": "1.3.7-beta.
|
|
3
|
+
"version": "1.3.7-beta.21",
|
|
4
4
|
"description": "An enterprise-class UI design language and React UI library.",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"dist/*",
|
|
@@ -93,11 +93,6 @@
|
|
|
93
93
|
"@tiptap/react": "3.0.7",
|
|
94
94
|
"@tiptap/starter-kit": "3.0.7",
|
|
95
95
|
"@tiptap/suggestion": "3.0.7",
|
|
96
|
-
"@types/currency-formatter": "1.5.1",
|
|
97
|
-
"@types/react-custom-scrollbars": "^4.0.13",
|
|
98
|
-
"@types/react-frame-component": "^4.1.6",
|
|
99
|
-
"@types/react-router-dom": "^5.3.3",
|
|
100
|
-
"@types/react-window": "^1.8.8",
|
|
101
96
|
"@yaireo/tagify": "^4.31.2",
|
|
102
97
|
"ace-builds": "1.4.14",
|
|
103
98
|
"animate.css": "^4.1.1",
|
|
@@ -153,8 +148,7 @@
|
|
|
153
148
|
"react-virtualized-auto-sizer": "^1.0.24",
|
|
154
149
|
"react-window": "^1.8.10",
|
|
155
150
|
"rehype-highlight": "^6.0.0",
|
|
156
|
-
"remark-gfm": "^
|
|
157
|
-
"remark-gfm-alias-story": "npm:remark-gfm@4.0.0",
|
|
151
|
+
"remark-gfm": "^4",
|
|
158
152
|
"reselect": "^5.1.1",
|
|
159
153
|
"socket.io-client": "^4.7.5",
|
|
160
154
|
"string-replace-to-array": "^2.1.0",
|
|
@@ -171,7 +165,7 @@
|
|
|
171
165
|
"devDependencies": {
|
|
172
166
|
"@antscorp/antsomi-constants": "1.0.8-beta.1",
|
|
173
167
|
"@antscorp/eslint-config-antsomi": "1.0.4",
|
|
174
|
-
"@antscorp/antsomi-locales": "^1.0.
|
|
168
|
+
"@antscorp/antsomi-locales": "^1.0.79",
|
|
175
169
|
"@babel/cli": "^7.23.4",
|
|
176
170
|
"@babel/core": "^7.21.3",
|
|
177
171
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
@@ -186,17 +180,11 @@
|
|
|
186
180
|
"@babel/preset-typescript": "^7.23.3",
|
|
187
181
|
"@commitlint/cli": "17.5.0",
|
|
188
182
|
"@commitlint/config-conventional": "17.4.4",
|
|
189
|
-
"@storybook/addon-docs": "^
|
|
190
|
-
"@storybook/addon-
|
|
191
|
-
"@storybook/addon-
|
|
192
|
-
"@storybook/addon-
|
|
193
|
-
"@storybook/
|
|
194
|
-
"@storybook/blocks": "^8.6.9",
|
|
195
|
-
"@storybook/manager-api": "^8.6.9",
|
|
196
|
-
"@storybook/react": "^8.6.9",
|
|
197
|
-
"@storybook/react-webpack5": "^8.6.9",
|
|
198
|
-
"@storybook/test": "^8.6.9",
|
|
199
|
-
"@storybook/theming": "^8.6.9",
|
|
183
|
+
"@storybook/addon-docs": "^9.1.10",
|
|
184
|
+
"@storybook/addon-links": "^9.1.10",
|
|
185
|
+
"@storybook/addon-styling-webpack": "^2.0.0",
|
|
186
|
+
"@storybook/addon-webpack5-compiler-babel": "^3.0.6",
|
|
187
|
+
"@storybook/react-webpack5": "^9.1.10",
|
|
200
188
|
"@testing-library/dom": "^10.4.0",
|
|
201
189
|
"@testing-library/jest-dom": "^6.5.0",
|
|
202
190
|
"@testing-library/react": "^16.0.0",
|
|
@@ -247,7 +235,7 @@
|
|
|
247
235
|
"eslint-plugin-prettier": "^5.2.1",
|
|
248
236
|
"eslint-plugin-react": "^7.32.2",
|
|
249
237
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
250
|
-
"eslint-plugin-storybook": "^
|
|
238
|
+
"eslint-plugin-storybook": "^9.1.10",
|
|
251
239
|
"file-loader": "^6.2.0",
|
|
252
240
|
"googleapis": "^142.0.0",
|
|
253
241
|
"husky": "^8.0.3",
|
|
@@ -264,7 +252,7 @@
|
|
|
264
252
|
"react-router-dom": "5.1.0 || 6.14.2",
|
|
265
253
|
"sass": "^1.77.8",
|
|
266
254
|
"sass-loader": "^16.0.1",
|
|
267
|
-
"storybook": "^
|
|
255
|
+
"storybook": "^9.1.10",
|
|
268
256
|
"style-loader": "^4.0.0",
|
|
269
257
|
"styled-components": "^5.3.9",
|
|
270
258
|
"terser-webpack-plugin": "^5.3.10",
|
|
@@ -288,6 +276,6 @@
|
|
|
288
276
|
"react-dom": ">=16.9.0",
|
|
289
277
|
"react-router-dom": ">= 5.1.0",
|
|
290
278
|
"@antscorp/antsomi-constants": ">=1.0.8-beta.1",
|
|
291
|
-
"@antscorp/antsomi-locales": ">=1.0.
|
|
279
|
+
"@antscorp/antsomi-locales": ">=1.0.79"
|
|
292
280
|
}
|
|
293
281
|
}
|