@antscorp/antsomi-ui 1.3.7-beta.3 → 1.3.7-beta.31
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/InputDynamic/InputDynamic.js +3 -3
- package/es/components/atoms/index.d.ts +0 -2
- package/es/components/atoms/index.js +0 -2
- package/es/components/molecules/AddDynamicContent/AddDynamicContent.js +28 -2
- package/es/components/molecules/AddDynamicContent/constants.d.ts +2 -0
- package/es/components/molecules/AddDynamicContent/constants.js +2 -0
- package/es/components/molecules/EmojiPopover/EmojiPopover.d.ts +1 -0
- package/es/components/molecules/EmojiPopover/EmojiPopover.js +2 -2
- package/es/components/molecules/EmojiPopover/styled.d.ts +2 -2
- package/es/components/molecules/EmojiPopover/styled.js +1 -1
- package/es/components/molecules/SearchPopover/SearchPopover.js +2 -2
- package/es/components/molecules/SearchPopover/styled.d.ts +12 -1
- package/es/components/molecules/SearchPopover/styled.js +1 -2
- package/es/components/molecules/SearchPopover/types.d.ts +4 -3
- package/es/components/molecules/TagifyInput/TagifyInput.js +55 -19
- package/es/components/molecules/TagifyInput/types.d.ts +20 -1
- package/es/components/molecules/TagifyInput/utils.d.ts +6 -1
- package/es/components/molecules/TagifyInput/utils.js +19 -0
- package/es/components/molecules/VirtualizedMenu/VirtualizedMenu.d.ts +1 -0
- package/es/components/molecules/VirtualizedMenu/components/Item/Item.js +3 -7
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.d.ts +10 -10
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.js +46 -327
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/index.d.ts +9 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/index.js +5 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useFocusManagement.d.ts +23 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useFocusManagement.js +81 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useItemInteraction.d.ts +24 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useItemInteraction.js +32 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useKeyboardNavigation.d.ts +26 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useKeyboardNavigation.js +93 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useTreeState.d.ts +24 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useTreeState.js +94 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useVisibleItems.d.ts +7 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/hooks/useVisibleItems.js +132 -0
- package/es/components/molecules/VirtualizedMenu/styled.js +14 -3
- package/es/components/molecules/VirtualizedMenu/types.d.ts +1 -0
- package/es/components/molecules/VirtualizedMenu/utils.d.ts +1 -0
- package/es/components/molecules/VirtualizedMenu/utils.js +1 -0
- package/es/components/organism/ActivityTimeline/ActivityTimeline.js +3 -3
- 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.js +7 -6
- package/es/components/organism/TextEditor/TextEditor.d.ts +9 -2
- package/es/components/organism/TextEditor/TextEditor.js +181 -40
- package/es/components/organism/TextEditor/constants.d.ts +9 -0
- package/es/components/organism/TextEditor/constants.js +66 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.d.ts +6 -128
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.js +7 -292
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu.d.ts +1 -1
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu.js +4 -0
- package/es/components/organism/TextEditor/extensions/Link.js +3 -3
- package/es/components/organism/TextEditor/extensions/ListItem.d.ts +10 -0
- package/es/components/organism/TextEditor/extensions/ListItem.js +93 -0
- package/es/components/organism/TextEditor/extensions/SmartTag.d.ts +5 -6
- package/es/components/organism/TextEditor/extensions/SmartTag.js +94 -2
- package/es/components/organism/TextEditor/hooks/useColorSet.js +7 -0
- package/es/components/organism/TextEditor/hooks/useMarkTracking.js +2 -1
- package/es/components/organism/TextEditor/index.d.ts +7 -5
- package/es/components/organism/TextEditor/index.scss +4 -7
- package/es/components/organism/TextEditor/provider.d.ts +1 -0
- package/es/components/organism/TextEditor/provider.js +6 -3
- package/es/components/organism/TextEditor/store.d.ts +11 -4
- package/es/components/organism/TextEditor/store.js +22 -2
- package/es/components/organism/TextEditor/stories/WithOldDynAndLink/froala-legacy-format.settings.json +95 -0
- package/es/components/organism/TextEditor/stories/WithOldDynAndLink/shared.d.ts +111 -0
- package/es/components/organism/TextEditor/stories/WithOldDynAndLink/shared.js +82 -0
- package/es/components/organism/TextEditor/stories/shared.d.ts +64 -0
- package/es/components/organism/TextEditor/stories/shared.js +57 -0
- package/es/components/organism/TextEditor/styled.d.ts +1 -1
- package/es/components/organism/TextEditor/styled.js +1 -0
- package/es/components/organism/TextEditor/types.d.ts +153 -9
- package/es/components/organism/TextEditor/types.js +1 -0
- package/es/components/organism/TextEditor/ui/BubbleMenu/BubbleMenu.d.ts +2 -1
- package/es/components/organism/TextEditor/ui/BubbleMenu/BubbleMenu.js +80 -51
- package/es/components/organism/TextEditor/ui/Emoji/EmojiList.js +1 -1
- package/es/components/organism/TextEditor/ui/Emoji/suggestion.d.ts +1 -1
- package/es/components/organism/TextEditor/ui/Emoji/suggestion.js +2 -2
- package/es/components/organism/TextEditor/ui/FontPopover/FontPopover.js +12 -2
- package/es/components/organism/TextEditor/ui/LinkInsertForm/LinkInsertForm.d.ts +16 -0
- package/es/components/organism/TextEditor/ui/LinkInsertForm/LinkInsertForm.js +61 -0
- package/es/components/organism/TextEditor/ui/LinkInsertForm/index.d.ts +2 -0
- package/es/components/organism/TextEditor/ui/LinkInsertForm/index.js +1 -0
- package/es/components/organism/TextEditor/ui/LinkPopover/LinkPopover.d.ts +9 -0
- package/es/components/organism/TextEditor/ui/LinkPopover/LinkPopover.js +126 -0
- package/es/components/organism/TextEditor/ui/LinkPopover/index.d.ts +2 -0
- package/es/components/organism/TextEditor/ui/LinkPopover/index.js +1 -0
- package/es/components/organism/TextEditor/ui/Popover/Popover.js +1 -1
- package/es/components/organism/TextEditor/ui/TextAlignSelect/TextAlignSelect.js +1 -3
- package/es/components/organism/TextEditor/ui/Toolbar/{Toolbar.d.ts → FormattingToolbar.d.ts} +3 -4
- package/es/components/organism/TextEditor/ui/Toolbar/FormattingToolbar.js +85 -0
- package/es/components/organism/TextEditor/ui/Toolbar/LinkPreviewToolbar.d.ts +10 -0
- package/es/components/organism/TextEditor/ui/Toolbar/LinkPreviewToolbar.js +39 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/EmojiAction.js +4 -3
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontFamilyAction.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontFamilyAction.js +2 -2
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontSizeAction.js +6 -1
- package/es/components/organism/TextEditor/ui/Toolbar/index.d.ts +2 -1
- package/es/components/organism/TextEditor/ui/Toolbar/index.js +2 -1
- 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 +23 -35
- package/es/components/organism/TextEditor/ui/BubbleToolbar/BubbleToolbar.d.ts +0 -1
- package/es/components/organism/TextEditor/ui/BubbleToolbar/BubbleToolbar.js +0 -1
- package/es/components/organism/TextEditor/ui/BubbleToolbar/index.d.ts +0 -0
- package/es/components/organism/TextEditor/ui/BubbleToolbar/index.js +0 -1
- package/es/components/organism/TextEditor/ui/Toolbar/Toolbar.js +0 -39
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ANTSOMI_COMPONENT_PREFIX_CLS } from '@antscorp/antsomi-ui/es/constants';
|
|
3
|
-
import { useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
|
|
3
|
+
import { useDeepCompareEffect, useDeepCompareMemo } from '@antscorp/antsomi-ui/es/hooks';
|
|
4
4
|
import SubScript from '@tiptap/extension-subscript';
|
|
5
5
|
import Superscript from '@tiptap/extension-superscript';
|
|
6
6
|
import TextAlign from '@tiptap/extension-text-align';
|
|
7
7
|
import { TextStyleKit } from '@tiptap/extension-text-style';
|
|
8
|
-
import { Selection } from '@tiptap/extensions';
|
|
8
|
+
import { Selection, Focus } from '@tiptap/extensions';
|
|
9
9
|
import { useEditor } from '@tiptap/react';
|
|
10
10
|
import StarterKit from '@tiptap/starter-kit';
|
|
11
11
|
import clsx from 'clsx';
|
|
12
|
-
import { isBoolean
|
|
13
|
-
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, } from 'react';
|
|
12
|
+
import { isBoolean } from 'lodash';
|
|
13
|
+
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, } from 'react';
|
|
14
14
|
import { useDebouncedCallback } from 'use-debounce';
|
|
15
15
|
import { DEFAULT_TEXT_STYLE } from './constants';
|
|
16
16
|
import { BackgroundColor } from './extensions/BackgroundColor';
|
|
@@ -23,29 +23,53 @@ import { Indent } from './extensions/Indent';
|
|
|
23
23
|
import { LetterSpacing } from './extensions/LetterSpacing';
|
|
24
24
|
import { LineHeight } from './extensions/LineHeight';
|
|
25
25
|
import { CustomLink } from './extensions/Link';
|
|
26
|
+
import { CustomListItem } from './extensions/ListItem';
|
|
26
27
|
import { CustomOrderedList } from './extensions/OrderedList';
|
|
27
28
|
import { SmartTag } from './extensions/SmartTag';
|
|
28
29
|
import { TextTransform } from './extensions/TextTransform';
|
|
29
30
|
import { CustomUnorderedList } from './extensions/UnorderedList';
|
|
30
31
|
import { ClearFormatting } from './extensions/ClearFormatting';
|
|
31
|
-
import { useTextEditorStore } from './provider';
|
|
32
|
+
import { TextEditorProvider, useTextEditorStore, } from './provider';
|
|
32
33
|
import { StyledEditorContent } from './styled';
|
|
34
|
+
import { isSmartTagNode, } from './types';
|
|
33
35
|
import { emojiSuggestion } from './ui/Emoji';
|
|
34
|
-
import {
|
|
35
|
-
import { analyzeFont, defaultShouldShowBubbleMenu, handleLinkAction, handleSmartTagAction, isShowLinkToolbar, safeParseHTMLContent, htmlSerializerForOutput, } from './utils';
|
|
36
|
+
import { LinkPreviewToolbar, FormattingToolbar } from './ui/Toolbar';
|
|
37
|
+
import { analyzeFont, defaultShouldShowBubbleMenu, getAllFullLinkGroups, handleLinkAction, handleSmartTagAction, isShowLinkToolbar, safeParseHTMLContent, htmlSerializerForOutput, } from './utils';
|
|
36
38
|
import { BubbleMenu } from './ui/BubbleMenu';
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
39
|
+
import { LinkPopover } from './ui/LinkPopover';
|
|
40
|
+
const TextEditorInternal = memo(forwardRef((props, ref) => {
|
|
41
|
+
const { id, className, config, editable = true, initialContent = '', dataAttributes, onUpdateDebounced = 300, defaultTextStyle: defaultTextStyleProp, linkHandler: outerLinkHandler, smartTagHandler: outerSmartTagHandler, bubbleMenuProps, style, render, onUpdate, onFocus, onCreate, onChangeFont, } = props;
|
|
42
|
+
// Initialize bubbleMenuContainer with default value (document.body)
|
|
43
|
+
// This ensures BubbleMenu receives a valid appendTo prop on first render
|
|
44
|
+
const bubbleMenuContainer = useRef((() => {
|
|
45
|
+
const appendTo = bubbleMenuProps?.appendTo;
|
|
46
|
+
if (!appendTo)
|
|
47
|
+
return document.body;
|
|
48
|
+
return typeof appendTo === 'function' ? appendTo() : appendTo;
|
|
49
|
+
})());
|
|
50
|
+
const linkFormVisible = useTextEditorStore(state => state.linkFormState?.isVisible);
|
|
40
51
|
const setBubbleMenuContainer = useTextEditorStore(state => state.setBubbleMenuContainer);
|
|
52
|
+
const showLinkForm = useTextEditorStore(state => state.showLinkForm);
|
|
41
53
|
const defaultTextStyle = useDeepCompareMemo(() => ({
|
|
42
54
|
...DEFAULT_TEXT_STYLE,
|
|
43
55
|
...defaultTextStyleProp,
|
|
44
56
|
}), [defaultTextStyleProp]);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const bubbleMenuAppendTo = bubbleMenuProps?.appendTo;
|
|
59
|
+
// Default to document.body when no appendTo is provided
|
|
60
|
+
// This prevents bubble menu from being clipped by overflow containers
|
|
61
|
+
const el = bubbleMenuAppendTo
|
|
62
|
+
? typeof bubbleMenuAppendTo === 'function'
|
|
63
|
+
? bubbleMenuAppendTo()
|
|
64
|
+
: bubbleMenuAppendTo
|
|
65
|
+
: document.body;
|
|
66
|
+
setBubbleMenuContainer(el);
|
|
67
|
+
bubbleMenuContainer.current = el;
|
|
68
|
+
}, [bubbleMenuProps?.appendTo, setBubbleMenuContainer]);
|
|
45
69
|
const handleOnUpdateDebounce = useDebouncedCallback((editor) => {
|
|
46
|
-
const html = editor.getHTML();
|
|
47
70
|
const text = editor.getText();
|
|
48
71
|
const json = editor.getJSON();
|
|
72
|
+
const html = editor.getHTML();
|
|
49
73
|
onUpdate?.({
|
|
50
74
|
html: htmlSerializerForOutput(html),
|
|
51
75
|
text,
|
|
@@ -53,21 +77,40 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
53
77
|
});
|
|
54
78
|
}, onUpdateDebounced);
|
|
55
79
|
const contentRef = useRef(null);
|
|
80
|
+
// Compose linkHandler: merge outerLinkHandler with default handlers
|
|
81
|
+
// Allows partial override - user can provide only setNew or only edit
|
|
82
|
+
const linkHandler = useMemo(() => {
|
|
83
|
+
const defaultSetNew = ({ selectionText }) => {
|
|
84
|
+
showLinkForm('insert', {
|
|
85
|
+
url: '',
|
|
86
|
+
text: selectionText,
|
|
87
|
+
openInNewTab: false,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const defaultEdit = ({ attrs, selectionText, }) => {
|
|
91
|
+
showLinkForm('edit', {
|
|
92
|
+
url: attrs.href || '',
|
|
93
|
+
text: selectionText,
|
|
94
|
+
openInNewTab: attrs.target === '_blank',
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
setNew: outerLinkHandler?.setNew || defaultSetNew,
|
|
99
|
+
edit: outerLinkHandler?.edit || defaultEdit,
|
|
100
|
+
};
|
|
101
|
+
}, [outerLinkHandler, showLinkForm]);
|
|
56
102
|
const editor = useEditor({
|
|
57
103
|
extensions: [
|
|
58
104
|
StarterKit.configure({
|
|
59
105
|
link: false,
|
|
60
106
|
bulletList: false,
|
|
61
107
|
orderedList: false,
|
|
62
|
-
listItem:
|
|
63
|
-
HTMLAttributes: {
|
|
64
|
-
style: 'line-height:normal;',
|
|
65
|
-
},
|
|
66
|
-
},
|
|
108
|
+
listItem: false,
|
|
67
109
|
undoRedo: {
|
|
68
110
|
depth: 100,
|
|
69
111
|
},
|
|
70
112
|
}),
|
|
113
|
+
CustomListItem,
|
|
71
114
|
CustomUnorderedList,
|
|
72
115
|
CustomOrderedList,
|
|
73
116
|
FontWeight.configure({
|
|
@@ -107,7 +150,12 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
107
150
|
Selection.configure({
|
|
108
151
|
className: 'selection',
|
|
109
152
|
}),
|
|
110
|
-
|
|
153
|
+
Focus.configure({
|
|
154
|
+
className: 'has-focused',
|
|
155
|
+
}),
|
|
156
|
+
SmartTag.configure({
|
|
157
|
+
generateSmartTagId: config?.SmartTag?.generateId,
|
|
158
|
+
}),
|
|
111
159
|
TextAlign.configure({
|
|
112
160
|
types: ['heading', 'paragraph'],
|
|
113
161
|
}),
|
|
@@ -121,7 +169,7 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
121
169
|
Indent,
|
|
122
170
|
Emoji.configure({
|
|
123
171
|
suggestion: emojiSuggestion({
|
|
124
|
-
container:
|
|
172
|
+
container: bubbleMenuContainer.current,
|
|
125
173
|
}),
|
|
126
174
|
}),
|
|
127
175
|
ClearFormatting.configure({
|
|
@@ -141,6 +189,14 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
141
189
|
if (safeParseContent !== initialContent) {
|
|
142
190
|
editor.commands.setContent(safeParseContent);
|
|
143
191
|
}
|
|
192
|
+
const text = editor.getText();
|
|
193
|
+
const json = editor.getJSON();
|
|
194
|
+
const html = editor.getHTML();
|
|
195
|
+
onCreate?.({
|
|
196
|
+
html: htmlSerializerForOutput(html),
|
|
197
|
+
text,
|
|
198
|
+
json,
|
|
199
|
+
});
|
|
144
200
|
},
|
|
145
201
|
onUpdate: ({ editor }) => {
|
|
146
202
|
handleOnUpdateDebounce(editor);
|
|
@@ -154,7 +210,7 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
154
210
|
if (event.ctrlKey && event.key === 'k') {
|
|
155
211
|
// Add this line to prevent browser's default behavior.
|
|
156
212
|
event.preventDefault();
|
|
157
|
-
handleLinkAction(view,
|
|
213
|
+
handleLinkAction(view, linkHandler);
|
|
158
214
|
}
|
|
159
215
|
},
|
|
160
216
|
},
|
|
@@ -183,10 +239,15 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
183
239
|
return updatedAttrs;
|
|
184
240
|
})
|
|
185
241
|
.run(), [editor]);
|
|
186
|
-
const
|
|
242
|
+
const shouldShowLinkPreview = useCallback((params) => {
|
|
243
|
+
const { state } = params;
|
|
244
|
+
return isShowLinkToolbar(state);
|
|
245
|
+
}, []);
|
|
246
|
+
const shouldShowFormattingToolbar = useCallback((params) => {
|
|
187
247
|
const { state, view, element } = params;
|
|
248
|
+
// Don't show if link preview is visible
|
|
188
249
|
if (isShowLinkToolbar(state)) {
|
|
189
|
-
return
|
|
250
|
+
return false;
|
|
190
251
|
}
|
|
191
252
|
return defaultShouldShowBubbleMenu({
|
|
192
253
|
state,
|
|
@@ -203,9 +264,23 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
203
264
|
editor?.chain().blur().setTextSelection({ from: 0, to: 0 }).run();
|
|
204
265
|
}
|
|
205
266
|
}, [editor]);
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
267
|
+
const handleEachLinkGroup = useCallback(callback => {
|
|
268
|
+
if (!editor)
|
|
269
|
+
return;
|
|
270
|
+
const linkGroups = getAllFullLinkGroups(editor.state);
|
|
271
|
+
linkGroups.forEach(callback);
|
|
272
|
+
}, [editor]);
|
|
273
|
+
const handleEachSmartag = useCallback(callback => {
|
|
274
|
+
if (!editor)
|
|
275
|
+
return;
|
|
276
|
+
const { state } = editor;
|
|
277
|
+
const { doc } = state;
|
|
278
|
+
doc.descendants(node => {
|
|
279
|
+
if (isSmartTagNode(node)) {
|
|
280
|
+
callback(node.attrs);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}, [editor]);
|
|
209
284
|
useImperativeHandle(ref, () => ({
|
|
210
285
|
setLink: params => {
|
|
211
286
|
editor?.chain().setCustomLink(params).run();
|
|
@@ -226,6 +301,8 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
226
301
|
})
|
|
227
302
|
.run();
|
|
228
303
|
},
|
|
304
|
+
eachLinkGroup: handleEachLinkGroup,
|
|
305
|
+
eachSmartag: handleEachSmartag,
|
|
229
306
|
setSmartTag: handleSetSmartTag,
|
|
230
307
|
deleteSmartTag: handleDeleteSmartTag,
|
|
231
308
|
updateSmartTagAttrs: handleUpdateSmartTagAttrs,
|
|
@@ -236,23 +313,87 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
236
313
|
if (!editor) {
|
|
237
314
|
return null;
|
|
238
315
|
}
|
|
316
|
+
const bubbleMenus = (bubbleMenuProps?.enabled ?? true) ? (_jsxs(_Fragment, { children: [_jsx(LinkPopover, { editor: editor }), !linkFormVisible && (_jsxs(_Fragment, { children: [_jsx(BubbleMenu, { pluginKey: "linkPreviewBubbleMenu", ...bubbleMenuProps, appendTo: bubbleMenuContainer.current, editor: editor, shouldShow: shouldShowLinkPreview, children: _jsx(LinkPreviewToolbar, { editor: editor, linkHanlder: {
|
|
317
|
+
onUpsert: () => {
|
|
318
|
+
handleLinkAction(editor.view, linkHandler);
|
|
319
|
+
},
|
|
320
|
+
}, render: render }) }), _jsx(BubbleMenu, { pluginKey: "formattingBubbleMenu", ...bubbleMenuProps, appendTo: bubbleMenuContainer.current, editor: editor, shouldShow: shouldShowFormattingToolbar, children: _jsx(FormattingToolbar, { config: config, editor: editor, defaultTextStyle: defaultTextStyle, linkHanlder: {
|
|
321
|
+
onUpsert: () => {
|
|
322
|
+
handleLinkAction(editor.view, linkHandler);
|
|
323
|
+
},
|
|
324
|
+
}, smartTagHandler: {
|
|
325
|
+
onUpsert: (event) => {
|
|
326
|
+
handleSmartTagAction(event, editor.view, outerSmartTagHandler);
|
|
327
|
+
},
|
|
328
|
+
}, onChangeFont: ({ font, weight }) => {
|
|
329
|
+
onChangeFont?.({
|
|
330
|
+
font,
|
|
331
|
+
weight,
|
|
332
|
+
analysis: analyzeFont(font),
|
|
333
|
+
});
|
|
334
|
+
} }) })] }))] })) : null;
|
|
239
335
|
return (_jsxs(_Fragment, { children: [_jsx(StyledEditorContent, { className: clsx(`${ANTSOMI_COMPONENT_PREFIX_CLS}-text-editor`, className), "$textStyle": defaultTextStyle, style: {
|
|
240
336
|
// Inline styles apply to inner html elements (support email client)
|
|
241
|
-
...
|
|
337
|
+
...defaultTextStyle,
|
|
242
338
|
...style,
|
|
243
|
-
}, id: id, ref: contentRef, editor: editor, ...dataAttributes }),
|
|
244
|
-
onUpsert: () => {
|
|
245
|
-
handleLinkAction(editor.view, outerLinkHandler);
|
|
246
|
-
},
|
|
247
|
-
}, smartTagHandler: {
|
|
248
|
-
onUpsert: (event) => {
|
|
249
|
-
handleSmartTagAction(event, editor.view, outerSmartTagHandler);
|
|
250
|
-
},
|
|
251
|
-
}, render: render, onChangeFont: ({ font, weight }) => {
|
|
252
|
-
onChangeFont?.({
|
|
253
|
-
font,
|
|
254
|
-
weight,
|
|
255
|
-
analysis: analyzeFont(font),
|
|
256
|
-
});
|
|
257
|
-
} })) })] }));
|
|
339
|
+
}, id: id, ref: contentRef, editor: editor, ...dataAttributes }), bubbleMenus] }));
|
|
258
340
|
}));
|
|
341
|
+
TextEditorInternal.displayName = 'TextEditorInternal';
|
|
342
|
+
const TextEditorWithProvider = forwardRef((props, ref) => {
|
|
343
|
+
const { colors, onChangeColors, ...editorProps } = props;
|
|
344
|
+
const providerRef = useRef(null);
|
|
345
|
+
const editorRef = useRef(null);
|
|
346
|
+
// Sync external colors to internal store
|
|
347
|
+
useDeepCompareEffect(() => {
|
|
348
|
+
if (colors !== undefined) {
|
|
349
|
+
providerRef.current?.updateColors?.(colors);
|
|
350
|
+
}
|
|
351
|
+
}, [colors]);
|
|
352
|
+
useImperativeHandle(ref, () => ({
|
|
353
|
+
// Forward TextEditorRef methods - accessed at call time
|
|
354
|
+
get style() {
|
|
355
|
+
return editorRef.current?.style;
|
|
356
|
+
},
|
|
357
|
+
get editor() {
|
|
358
|
+
return editorRef.current?.editor ?? null;
|
|
359
|
+
},
|
|
360
|
+
get setLink() {
|
|
361
|
+
return editorRef.current.setLink;
|
|
362
|
+
},
|
|
363
|
+
get deleteLink() {
|
|
364
|
+
return editorRef.current.deleteLink;
|
|
365
|
+
},
|
|
366
|
+
get updateLinkAttrs() {
|
|
367
|
+
return editorRef.current.updateLinkAttrs;
|
|
368
|
+
},
|
|
369
|
+
get updateLinkText() {
|
|
370
|
+
return editorRef.current.updateLinkText;
|
|
371
|
+
},
|
|
372
|
+
get eachLinkGroup() {
|
|
373
|
+
return editorRef.current.eachLinkGroup;
|
|
374
|
+
},
|
|
375
|
+
get eachSmartag() {
|
|
376
|
+
return editorRef.current.eachSmartag;
|
|
377
|
+
},
|
|
378
|
+
get setSmartTag() {
|
|
379
|
+
return editorRef.current.setSmartTag;
|
|
380
|
+
},
|
|
381
|
+
get deleteSmartTag() {
|
|
382
|
+
return editorRef.current.deleteSmartTag;
|
|
383
|
+
},
|
|
384
|
+
get updateSmartTagAttrs() {
|
|
385
|
+
return editorRef.current.updateSmartTagAttrs;
|
|
386
|
+
},
|
|
387
|
+
get blur() {
|
|
388
|
+
return editorRef.current.blur;
|
|
389
|
+
},
|
|
390
|
+
// Forward TextEditorProviderRefHandler methods
|
|
391
|
+
updateColors: colors => providerRef.current?.updateColors?.(colors),
|
|
392
|
+
}), []);
|
|
393
|
+
return (_jsx(TextEditorProvider, { ref: providerRef, colors: colors, onChangeColors: onChangeColors, children: _jsx(TextEditorInternal, { ...editorProps, ref: editorRef }) }));
|
|
394
|
+
});
|
|
395
|
+
TextEditorWithProvider.displayName = 'TextEditorWithProvider';
|
|
396
|
+
export const TextEditor = Object.assign(TextEditorWithProvider, {
|
|
397
|
+
Provider: TextEditorProvider,
|
|
398
|
+
Internal: TextEditorInternal,
|
|
399
|
+
});
|
|
@@ -185,3 +185,12 @@ export declare const DEFAULT_FONT_GROUPING: {
|
|
|
185
185
|
readonly label: "Non-standard";
|
|
186
186
|
};
|
|
187
187
|
};
|
|
188
|
+
/**
|
|
189
|
+
* All available toolbar actions in default order
|
|
190
|
+
*/
|
|
191
|
+
export declare const ALL_TOOLBAR_ACTIONS: readonly ["fontFamily", "fontSize", "bold", "italic", "underline", "link", "strike", "superscript", "subscript", "textTransform", "textColor", "backgroundColor", "emoji", "smartTag", "bulletList", "orderedList", "textAlign", "lineSpacing", "letterSpacing", "indent", "outdent", "history", "clearFormatting"];
|
|
192
|
+
/**
|
|
193
|
+
* Default grouping of toolbar actions into rows
|
|
194
|
+
*/
|
|
195
|
+
export declare const DEFAULT_TOOLBAR_GROUPING: readonly [readonly ["fontFamily", "fontSize", "bold", "italic", "underline", "link", "strike", "superscript", "subscript", "textTransform", "textColor", "backgroundColor", "emoji", "smartTag"], readonly ["bulletList", "orderedList", "textAlign", "lineSpacing", "letterSpacing", "indent", "outdent", "history", "clearFormatting"]];
|
|
196
|
+
export declare const ATTR_WHITESPACE: RegExp;
|
|
@@ -330,3 +330,69 @@ export const DEFAULT_FONT_GROUPING = {
|
|
|
330
330
|
label: 'Non-standard',
|
|
331
331
|
},
|
|
332
332
|
};
|
|
333
|
+
/**
|
|
334
|
+
* All available toolbar actions in default order
|
|
335
|
+
*/
|
|
336
|
+
export const ALL_TOOLBAR_ACTIONS = [
|
|
337
|
+
// Row 1: Text formatting and styling
|
|
338
|
+
'fontFamily',
|
|
339
|
+
'fontSize',
|
|
340
|
+
'bold',
|
|
341
|
+
'italic',
|
|
342
|
+
'underline',
|
|
343
|
+
'link',
|
|
344
|
+
'strike',
|
|
345
|
+
'superscript',
|
|
346
|
+
'subscript',
|
|
347
|
+
'textTransform',
|
|
348
|
+
'textColor',
|
|
349
|
+
'backgroundColor',
|
|
350
|
+
'emoji',
|
|
351
|
+
'smartTag',
|
|
352
|
+
// Row 2: Lists, alignment, and utilities
|
|
353
|
+
'bulletList',
|
|
354
|
+
'orderedList',
|
|
355
|
+
'textAlign',
|
|
356
|
+
'lineSpacing',
|
|
357
|
+
'letterSpacing',
|
|
358
|
+
'indent',
|
|
359
|
+
'outdent',
|
|
360
|
+
'history',
|
|
361
|
+
'clearFormatting',
|
|
362
|
+
];
|
|
363
|
+
/**
|
|
364
|
+
* Default grouping of toolbar actions into rows
|
|
365
|
+
*/
|
|
366
|
+
export const DEFAULT_TOOLBAR_GROUPING = [
|
|
367
|
+
// Row 1
|
|
368
|
+
[
|
|
369
|
+
'fontFamily',
|
|
370
|
+
'fontSize',
|
|
371
|
+
'bold',
|
|
372
|
+
'italic',
|
|
373
|
+
'underline',
|
|
374
|
+
'link',
|
|
375
|
+
'strike',
|
|
376
|
+
'superscript',
|
|
377
|
+
'subscript',
|
|
378
|
+
'textTransform',
|
|
379
|
+
'textColor',
|
|
380
|
+
'backgroundColor',
|
|
381
|
+
'emoji',
|
|
382
|
+
'smartTag',
|
|
383
|
+
],
|
|
384
|
+
// Row 2
|
|
385
|
+
[
|
|
386
|
+
'bulletList',
|
|
387
|
+
'orderedList',
|
|
388
|
+
'textAlign',
|
|
389
|
+
'lineSpacing',
|
|
390
|
+
'letterSpacing',
|
|
391
|
+
'indent',
|
|
392
|
+
'outdent',
|
|
393
|
+
'history',
|
|
394
|
+
'clearFormatting',
|
|
395
|
+
],
|
|
396
|
+
];
|
|
397
|
+
// eslint-disable-next-line no-control-regex
|
|
398
|
+
export const ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
|
|
@@ -1,140 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
1
|
+
import type { EditorState } from '@tiptap/pm/state';
|
|
2
|
+
import { BubbleMenuView as TiptapBubbleMenuView } from '@tiptap/extension-bubble-menu';
|
|
3
|
+
import { Plugin } from '@tiptap/pm/state';
|
|
5
4
|
import type { EditorView } from '@tiptap/pm/view';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* The plugin key.
|
|
9
|
-
* @type {PluginKey | string}
|
|
10
|
-
* @default 'bubbleMenu'
|
|
11
|
-
*/
|
|
12
|
-
pluginKey: PluginKey | string;
|
|
13
|
-
/**
|
|
14
|
-
* The editor instance.
|
|
15
|
-
*/
|
|
16
|
-
editor: Editor;
|
|
17
|
-
/**
|
|
18
|
-
* The DOM element that contains your menu.
|
|
19
|
-
* @type {HTMLElement}
|
|
20
|
-
* @default null
|
|
21
|
-
*/
|
|
22
|
-
element: HTMLElement;
|
|
23
|
-
container?: HTMLElement | (() => HTMLElement) | null;
|
|
24
|
-
/**
|
|
25
|
-
* The delay in milliseconds before the menu should be updated.
|
|
26
|
-
* This can be useful to prevent performance issues.
|
|
27
|
-
* @type {number}
|
|
28
|
-
* @default 250
|
|
29
|
-
*/
|
|
30
|
-
updateDelay?: number;
|
|
31
|
-
/**
|
|
32
|
-
* The delay in milliseconds before the menu position should be updated on window resize.
|
|
33
|
-
* This can be useful to prevent performance issues.
|
|
34
|
-
* @type {number}
|
|
35
|
-
* @default 60
|
|
36
|
-
*/
|
|
37
|
-
resizeDelay?: number;
|
|
38
|
-
/**
|
|
39
|
-
* A function that determines whether the menu should be shown or not.
|
|
40
|
-
* If this function returns `false`, the menu will be hidden, otherwise it will be shown.
|
|
41
|
-
*/
|
|
42
|
-
shouldShow?: ((props: {
|
|
43
|
-
editor: Editor;
|
|
44
|
-
element: HTMLElement;
|
|
45
|
-
view: EditorView;
|
|
46
|
-
state: EditorState;
|
|
47
|
-
oldState?: EditorState;
|
|
48
|
-
from: number;
|
|
49
|
-
to: number;
|
|
50
|
-
}) => boolean) | null;
|
|
51
|
-
/**
|
|
52
|
-
* The options for the bubble menu. Those are passed to Floating UI and include options for the placement, offset, flip, shift, arrow, size, autoPlacement,
|
|
53
|
-
* hide, and inline middlewares.
|
|
54
|
-
* @default {}
|
|
55
|
-
* @see https://floating-ui.com/docs/computePosition#options
|
|
56
|
-
*/
|
|
57
|
-
options?: {
|
|
58
|
-
strategy?: 'absolute' | 'fixed';
|
|
59
|
-
placement?: 'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end';
|
|
60
|
-
offset?: Parameters<typeof offset>[0] | boolean;
|
|
61
|
-
flip?: Parameters<typeof flip>[0] | boolean;
|
|
62
|
-
shift?: Parameters<typeof shift>[0] | boolean;
|
|
63
|
-
arrow?: Parameters<typeof arrow>[0] | false;
|
|
64
|
-
size?: Parameters<typeof size>[0] | boolean;
|
|
65
|
-
autoPlacement?: Parameters<typeof autoPlacement>[0] | boolean;
|
|
66
|
-
hide?: Parameters<typeof hide>[0] | boolean;
|
|
67
|
-
inline?: Parameters<typeof inline>[0] | boolean;
|
|
68
|
-
onShow?: () => void;
|
|
69
|
-
onHide?: () => void;
|
|
70
|
-
onUpdate?: () => void;
|
|
71
|
-
onDestroy?: () => void;
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
export type BubbleMenuViewProps = BubbleMenuPluginProps & {
|
|
75
|
-
view: EditorView;
|
|
76
|
-
};
|
|
77
|
-
export declare class BubbleMenuView implements PluginView {
|
|
78
|
-
editor: Editor;
|
|
79
|
-
element: HTMLElement;
|
|
80
|
-
container?: HTMLElement | (() => HTMLElement) | null;
|
|
81
|
-
view: EditorView;
|
|
82
|
-
preventHide: boolean;
|
|
83
|
-
updateDelay: number;
|
|
84
|
-
resizeDelay: number;
|
|
85
|
-
private updateDebounceTimer;
|
|
86
|
-
private resizeDebounceTimer;
|
|
5
|
+
import type { BubbleMenuPluginProps, BubbleMenuViewProps } from '@tiptap/extension-bubble-menu';
|
|
6
|
+
export declare class BubbleMenuView extends TiptapBubbleMenuView {
|
|
87
7
|
private resizeObserver;
|
|
88
|
-
|
|
89
|
-
private floatingUIOptions;
|
|
90
|
-
shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null>;
|
|
91
|
-
get middlewares(): {
|
|
92
|
-
name: string;
|
|
93
|
-
options?: any;
|
|
94
|
-
fn: (state: {
|
|
95
|
-
x: number;
|
|
96
|
-
y: number;
|
|
97
|
-
platform: import("@floating-ui/core").Platform;
|
|
98
|
-
placement: import("@floating-ui/utils").Placement;
|
|
99
|
-
initialPlacement: import("@floating-ui/utils").Placement;
|
|
100
|
-
strategy: import("@floating-ui/utils").Strategy;
|
|
101
|
-
middlewareData: import("@floating-ui/core").MiddlewareData;
|
|
102
|
-
rects: import("@floating-ui/utils").ElementRects;
|
|
103
|
-
elements: import("@floating-ui/dom").Elements;
|
|
104
|
-
}) => import("@floating-ui/core").MiddlewareReturn | Promise<import("@floating-ui/core").MiddlewareReturn>;
|
|
105
|
-
}[];
|
|
106
|
-
constructor({ editor, element, view, updateDelay, resizeDelay, container, shouldShow, options, }: BubbleMenuViewProps);
|
|
107
|
-
mousedownHandler: () => void;
|
|
108
|
-
dragstartHandler: () => void;
|
|
109
|
-
/**
|
|
110
|
-
* Handles the window resize event and element resize event to update the position of the bubble menu.
|
|
111
|
-
* It uses a debounce mechanism to prevent excessive updates.
|
|
112
|
-
* The delay is defined by the `resizeDelay` property.
|
|
113
|
-
*/
|
|
114
|
-
resizeHandler: (delay?: number) => void;
|
|
115
|
-
/**
|
|
116
|
-
* Window resize handler that uses the default resize delay.
|
|
117
|
-
* This is a separate function to maintain the same reference for addEventListener/removeEventListener.
|
|
118
|
-
*/
|
|
119
|
-
windowResizeHandler: () => void;
|
|
8
|
+
constructor(props: BubbleMenuViewProps);
|
|
120
9
|
/**
|
|
121
10
|
* Sets up ResizeObserver to watch for bubble menu element size changes.
|
|
122
11
|
* This ensures the bubble menu position is updated when the element resizes
|
|
123
12
|
* due to React component rendering different children, not just when the window resizes.
|
|
124
13
|
*/
|
|
125
14
|
setupResizeObserver: () => void;
|
|
126
|
-
focusHandler: () => void;
|
|
127
|
-
blurHandler: ({ event }: {
|
|
128
|
-
event: FocusEvent;
|
|
129
|
-
}) => void;
|
|
130
|
-
updatePosition(): void;
|
|
131
|
-
update(view: EditorView, oldState?: EditorState): void;
|
|
132
|
-
handleDebouncedUpdate: (view: EditorView, oldState?: EditorState) => void;
|
|
133
|
-
getShouldShow(oldState?: EditorState): boolean | undefined;
|
|
134
15
|
updateHandler: (view: EditorView, selectionChanged: boolean, docChanged: boolean, oldState?: EditorState) => void;
|
|
135
|
-
private getContainer;
|
|
136
|
-
show(): void;
|
|
137
|
-
hide(): void;
|
|
138
16
|
destroy(): void;
|
|
139
17
|
}
|
|
140
18
|
export declare const BubbleMenuPlugin: (options: BubbleMenuPluginProps) => Plugin<any>;
|