@antscorp/antsomi-ui 1.3.7-beta.6 → 1.3.7-beta.60
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/icons/LazyIcon/LazyIcon.d.ts +2 -0
- package/es/components/icons/LazyIcon/LazyIcon.js +2 -0
- package/es/components/icons/QRCodeManagementIcon.d.ts +3 -0
- package/es/components/icons/QRCodeManagementIcon.js +7 -0
- package/es/components/icons/QRSetDashboardIcon.d.ts +3 -0
- package/es/components/icons/QRSetDashboardIcon.js +7 -0
- package/es/components/icons/index.d.ts +2 -0
- package/es/components/icons/index.js +2 -0
- 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/ColorPicker/index.d.ts +2 -0
- package/es/components/molecules/ColorPicker/index.js +8 -3
- 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/HeaderV2/HeaderV2.d.ts +1 -1
- package/es/components/molecules/Modal/Modal.js +7 -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/Select/Select.js +1 -1
- package/es/components/molecules/ShareAccess/ShareAccess.d.ts +2 -1
- package/es/components/molecules/ShareAccess/ShareAccess.js +12 -9
- package/es/components/molecules/ShareAccess/components/LayoutContent/LayoutContent.js +5 -5
- package/es/components/molecules/ShareAccess/components/PeopleAccess/PeopleAccess.js +2 -2
- package/es/components/molecules/ShareAccess/hooks/useShareAccess.d.ts +2 -1
- package/es/components/molecules/ShareAccess/index.d.ts +1 -0
- package/es/components/molecules/ShareAccess/reducer.d.ts +1 -1
- package/es/components/molecules/ShareAccess/reducer.js +7 -4
- package/es/components/molecules/ShareAccess/types.d.ts +22 -0
- package/es/components/molecules/ShareAccess/utils.d.ts +3 -1
- package/es/components/molecules/ShareAccess/utils.js +35 -2
- package/es/components/molecules/TagifyInput/TagifyInput.js +48 -27
- package/es/components/molecules/TagifyInput/types.d.ts +14 -8
- 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/molecules/index.d.ts +1 -0
- package/es/components/organism/AccountSharing/AccountSharing.d.ts +1 -0
- package/es/components/organism/AccountSharing/AccountSharing.js +11 -4
- package/es/components/organism/AccountSharing/styled.js +1 -1
- 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 +175 -8
- package/es/components/organism/LeftMenu/LeftMenu.js +3 -3
- package/es/components/organism/LeftMenu/hooks/usePermission.js +1 -1
- package/es/components/organism/LeftMenu/types/index.d.ts +7 -0
- package/es/components/organism/LeftMenu/utils/index.js +1 -1
- package/es/components/organism/Login/Login.js +12 -3
- package/es/components/organism/Login/components/SignIn/SignIn.js +2 -2
- package/es/components/organism/Login/types/index.d.ts +2 -0
- package/es/components/organism/TextEditor/TextEditor.d.ts +9 -2
- package/es/components/organism/TextEditor/TextEditor.js +203 -42
- 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 +33 -14
- 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 +96 -4
- 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 +161 -11
- 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 +90 -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/providers/ConfigProvider/ConfigProvider.d.ts +4 -0
- package/es/providers/ConfigProvider/ConfigProvider.js +2 -3
- package/es/providers/ConfigProvider/GlobalStyle.d.ts +2 -2
- package/es/providers/ConfigProvider/GlobalStyle.js +67 -64
- package/es/services/MediaTemplateDesign/UploadFile/index.js +4 -4
- package/es/utils/common.d.ts +1 -1
- package/es/utils/common.js +3 -3
- package/es/utils/cookie.js +2 -1
- package/package.json +18 -23
- 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,54 @@ 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();
|
|
73
|
+
// console.log(id, { text });
|
|
49
74
|
onUpdate?.({
|
|
50
75
|
html: htmlSerializerForOutput(html),
|
|
51
76
|
text,
|
|
@@ -53,21 +78,40 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
53
78
|
});
|
|
54
79
|
}, onUpdateDebounced);
|
|
55
80
|
const contentRef = useRef(null);
|
|
81
|
+
// Compose linkHandler: merge outerLinkHandler with default handlers
|
|
82
|
+
// Allows partial override - user can provide only setNew or only edit
|
|
83
|
+
const linkHandler = useMemo(() => {
|
|
84
|
+
const defaultSetNew = ({ selectionText }) => {
|
|
85
|
+
showLinkForm('insert', {
|
|
86
|
+
url: '',
|
|
87
|
+
text: selectionText,
|
|
88
|
+
openInNewTab: false,
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
const defaultEdit = ({ attrs, selectionText, }) => {
|
|
92
|
+
showLinkForm('edit', {
|
|
93
|
+
url: attrs.href || '',
|
|
94
|
+
text: selectionText,
|
|
95
|
+
openInNewTab: attrs.target === '_blank',
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
return {
|
|
99
|
+
setNew: outerLinkHandler?.setNew || defaultSetNew,
|
|
100
|
+
edit: outerLinkHandler?.edit || defaultEdit,
|
|
101
|
+
};
|
|
102
|
+
}, [outerLinkHandler, showLinkForm]);
|
|
56
103
|
const editor = useEditor({
|
|
57
104
|
extensions: [
|
|
58
105
|
StarterKit.configure({
|
|
59
106
|
link: false,
|
|
60
107
|
bulletList: false,
|
|
61
108
|
orderedList: false,
|
|
62
|
-
listItem:
|
|
63
|
-
|
|
64
|
-
style: 'line-height:normal;',
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
undoRedo: {
|
|
109
|
+
listItem: false,
|
|
110
|
+
undoRedo: config?.UndoRedo && {
|
|
68
111
|
depth: 100,
|
|
69
112
|
},
|
|
70
113
|
}),
|
|
114
|
+
CustomListItem,
|
|
71
115
|
CustomUnorderedList,
|
|
72
116
|
CustomOrderedList,
|
|
73
117
|
FontWeight.configure({
|
|
@@ -107,7 +151,12 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
107
151
|
Selection.configure({
|
|
108
152
|
className: 'selection',
|
|
109
153
|
}),
|
|
110
|
-
|
|
154
|
+
Focus.configure({
|
|
155
|
+
className: 'has-focused',
|
|
156
|
+
}),
|
|
157
|
+
SmartTag.configure({
|
|
158
|
+
generateSmartTagId: config?.SmartTag?.generateId,
|
|
159
|
+
}),
|
|
111
160
|
TextAlign.configure({
|
|
112
161
|
types: ['heading', 'paragraph'],
|
|
113
162
|
}),
|
|
@@ -121,7 +170,7 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
121
170
|
Indent,
|
|
122
171
|
Emoji.configure({
|
|
123
172
|
suggestion: emojiSuggestion({
|
|
124
|
-
container:
|
|
173
|
+
container: bubbleMenuContainer.current,
|
|
125
174
|
}),
|
|
126
175
|
}),
|
|
127
176
|
ClearFormatting.configure({
|
|
@@ -138,9 +187,22 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
138
187
|
wrapperElement: contentRef.current.parentElement,
|
|
139
188
|
defaultStyle: defaultTextStyle,
|
|
140
189
|
});
|
|
190
|
+
// console.log(
|
|
191
|
+
// '[ONCREATE] safeParseContent !== initialContent:',
|
|
192
|
+
// safeParseContent !== initialContent,
|
|
193
|
+
// );
|
|
141
194
|
if (safeParseContent !== initialContent) {
|
|
195
|
+
// console.log('[ONCREATE] Calling setContent - this RESETS editor content!');
|
|
142
196
|
editor.commands.setContent(safeParseContent);
|
|
143
197
|
}
|
|
198
|
+
const text = editor.getText();
|
|
199
|
+
const json = editor.getJSON();
|
|
200
|
+
const html = editor.getHTML();
|
|
201
|
+
onCreate?.({
|
|
202
|
+
html: htmlSerializerForOutput(html),
|
|
203
|
+
text,
|
|
204
|
+
json,
|
|
205
|
+
});
|
|
144
206
|
},
|
|
145
207
|
onUpdate: ({ editor }) => {
|
|
146
208
|
handleOnUpdateDebounce(editor);
|
|
@@ -154,7 +216,7 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
154
216
|
if (event.ctrlKey && event.key === 'k') {
|
|
155
217
|
// Add this line to prevent browser's default behavior.
|
|
156
218
|
event.preventDefault();
|
|
157
|
-
handleLinkAction(view,
|
|
219
|
+
handleLinkAction(view, linkHandler);
|
|
158
220
|
}
|
|
159
221
|
},
|
|
160
222
|
},
|
|
@@ -183,10 +245,15 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
183
245
|
return updatedAttrs;
|
|
184
246
|
})
|
|
185
247
|
.run(), [editor]);
|
|
186
|
-
const
|
|
248
|
+
const shouldShowLinkPreview = useCallback((params) => {
|
|
249
|
+
const { state } = params;
|
|
250
|
+
return isShowLinkToolbar(state);
|
|
251
|
+
}, []);
|
|
252
|
+
const shouldShowFormattingToolbar = useCallback((params) => {
|
|
187
253
|
const { state, view, element } = params;
|
|
254
|
+
// Don't show if link preview is visible
|
|
188
255
|
if (isShowLinkToolbar(state)) {
|
|
189
|
-
return
|
|
256
|
+
return false;
|
|
190
257
|
}
|
|
191
258
|
return defaultShouldShowBubbleMenu({
|
|
192
259
|
state,
|
|
@@ -203,10 +270,25 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
203
270
|
editor?.chain().blur().setTextSelection({ from: 0, to: 0 }).run();
|
|
204
271
|
}
|
|
205
272
|
}, [editor]);
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
273
|
+
const handleEachLinkGroup = useCallback(callback => {
|
|
274
|
+
if (!editor)
|
|
275
|
+
return;
|
|
276
|
+
const linkGroups = getAllFullLinkGroups(editor.state);
|
|
277
|
+
linkGroups.forEach(callback);
|
|
278
|
+
}, [editor]);
|
|
279
|
+
const handleEachSmartag = useCallback(callback => {
|
|
280
|
+
if (!editor)
|
|
281
|
+
return;
|
|
282
|
+
const { state } = editor;
|
|
283
|
+
const { doc } = state;
|
|
284
|
+
doc.descendants(node => {
|
|
285
|
+
if (isSmartTagNode(node)) {
|
|
286
|
+
callback(node.attrs);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}, [editor]);
|
|
209
290
|
useImperativeHandle(ref, () => ({
|
|
291
|
+
editor,
|
|
210
292
|
setLink: params => {
|
|
211
293
|
editor?.chain().setCustomLink(params).run();
|
|
212
294
|
},
|
|
@@ -226,33 +308,112 @@ export const TextEditor = memo(forwardRef((props, ref) => {
|
|
|
226
308
|
})
|
|
227
309
|
.run();
|
|
228
310
|
},
|
|
311
|
+
getHTML: () => htmlSerializerForOutput(editor.getHTML()),
|
|
312
|
+
eachLinkGroup: handleEachLinkGroup,
|
|
313
|
+
eachSmartag: handleEachSmartag,
|
|
229
314
|
setSmartTag: handleSetSmartTag,
|
|
230
315
|
deleteSmartTag: handleDeleteSmartTag,
|
|
231
316
|
updateSmartTagAttrs: handleUpdateSmartTagAttrs,
|
|
232
317
|
blur: handleBlur,
|
|
318
|
+
focus() {
|
|
319
|
+
editor.chain().focus().run();
|
|
320
|
+
},
|
|
321
|
+
setContent: editor.commands.setContent,
|
|
233
322
|
style: contentRef.current?.style,
|
|
234
|
-
editor,
|
|
235
323
|
}));
|
|
236
324
|
if (!editor) {
|
|
237
325
|
return null;
|
|
238
326
|
}
|
|
327
|
+
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: {
|
|
328
|
+
onUpsert: () => {
|
|
329
|
+
handleLinkAction(editor.view, linkHandler);
|
|
330
|
+
},
|
|
331
|
+
}, render: render }) }), _jsx(BubbleMenu, { pluginKey: "formattingBubbleMenu", ...bubbleMenuProps, appendTo: bubbleMenuContainer.current, editor: editor, shouldShow: shouldShowFormattingToolbar, children: _jsx(FormattingToolbar, { config: config, editor: editor, defaultTextStyle: defaultTextStyle, linkHanlder: {
|
|
332
|
+
onUpsert: () => {
|
|
333
|
+
handleLinkAction(editor.view, linkHandler);
|
|
334
|
+
},
|
|
335
|
+
}, smartTagHandler: {
|
|
336
|
+
onUpsert: (event) => {
|
|
337
|
+
handleSmartTagAction(event, editor.view, outerSmartTagHandler);
|
|
338
|
+
},
|
|
339
|
+
}, onChangeFont: ({ font, weight }) => {
|
|
340
|
+
onChangeFont?.({
|
|
341
|
+
font,
|
|
342
|
+
weight,
|
|
343
|
+
analysis: analyzeFont(font),
|
|
344
|
+
});
|
|
345
|
+
} }) })] }))] })) : null;
|
|
239
346
|
return (_jsxs(_Fragment, { children: [_jsx(StyledEditorContent, { className: clsx(`${ANTSOMI_COMPONENT_PREFIX_CLS}-text-editor`, className), "$textStyle": defaultTextStyle, style: {
|
|
240
347
|
// Inline styles apply to inner html elements (support email client)
|
|
241
|
-
...
|
|
348
|
+
...defaultTextStyle,
|
|
242
349
|
...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
|
-
} })) })] }));
|
|
350
|
+
}, id: id, ref: contentRef, editor: editor, ...dataAttributes }), bubbleMenus] }));
|
|
258
351
|
}));
|
|
352
|
+
TextEditorInternal.displayName = 'TextEditorInternal';
|
|
353
|
+
const TextEditorWithProvider = forwardRef((props, ref) => {
|
|
354
|
+
const { colors, onChangeColors, ...editorProps } = props;
|
|
355
|
+
const providerRef = useRef(null);
|
|
356
|
+
const editorRef = useRef(null);
|
|
357
|
+
// Sync external colors to internal store
|
|
358
|
+
useDeepCompareEffect(() => {
|
|
359
|
+
if (colors !== undefined) {
|
|
360
|
+
providerRef.current?.updateColors?.(colors);
|
|
361
|
+
}
|
|
362
|
+
}, [colors]);
|
|
363
|
+
useImperativeHandle(ref, () => ({
|
|
364
|
+
// Forward TextEditorRef methods - accessed at call time
|
|
365
|
+
get editor() {
|
|
366
|
+
return editorRef.current?.editor;
|
|
367
|
+
},
|
|
368
|
+
get style() {
|
|
369
|
+
return editorRef.current?.style;
|
|
370
|
+
},
|
|
371
|
+
get getHTML() {
|
|
372
|
+
return editorRef.current.getHTML;
|
|
373
|
+
},
|
|
374
|
+
get setLink() {
|
|
375
|
+
return editorRef.current.setLink;
|
|
376
|
+
},
|
|
377
|
+
get deleteLink() {
|
|
378
|
+
return editorRef.current.deleteLink;
|
|
379
|
+
},
|
|
380
|
+
get updateLinkAttrs() {
|
|
381
|
+
return editorRef.current.updateLinkAttrs;
|
|
382
|
+
},
|
|
383
|
+
get updateLinkText() {
|
|
384
|
+
return editorRef.current.updateLinkText;
|
|
385
|
+
},
|
|
386
|
+
get eachLinkGroup() {
|
|
387
|
+
return editorRef.current.eachLinkGroup;
|
|
388
|
+
},
|
|
389
|
+
get eachSmartag() {
|
|
390
|
+
return editorRef.current.eachSmartag;
|
|
391
|
+
},
|
|
392
|
+
get setSmartTag() {
|
|
393
|
+
return editorRef.current.setSmartTag;
|
|
394
|
+
},
|
|
395
|
+
get deleteSmartTag() {
|
|
396
|
+
return editorRef.current.deleteSmartTag;
|
|
397
|
+
},
|
|
398
|
+
get updateSmartTagAttrs() {
|
|
399
|
+
return editorRef.current.updateSmartTagAttrs;
|
|
400
|
+
},
|
|
401
|
+
get blur() {
|
|
402
|
+
return editorRef.current.blur;
|
|
403
|
+
},
|
|
404
|
+
get focus() {
|
|
405
|
+
return editorRef.current.focus;
|
|
406
|
+
},
|
|
407
|
+
get setContent() {
|
|
408
|
+
return editorRef.current.setContent;
|
|
409
|
+
},
|
|
410
|
+
// Forward TextEditorProviderRefHandler methods
|
|
411
|
+
updateColors: colors => providerRef.current?.updateColors?.(colors),
|
|
412
|
+
}), []);
|
|
413
|
+
return (_jsx(TextEditorProvider, { ref: providerRef, colors: colors, onChangeColors: onChangeColors, children: _jsx(TextEditorInternal, { ...editorProps, ref: editorRef }) }));
|
|
414
|
+
});
|
|
415
|
+
TextEditorWithProvider.displayName = 'TextEditorWithProvider';
|
|
416
|
+
export const TextEditor = Object.assign(TextEditorWithProvider, {
|
|
417
|
+
Provider: TextEditorProvider,
|
|
418
|
+
Internal: TextEditorInternal,
|
|
419
|
+
});
|
|
@@ -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>;
|