@antscorp/antsomi-ui 2.0.82 → 2.0.83-text-editor-beta.1
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/assets/css/main.scss +4 -2
- package/es/components/index.scss +1 -0
- package/es/components/molecules/AccountSelection/AccountListing.js +14 -3
- package/es/components/molecules/EmojiPopover/EmojiPopover.js +5 -1
- package/es/components/molecules/FontSizeInput/FontSizeInput.d.ts +3 -0
- package/es/components/molecules/FontSizeInput/FontSizeInput.js +77 -0
- package/es/components/molecules/FontSizeInput/constants.d.ts +2 -0
- package/es/components/molecules/FontSizeInput/constants.js +5 -0
- package/es/components/molecules/FontSizeInput/index.d.ts +2 -0
- package/es/components/molecules/FontSizeInput/index.js +1 -0
- package/es/components/molecules/FontSizeInput/types.d.ts +21 -0
- package/es/components/molecules/FontSizeInput/types.js +1 -0
- package/es/components/molecules/VirtualizedMenu/VirtualizedMenu.d.ts +1 -2
- package/es/components/molecules/VirtualizedMenu/__mocks__/index.js +2550 -938
- package/es/components/molecules/VirtualizedMenu/components/Item/Item.d.ts +4 -3
- package/es/components/molecules/VirtualizedMenu/components/Item/Item.js +24 -22
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.d.ts +1 -2
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.js +59 -31
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.optimized.d.ts +19 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.optimized.js +233 -0
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/index.d.ts +1 -1
- package/es/components/molecules/VirtualizedMenu/components/MenuInline/index.js +2 -1
- package/es/components/molecules/VirtualizedMenu/styled.d.ts +1 -1
- package/es/components/molecules/VirtualizedMenu/styled.js +11 -3
- package/es/components/molecules/VirtualizedMenu/types.d.ts +1 -8
- package/es/components/molecules/VirtualizedMenu/utils.d.ts +7 -5
- package/es/components/molecules/VirtualizedMenu/utils.js +12 -18
- package/es/components/molecules/index.d.ts +1 -0
- package/es/components/molecules/index.js +1 -0
- package/es/components/organism/ActivityTimeline/__mocks__/event_tracking.json +1290 -0
- package/es/components/organism/ActivityTimeline/__mocks__/timeline.json +3059 -0
- package/es/components/organism/TextEditor/TextEditor.d.ts +3 -0
- package/es/components/organism/TextEditor/TextEditor.js +239 -0
- package/es/components/organism/TextEditor/__mocks__/text-block.settings.json +320 -0
- package/es/components/organism/TextEditor/__mocks__/text-contennt.d.ts +1 -0
- package/es/components/organism/TextEditor/__mocks__/text-contennt.js +38 -0
- package/es/components/organism/TextEditor/constants.d.ts +135 -0
- package/es/components/organism/TextEditor/constants.js +280 -0
- package/es/components/organism/TextEditor/extensions/BackgroundColor.d.ts +25 -0
- package/es/components/organism/TextEditor/extensions/BackgroundColor.js +41 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.d.ts +130 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.js +247 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu.d.ts +15 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu.js +31 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/index.d.ts +2 -0
- package/es/components/organism/TextEditor/extensions/BubbleMenu/index.js +2 -0
- package/es/components/organism/TextEditor/extensions/Color.d.ts +6 -0
- package/es/components/organism/TextEditor/extensions/Color.js +19 -0
- package/es/components/organism/TextEditor/extensions/Emoji.d.ts +57 -0
- package/es/components/organism/TextEditor/extensions/Emoji.js +184 -0
- package/es/components/organism/TextEditor/extensions/FontFamily.d.ts +6 -0
- package/es/components/organism/TextEditor/extensions/FontFamily.js +43 -0
- package/es/components/organism/TextEditor/extensions/FontSize.d.ts +32 -0
- package/es/components/organism/TextEditor/extensions/FontSize.js +47 -0
- package/es/components/organism/TextEditor/extensions/FontWeight.d.ts +23 -0
- package/es/components/organism/TextEditor/extensions/FontWeight.js +41 -0
- package/es/components/organism/TextEditor/extensions/Highlight.d.ts +1 -0
- package/es/components/organism/TextEditor/extensions/Highlight.js +14 -0
- package/es/components/organism/TextEditor/extensions/Indent.d.ts +28 -0
- package/es/components/organism/TextEditor/extensions/Indent.js +66 -0
- package/es/components/organism/TextEditor/extensions/LineHeight.d.ts +20 -0
- package/es/components/organism/TextEditor/extensions/LineHeight.js +36 -0
- package/es/components/organism/TextEditor/extensions/Link.d.ts +3 -0
- package/es/components/organism/TextEditor/extensions/Link.js +47 -0
- package/es/components/organism/TextEditor/extensions/ListItemMarker.d.ts +13 -0
- package/es/components/organism/TextEditor/extensions/ListItemMarker.js +174 -0
- package/es/components/organism/TextEditor/extensions/Selection.d.ts +6 -0
- package/es/components/organism/TextEditor/extensions/Selection.js +40 -0
- package/es/components/organism/TextEditor/extensions/SmartTag.d.ts +33 -0
- package/es/components/organism/TextEditor/extensions/SmartTag.js +162 -0
- package/es/components/organism/TextEditor/extensions/StyleMemory.d.ts +36 -0
- package/es/components/organism/TextEditor/extensions/StyleMemory.js +163 -0
- package/es/components/organism/TextEditor/extensions/TextTransform.d.ts +31 -0
- package/es/components/organism/TextEditor/extensions/TextTransform.js +35 -0
- package/es/components/organism/TextEditor/hooks/index.d.ts +6 -0
- package/es/components/organism/TextEditor/hooks/index.js +6 -0
- package/es/components/organism/TextEditor/hooks/useDocumentState.d.ts +18 -0
- package/es/components/organism/TextEditor/hooks/useDocumentState.js +42 -0
- package/es/components/organism/TextEditor/hooks/useLinkHandler.d.ts +27 -0
- package/es/components/organism/TextEditor/hooks/useLinkHandler.js +279 -0
- package/es/components/organism/TextEditor/hooks/useMarkTracking.d.ts +26 -0
- package/es/components/organism/TextEditor/hooks/useMarkTracking.js +68 -0
- package/es/components/organism/TextEditor/hooks/usePersistence.d.ts +31 -0
- package/es/components/organism/TextEditor/hooks/usePersistence.js +169 -0
- package/es/components/organism/TextEditor/hooks/useStyleMemory.d.ts +6 -0
- package/es/components/organism/TextEditor/hooks/useStyleMemory.js +42 -0
- package/es/components/organism/TextEditor/hooks/useStylePresets.d.ts +34 -0
- package/es/components/organism/TextEditor/hooks/useStylePresets.js +83 -0
- package/es/components/organism/TextEditor/index.d.ts +5 -0
- package/es/components/organism/TextEditor/index.js +2 -0
- package/es/components/organism/TextEditor/index.scss +26 -0
- package/es/components/organism/TextEditor/provider.d.ts +10 -0
- package/es/components/organism/TextEditor/provider.js +20 -0
- package/es/components/organism/TextEditor/store.d.ts +11 -0
- package/es/components/organism/TextEditor/store.js +12 -0
- package/es/components/organism/TextEditor/styled.d.ts +5 -0
- package/es/components/organism/TextEditor/styled.js +69 -0
- package/es/components/organism/TextEditor/types.d.ts +95 -0
- package/es/components/organism/TextEditor/types.js +1 -0
- package/es/components/organism/TextEditor/ui/BubbleMenu/BubbleMenu.d.ts +6 -0
- package/es/components/organism/TextEditor/ui/BubbleMenu/BubbleMenu.js +78 -0
- package/es/components/organism/TextEditor/ui/BubbleMenu/index.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/BubbleMenu/index.js +1 -0
- package/es/components/organism/TextEditor/ui/ColorPicker/ColorPicker.d.ts +43 -0
- package/es/components/organism/TextEditor/ui/ColorPicker/ColorPicker.js +120 -0
- package/es/components/organism/TextEditor/ui/ColorPicker/index.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/ColorPicker/index.js +1 -0
- package/es/components/organism/TextEditor/ui/Emoji/EmojiList.d.ts +11 -0
- package/es/components/organism/TextEditor/ui/Emoji/EmojiList.js +66 -0
- package/es/components/organism/TextEditor/ui/Emoji/index.d.ts +2 -0
- package/es/components/organism/TextEditor/ui/Emoji/index.js +2 -0
- package/es/components/organism/TextEditor/ui/Emoji/suggestion.d.ts +4 -0
- package/es/components/organism/TextEditor/ui/Emoji/suggestion.js +71 -0
- package/es/components/organism/TextEditor/ui/FontPopover/FontPopover.d.ts +11 -0
- package/es/components/organism/TextEditor/ui/FontPopover/FontPopover.js +72 -0
- package/es/components/organism/TextEditor/ui/FontPopover/styled.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/FontPopover/styled.js +51 -0
- package/es/components/organism/TextEditor/ui/Popover/Popover.d.ts +6 -0
- package/es/components/organism/TextEditor/ui/Popover/Popover.js +7 -0
- package/es/components/organism/TextEditor/ui/Popover/index.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/Popover/index.js +1 -0
- package/es/components/organism/TextEditor/ui/Select/Select.d.ts +4 -0
- package/es/components/organism/TextEditor/ui/Select/Select.js +7 -0
- package/es/components/organism/TextEditor/ui/Select/index.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/Select/index.js +1 -0
- package/es/components/organism/TextEditor/ui/TextAlignSelect/TextAlignSelect.d.ts +30 -0
- package/es/components/organism/TextEditor/ui/TextAlignSelect/TextAlignSelect.js +49 -0
- package/es/components/organism/TextEditor/ui/TextAlignSelect/index.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/TextAlignSelect/index.js +1 -0
- package/es/components/organism/TextEditor/ui/Toolbar/Toolbar.d.ts +14 -0
- package/es/components/organism/TextEditor/ui/Toolbar/Toolbar.js +42 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/BoldAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/BoldAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/BulletListAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/BulletListAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/ClearFormattingAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/ClearFormattingAction.js +18 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/EmojiAction.d.ts +4 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/EmojiAction.js +13 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontFamilyAction.d.ts +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontFamilyAction.js +18 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontSizeAction.d.ts +6 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/FontSizeAction.js +42 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/HighlightAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/HighlightAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/IndentAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/IndentAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/ItalicAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/ItalicAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/LinkAction.d.ts +6 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/LinkAction.js +4 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/OrderedListAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/OrderedListAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/OutdentAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/OutdentAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SmartTagAction.d.ts +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SmartTagAction.js +9 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SpacingAction.d.ts +9 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SpacingAction.js +22 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/StrikeAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/StrikeAction.js +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SubscriptAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SubscriptAction.js +13 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SuperscriptAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/SuperscriptAction.js +13 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextAlignAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextAlignAction.js +3 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextBackgroundColorAction.d.ts +7 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextBackgroundColorAction.js +19 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextColorAction.d.ts +15 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextColorAction.js +14 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextTransformAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/TextTransformAction.js +28 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/UnderlineAction.d.ts +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/UnderlineAction.js +5 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/UnsetLink.d.ts +6 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/UnsetLink.js +10 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/index.d.ts +20 -0
- package/es/components/organism/TextEditor/ui/Toolbar/actions/index.js +20 -0
- package/es/components/organism/TextEditor/ui/Toolbar/index.d.ts +1 -0
- package/es/components/organism/TextEditor/ui/Toolbar/index.js +1 -0
- package/es/components/organism/TextEditor/utils/documentState.d.ts +57 -0
- package/es/components/organism/TextEditor/utils/documentState.js +100 -0
- package/es/components/organism/TextEditor/utils/font.d.ts +84 -0
- package/es/components/organism/TextEditor/utils/font.js +175 -0
- package/es/components/organism/TextEditor/utils/htmlProcessing.d.ts +62 -0
- package/es/components/organism/TextEditor/utils/htmlProcessing.js +304 -0
- package/es/components/organism/TextEditor/utils/index.d.ts +8 -0
- package/es/components/organism/TextEditor/utils/index.js +16 -0
- package/es/components/organism/TextEditor/utils/link.d.ts +100 -0
- package/es/components/organism/TextEditor/utils/link.js +149 -0
- package/es/components/organism/TextEditor/utils/menu.d.ts +134 -0
- package/es/components/organism/TextEditor/utils/menu.js +317 -0
- package/es/components/organism/TextEditor/utils/selection.d.ts +25 -0
- package/es/components/organism/TextEditor/utils/selection.js +57 -0
- package/es/components/organism/TextEditor/utils/smartTag.d.ts +49 -0
- package/es/components/organism/TextEditor/utils/smartTag.js +89 -0
- package/es/components/organism/TextEditor/utils/style.d.ts +78 -0
- package/es/components/organism/TextEditor/utils/style.js +193 -0
- package/es/components/organism/index.d.ts +1 -0
- package/es/components/organism/index.js +1 -0
- package/es/components/organism/index.scss +1 -0
- package/es/hooks/useBroadcastedLocalStorage.d.ts +5 -0
- package/es/hooks/useBroadcastedLocalStorage.js +71 -0
- package/es/utils/common.d.ts +6 -9
- package/es/utils/common.js +44 -23
- package/es/utils/index.d.ts +1 -0
- package/es/utils/index.js +1 -0
- package/es/utils/tree.d.ts +225 -0
- package/es/utils/tree.js +469 -0
- package/es/utils/web.d.ts +4 -0
- package/es/utils/web.js +25 -0
- package/package.json +29 -3
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EditorState } from '@tiptap/pm/state';
|
|
2
|
+
/**
|
|
3
|
+
* Kiểm tra xem có selection nào trong tài liệu hay không
|
|
4
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
5
|
+
* @returns true nếu không có selection, false nếu có selection
|
|
6
|
+
*/
|
|
7
|
+
export declare const isNoSelection: (state: EditorState) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Gets the text content of the current selection
|
|
10
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
11
|
+
* @returns Selected text content
|
|
12
|
+
*/
|
|
13
|
+
export declare const getSelectionText: (state: EditorState) => string;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if selection spans multiple nodes
|
|
16
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
17
|
+
* @returns true if selection spans multiple nodes
|
|
18
|
+
*/
|
|
19
|
+
export declare const isMultiNodeSelection: (state: EditorState) => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Gets the depth of the current selection
|
|
22
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
23
|
+
* @returns Selection depth
|
|
24
|
+
*/
|
|
25
|
+
export declare const getSelectionDepth: (state: EditorState) => number;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isNodeSelection, isTextSelection } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* Kiểm tra xem có selection nào trong tài liệu hay không
|
|
4
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
5
|
+
* @returns true nếu không có selection, false nếu có selection
|
|
6
|
+
*/
|
|
7
|
+
export const isNoSelection = (state) => {
|
|
8
|
+
const { selection } = state;
|
|
9
|
+
if (selection.empty)
|
|
10
|
+
return true;
|
|
11
|
+
// Kiểm tra trường hợp text selection không có nội dung
|
|
12
|
+
if (isTextSelection(selection)) {
|
|
13
|
+
const { from, to } = selection;
|
|
14
|
+
if (from === to)
|
|
15
|
+
return true;
|
|
16
|
+
const selectedText = state.doc.textBetween(from, to);
|
|
17
|
+
return selectedText.length === 0;
|
|
18
|
+
}
|
|
19
|
+
// Nếu là node selection, thì có selection
|
|
20
|
+
if (isNodeSelection(selection))
|
|
21
|
+
return false;
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Gets the text content of the current selection
|
|
26
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
27
|
+
* @returns Selected text content
|
|
28
|
+
*/
|
|
29
|
+
export const getSelectionText = (state) => {
|
|
30
|
+
const { selection } = state;
|
|
31
|
+
const { from, to } = selection;
|
|
32
|
+
return state.doc.textBetween(from, to);
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Checks if selection spans multiple nodes
|
|
36
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
37
|
+
* @returns true if selection spans multiple nodes
|
|
38
|
+
*/
|
|
39
|
+
export const isMultiNodeSelection = (state) => {
|
|
40
|
+
const { selection } = state;
|
|
41
|
+
if (selection.empty)
|
|
42
|
+
return false;
|
|
43
|
+
const { from, to } = selection;
|
|
44
|
+
const $from = state.doc.resolve(from);
|
|
45
|
+
const $to = state.doc.resolve(to);
|
|
46
|
+
return $from.parent !== $to.parent;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Gets the depth of the current selection
|
|
50
|
+
* @param state EditorState của Tiptap/ProseMirror
|
|
51
|
+
* @returns Selection depth
|
|
52
|
+
*/
|
|
53
|
+
export const getSelectionDepth = (state) => {
|
|
54
|
+
const { selection } = state;
|
|
55
|
+
const { $from } = selection;
|
|
56
|
+
return $from.depth;
|
|
57
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EditorView } from '@tiptap/pm/view';
|
|
2
|
+
import { SmartTagHandler } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Handles smart tag actions (create or edit)
|
|
5
|
+
* @param event Mouse event from the action
|
|
6
|
+
* @param view EditorView instance
|
|
7
|
+
* @param smartTagHandler Smart tag handler callbacks
|
|
8
|
+
*/
|
|
9
|
+
export declare const handleSmartTagAction: (event: React.MouseEvent, view: EditorView, smartTagHandler?: SmartTagHandler) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Gets smart tag node at a specific position
|
|
12
|
+
* @param view EditorView instance
|
|
13
|
+
* @param pos Position to check
|
|
14
|
+
* @returns Smart tag node or null
|
|
15
|
+
*/
|
|
16
|
+
export declare const getSmartTagAtPosition: (view: EditorView, pos: number) => import("prosemirror-model").Node | null;
|
|
17
|
+
/**
|
|
18
|
+
* Gets all smart tags in the document
|
|
19
|
+
* @param view EditorView instance
|
|
20
|
+
* @returns Array of smart tag nodes with their positions
|
|
21
|
+
*/
|
|
22
|
+
export declare const getAllSmartTags: (view: EditorView) => {
|
|
23
|
+
node: any;
|
|
24
|
+
pos: number;
|
|
25
|
+
}[];
|
|
26
|
+
/**
|
|
27
|
+
* Finds smart tag by ID
|
|
28
|
+
* @param view EditorView instance
|
|
29
|
+
* @param id Smart tag ID to find
|
|
30
|
+
* @returns Smart tag node and position or null
|
|
31
|
+
*/
|
|
32
|
+
export declare const findSmartTagById: (view: EditorView, id: string) => null;
|
|
33
|
+
/**
|
|
34
|
+
* Checks if position is inside a smart tag
|
|
35
|
+
* @param view EditorView instance
|
|
36
|
+
* @param pos Position to check
|
|
37
|
+
* @returns true if position is inside a smart tag
|
|
38
|
+
*/
|
|
39
|
+
export declare const isPositionInSmartTag: (view: EditorView, pos: number) => boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Gets smart tag content at cursor position
|
|
42
|
+
* @param view EditorView instance
|
|
43
|
+
* @returns Smart tag content or null
|
|
44
|
+
*/
|
|
45
|
+
export declare const getSmartTagAtCursor: (view: EditorView) => {
|
|
46
|
+
id: any;
|
|
47
|
+
content: any;
|
|
48
|
+
node: import("prosemirror-model").Node;
|
|
49
|
+
} | null;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles smart tag actions (create or edit)
|
|
3
|
+
* @param event Mouse event from the action
|
|
4
|
+
* @param view EditorView instance
|
|
5
|
+
* @param smartTagHandler Smart tag handler callbacks
|
|
6
|
+
*/
|
|
7
|
+
export const handleSmartTagAction = (event, view, smartTagHandler) => {
|
|
8
|
+
const { state } = view;
|
|
9
|
+
const { from, to } = state.selection;
|
|
10
|
+
const smartTagNode = state.doc.nodeAt(from);
|
|
11
|
+
const smartTagId = smartTagNode?.attrs.id;
|
|
12
|
+
if (smartTagId) {
|
|
13
|
+
smartTagHandler?.edit?.(smartTagId, event);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const selectedText = state.doc.textBetween(from, to);
|
|
17
|
+
if (selectedText) {
|
|
18
|
+
smartTagHandler?.setNew?.({
|
|
19
|
+
selectionText: selectedText,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Gets smart tag node at a specific position
|
|
26
|
+
* @param view EditorView instance
|
|
27
|
+
* @param pos Position to check
|
|
28
|
+
* @returns Smart tag node or null
|
|
29
|
+
*/
|
|
30
|
+
export const getSmartTagAtPosition = (view, pos) => {
|
|
31
|
+
const node = view.state.doc.nodeAt(pos);
|
|
32
|
+
if (node && node.type.name === 'smartTag') {
|
|
33
|
+
return node;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Gets all smart tags in the document
|
|
39
|
+
* @param view EditorView instance
|
|
40
|
+
* @returns Array of smart tag nodes with their positions
|
|
41
|
+
*/
|
|
42
|
+
export const getAllSmartTags = (view) => {
|
|
43
|
+
const smartTags = [];
|
|
44
|
+
view.state.doc.descendants((node, pos) => {
|
|
45
|
+
if (node.type.name === 'smartTag') {
|
|
46
|
+
smartTags.push({ node, pos });
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return smartTags;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Finds smart tag by ID
|
|
53
|
+
* @param view EditorView instance
|
|
54
|
+
* @param id Smart tag ID to find
|
|
55
|
+
* @returns Smart tag node and position or null
|
|
56
|
+
*/
|
|
57
|
+
export const findSmartTagById = (view, id) => {
|
|
58
|
+
let result = null;
|
|
59
|
+
view.state.doc.descendants((node, pos) => {
|
|
60
|
+
if (node.type.name === 'smartTag' && node.attrs.id === id) {
|
|
61
|
+
result = { node, pos };
|
|
62
|
+
return false; // Stop traversal
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Checks if position is inside a smart tag
|
|
69
|
+
* @param view EditorView instance
|
|
70
|
+
* @param pos Position to check
|
|
71
|
+
* @returns true if position is inside a smart tag
|
|
72
|
+
*/
|
|
73
|
+
export const isPositionInSmartTag = (view, pos) => getSmartTagAtPosition(view, pos) !== null;
|
|
74
|
+
/**
|
|
75
|
+
* Gets smart tag content at cursor position
|
|
76
|
+
* @param view EditorView instance
|
|
77
|
+
* @returns Smart tag content or null
|
|
78
|
+
*/
|
|
79
|
+
export const getSmartTagAtCursor = (view) => {
|
|
80
|
+
const { selection } = view.state;
|
|
81
|
+
const node = getSmartTagAtPosition(view, selection.from);
|
|
82
|
+
return node
|
|
83
|
+
? {
|
|
84
|
+
id: node.attrs.id,
|
|
85
|
+
content: node.attrs.content,
|
|
86
|
+
node,
|
|
87
|
+
}
|
|
88
|
+
: null;
|
|
89
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { TextStyle } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts text style from element's computed style
|
|
4
|
+
* @param style CSSStyleDeclaration from element
|
|
5
|
+
* @returns Partial TextStyle object
|
|
6
|
+
*/
|
|
7
|
+
export declare const textStyleFromElStyle: <T extends CSSStyleDeclaration>(style: T) => Partial<TextStyle>;
|
|
8
|
+
/**
|
|
9
|
+
* Applies text style to HTML element
|
|
10
|
+
* @param el HTML element to apply styles to
|
|
11
|
+
* @param style TextStyle object
|
|
12
|
+
*/
|
|
13
|
+
export declare const appendTextStyleToEl: (el: HTMLElement, style: Partial<TextStyle>) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Converts a style object to a CSS string representation
|
|
16
|
+
* @param styleObj The style object to convert
|
|
17
|
+
* @returns The CSS string representation
|
|
18
|
+
* @example
|
|
19
|
+
* styleObjectToString({ color: 'red', fontSize: '16px' })
|
|
20
|
+
* // returns "color: red; font-size: 16px"
|
|
21
|
+
*/
|
|
22
|
+
export declare function styleObjectToString(styleObj: Record<string, unknown>): string;
|
|
23
|
+
/**
|
|
24
|
+
* Normalizes a font-family string by adding quotes when needed
|
|
25
|
+
* @param fontFamily The font-family string to normalize
|
|
26
|
+
* @returns The normalized font-family string
|
|
27
|
+
* @description
|
|
28
|
+
* - Preserves existing quoted names
|
|
29
|
+
* - Doesn't quote generic families (e.g. sans-serif)
|
|
30
|
+
* - Quotes names containing spaces or special characters
|
|
31
|
+
* @example
|
|
32
|
+
* normalizeFontFamily('Arial, Helvetica, sans-serif')
|
|
33
|
+
* // returns 'Arial, Helvetica, sans-serif'
|
|
34
|
+
*
|
|
35
|
+
* normalizeFontFamily('Times New Roman, serif')
|
|
36
|
+
* // returns '"Times New Roman", serif'
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeFontFamily(fontFamily: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Creates font-family string with fallback
|
|
41
|
+
* @param fontFamily Primary font family
|
|
42
|
+
* @param defaultFont Default fallback font
|
|
43
|
+
* @returns Normalized font-family string with fallback
|
|
44
|
+
*/
|
|
45
|
+
export declare const fontWithFallback: (fontFamily: string, defaultFont?: string) => string;
|
|
46
|
+
/**
|
|
47
|
+
* Checks if a color matches the link color
|
|
48
|
+
* @param color Color to check
|
|
49
|
+
* @returns true if color matches link color
|
|
50
|
+
*/
|
|
51
|
+
export declare const isLinkColor: (color: string) => boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Extracts CSS variables from a style object
|
|
54
|
+
* @param styleObj Style object that may contain CSS variables
|
|
55
|
+
* @returns Object with CSS variables and regular styles separated
|
|
56
|
+
*/
|
|
57
|
+
export declare function extractCSSVariables(styleObj: Record<string, unknown>): {
|
|
58
|
+
cssVariables: Record<string, unknown>;
|
|
59
|
+
regularStyles: Record<string, unknown>;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Merges multiple text styles with priority
|
|
63
|
+
* @param styles Array of text styles to merge
|
|
64
|
+
* @returns Merged text style
|
|
65
|
+
*/
|
|
66
|
+
export declare function mergeTextStyles(...styles: Partial<TextStyle>[]): Partial<TextStyle>;
|
|
67
|
+
/**
|
|
68
|
+
* Validates if a text style is complete
|
|
69
|
+
* @param style Text style to validate
|
|
70
|
+
* @returns true if all required properties are present
|
|
71
|
+
*/
|
|
72
|
+
export declare function isCompleteTextStyle(style: Partial<TextStyle>): style is TextStyle;
|
|
73
|
+
/**
|
|
74
|
+
* Converts text style to CSS style object
|
|
75
|
+
* @param textStyle Text style object
|
|
76
|
+
* @returns CSS style object
|
|
77
|
+
*/
|
|
78
|
+
export declare function textStyleToCSSStyle(textStyle: Partial<TextStyle>): React.CSSProperties;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { DEFAULT_TEXT_STYLE, LINK_TEXT_COLOR } from '../constants';
|
|
2
|
+
import { uniqBy } from 'lodash';
|
|
3
|
+
import tinycolor from 'tinycolor2';
|
|
4
|
+
/**
|
|
5
|
+
* Extracts text style from element's computed style
|
|
6
|
+
* @param style CSSStyleDeclaration from element
|
|
7
|
+
* @returns Partial TextStyle object
|
|
8
|
+
*/
|
|
9
|
+
export const textStyleFromElStyle = (style) => ({
|
|
10
|
+
color: style.color || DEFAULT_TEXT_STYLE.color,
|
|
11
|
+
fontFamily: style.fontFamily || DEFAULT_TEXT_STYLE.fontFamily,
|
|
12
|
+
fontSize: style.fontSize || DEFAULT_TEXT_STYLE.fontSize,
|
|
13
|
+
backgroundColor: style.backgroundColor,
|
|
14
|
+
lineHeight: style.lineHeight || DEFAULT_TEXT_STYLE.lineHeight,
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Applies text style to HTML element
|
|
18
|
+
* @param el HTML element to apply styles to
|
|
19
|
+
* @param style TextStyle object
|
|
20
|
+
*/
|
|
21
|
+
export const appendTextStyleToEl = (el, style) => {
|
|
22
|
+
if (style.color) {
|
|
23
|
+
el.style.color = style.color;
|
|
24
|
+
}
|
|
25
|
+
if (style.fontSize) {
|
|
26
|
+
el.style.fontSize = style.fontSize;
|
|
27
|
+
}
|
|
28
|
+
if (style.fontFamily) {
|
|
29
|
+
el.style.fontFamily = style.fontFamily;
|
|
30
|
+
}
|
|
31
|
+
if (style.backgroundColor) {
|
|
32
|
+
el.style.backgroundColor = style.backgroundColor;
|
|
33
|
+
}
|
|
34
|
+
if (style.lineHeight) {
|
|
35
|
+
el.style.lineHeight = style.lineHeight;
|
|
36
|
+
}
|
|
37
|
+
if (style.fontWeight) {
|
|
38
|
+
el.style.fontWeight = style.fontWeight;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Converts a style object to a CSS string representation
|
|
43
|
+
* @param styleObj The style object to convert
|
|
44
|
+
* @returns The CSS string representation
|
|
45
|
+
* @example
|
|
46
|
+
* styleObjectToString({ color: 'red', fontSize: '16px' })
|
|
47
|
+
* // returns "color: red; font-size: 16px"
|
|
48
|
+
*/
|
|
49
|
+
export function styleObjectToString(styleObj) {
|
|
50
|
+
return Object.entries(styleObj)
|
|
51
|
+
.map(([key, value]) => {
|
|
52
|
+
// Nếu key đã là kebab-case hoặc bắt đầu bằng dấu '-', giữ nguyên
|
|
53
|
+
const isPrefixed = key.startsWith('-');
|
|
54
|
+
const kebabKey = isPrefixed ? key : key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);
|
|
55
|
+
return `${kebabKey}: ${value}`;
|
|
56
|
+
})
|
|
57
|
+
.join('; ');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Normalizes a font-family string by adding quotes when needed
|
|
61
|
+
* @param fontFamily The font-family string to normalize
|
|
62
|
+
* @returns The normalized font-family string
|
|
63
|
+
* @description
|
|
64
|
+
* - Preserves existing quoted names
|
|
65
|
+
* - Doesn't quote generic families (e.g. sans-serif)
|
|
66
|
+
* - Quotes names containing spaces or special characters
|
|
67
|
+
* @example
|
|
68
|
+
* normalizeFontFamily('Arial, Helvetica, sans-serif')
|
|
69
|
+
* // returns 'Arial, Helvetica, sans-serif'
|
|
70
|
+
*
|
|
71
|
+
* normalizeFontFamily('Times New Roman, serif')
|
|
72
|
+
* // returns '"Times New Roman", serif'
|
|
73
|
+
*/
|
|
74
|
+
export function normalizeFontFamily(fontFamily) {
|
|
75
|
+
if (!fontFamily || typeof fontFamily !== 'string')
|
|
76
|
+
return '';
|
|
77
|
+
const genericFamilies = new Set([
|
|
78
|
+
'serif',
|
|
79
|
+
'sans-serif',
|
|
80
|
+
'monospace',
|
|
81
|
+
'cursive',
|
|
82
|
+
'fantasy',
|
|
83
|
+
'system-ui',
|
|
84
|
+
'ui-serif',
|
|
85
|
+
'ui-sans-serif',
|
|
86
|
+
'ui-monospace',
|
|
87
|
+
'ui-rounded',
|
|
88
|
+
'math',
|
|
89
|
+
'emoji',
|
|
90
|
+
'fangsong',
|
|
91
|
+
]);
|
|
92
|
+
return uniqBy(fontFamily.split(','), name => name.trim())
|
|
93
|
+
.map(name => {
|
|
94
|
+
const trimmed = name.trim();
|
|
95
|
+
// Preserve already quoted names
|
|
96
|
+
const isQuoted = (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
97
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'"));
|
|
98
|
+
if (isQuoted)
|
|
99
|
+
return trimmed;
|
|
100
|
+
// Do not quote generic family names
|
|
101
|
+
if (genericFamilies.has(trimmed))
|
|
102
|
+
return trimmed;
|
|
103
|
+
// Quote if contains whitespace or special characters
|
|
104
|
+
const needsQuotes = /[^\w-]/.test(trimmed);
|
|
105
|
+
return needsQuotes ? `"${trimmed}"` : trimmed;
|
|
106
|
+
})
|
|
107
|
+
.join(', ');
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Creates font-family string with fallback
|
|
111
|
+
* @param fontFamily Primary font family
|
|
112
|
+
* @param defaultFont Default fallback font
|
|
113
|
+
* @returns Normalized font-family string with fallback
|
|
114
|
+
*/
|
|
115
|
+
export const fontWithFallback = (fontFamily, defaultFont = DEFAULT_TEXT_STYLE.fontFamily) => normalizeFontFamily(fontFamily ? `${fontFamily}, ${defaultFont}` : defaultFont);
|
|
116
|
+
/**
|
|
117
|
+
* Checks if a color matches the link color
|
|
118
|
+
* @param color Color to check
|
|
119
|
+
* @returns true if color matches link color
|
|
120
|
+
*/
|
|
121
|
+
export const isLinkColor = (color) => tinycolor.equals(color, LINK_TEXT_COLOR);
|
|
122
|
+
/**
|
|
123
|
+
* Extracts CSS variables from a style object
|
|
124
|
+
* @param styleObj Style object that may contain CSS variables
|
|
125
|
+
* @returns Object with CSS variables and regular styles separated
|
|
126
|
+
*/
|
|
127
|
+
export function extractCSSVariables(styleObj) {
|
|
128
|
+
const cssVariables = {};
|
|
129
|
+
const regularStyles = {};
|
|
130
|
+
Object.entries(styleObj).forEach(([key, value]) => {
|
|
131
|
+
if (key.startsWith('--')) {
|
|
132
|
+
cssVariables[key] = value;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
regularStyles[key] = value;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return { cssVariables, regularStyles };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Merges multiple text styles with priority
|
|
142
|
+
* @param styles Array of text styles to merge
|
|
143
|
+
* @returns Merged text style
|
|
144
|
+
*/
|
|
145
|
+
export function mergeTextStyles(...styles) {
|
|
146
|
+
return styles.reduce((merged, style) => ({
|
|
147
|
+
...merged,
|
|
148
|
+
...Object.fromEntries(Object.entries(style).filter(([_, value]) => value !== undefined && value !== null)),
|
|
149
|
+
}), {});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Validates if a text style is complete
|
|
153
|
+
* @param style Text style to validate
|
|
154
|
+
* @returns true if all required properties are present
|
|
155
|
+
*/
|
|
156
|
+
export function isCompleteTextStyle(style) {
|
|
157
|
+
const requiredProps = [
|
|
158
|
+
'fontFamily',
|
|
159
|
+
'fontSize',
|
|
160
|
+
'color',
|
|
161
|
+
'backgroundColor',
|
|
162
|
+
'lineHeight',
|
|
163
|
+
'fontWeight',
|
|
164
|
+
];
|
|
165
|
+
return requiredProps.every(prop => style[prop] !== undefined);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Converts text style to CSS style object
|
|
169
|
+
* @param textStyle Text style object
|
|
170
|
+
* @returns CSS style object
|
|
171
|
+
*/
|
|
172
|
+
export function textStyleToCSSStyle(textStyle) {
|
|
173
|
+
const cssStyle = {};
|
|
174
|
+
if (textStyle.fontFamily) {
|
|
175
|
+
cssStyle.fontFamily = textStyle.fontFamily;
|
|
176
|
+
}
|
|
177
|
+
if (textStyle.fontSize) {
|
|
178
|
+
cssStyle.fontSize = textStyle.fontSize;
|
|
179
|
+
}
|
|
180
|
+
if (textStyle.color) {
|
|
181
|
+
cssStyle.color = textStyle.color;
|
|
182
|
+
}
|
|
183
|
+
if (textStyle.backgroundColor) {
|
|
184
|
+
cssStyle.backgroundColor = textStyle.backgroundColor;
|
|
185
|
+
}
|
|
186
|
+
if (textStyle.lineHeight) {
|
|
187
|
+
cssStyle.lineHeight = textStyle.lineHeight;
|
|
188
|
+
}
|
|
189
|
+
if (textStyle.fontWeight) {
|
|
190
|
+
cssStyle.fontWeight = textStyle.fontWeight;
|
|
191
|
+
}
|
|
192
|
+
return cssStyle;
|
|
193
|
+
}
|
|
@@ -15,4 +15,5 @@ export { AccountProfile, type AccountSettingProps } from './AccountProfile';
|
|
|
15
15
|
export * from './Login';
|
|
16
16
|
export * from './Filter';
|
|
17
17
|
export { ActivityTimeline, type ActivityTimeLineProps } from './ActivityTimeline';
|
|
18
|
+
export { TextEditor, TextEditorProvider, type TextEditorProps, type TextEditorRef, type TextEditorJSONContent, } from './TextEditor';
|
|
18
19
|
export { WhatsappMobile, SAMPLE_PREVIEW } from './PreviewCollections';
|
|
@@ -15,4 +15,5 @@ export { AccountProfile } from './AccountProfile';
|
|
|
15
15
|
export * from './Login';
|
|
16
16
|
export * from './Filter';
|
|
17
17
|
export { ActivityTimeline } from './ActivityTimeline';
|
|
18
|
+
export { TextEditor, TextEditorProvider, } from './TextEditor';
|
|
18
19
|
export { WhatsappMobile, SAMPLE_PREVIEW } from './PreviewCollections';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import url('./TextEditor/index.scss');
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { useEffect, useState, useRef } from 'react';
|
|
3
|
+
import { useDeepCompareEffect } from './useDeepCompareEffect';
|
|
4
|
+
export function useBroadcastedLocalStorage(key, initialValue) {
|
|
5
|
+
const [value, setValue] = useState(() => {
|
|
6
|
+
if (typeof window === 'undefined')
|
|
7
|
+
return initialValue;
|
|
8
|
+
try {
|
|
9
|
+
const saved = window.localStorage.getItem(key);
|
|
10
|
+
return saved != null ? JSON.parse(saved) : initialValue;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return initialValue;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
// We keep a ref to avoid re-creating the channel on every render
|
|
17
|
+
const channelRef = useRef(null);
|
|
18
|
+
// Initialize BroadcastChannel once
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (typeof window === 'undefined' || !('BroadcastChannel' in window)) {
|
|
21
|
+
console.warn('BroadcastChannel not supported in this environment');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const channel = new BroadcastChannel(`localstorage_${key}`);
|
|
25
|
+
channelRef.current = channel;
|
|
26
|
+
// Listen for incoming messages
|
|
27
|
+
const onMessage = (event) => {
|
|
28
|
+
setValue(event.data.value);
|
|
29
|
+
};
|
|
30
|
+
channel.addEventListener('message', onMessage);
|
|
31
|
+
return () => {
|
|
32
|
+
channel.removeEventListener('message', onMessage);
|
|
33
|
+
channel.close();
|
|
34
|
+
};
|
|
35
|
+
}, [key]);
|
|
36
|
+
// Whenever `value` changes, persist and broadcast
|
|
37
|
+
useDeepCompareEffect(() => {
|
|
38
|
+
if (typeof window === 'undefined')
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
window.localStorage.setItem(key, JSON.stringify(value));
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
console.error('Failed to write to localStorage:', err);
|
|
45
|
+
}
|
|
46
|
+
if (channelRef.current) {
|
|
47
|
+
channelRef.current.postMessage({ value });
|
|
48
|
+
}
|
|
49
|
+
}, [key, value]);
|
|
50
|
+
// Expose setter that mirrors functional API of useState
|
|
51
|
+
const setValueAndBroadcast = (next) => {
|
|
52
|
+
setValue(prev => {
|
|
53
|
+
const computed = next instanceof Function ? next(prev) : next;
|
|
54
|
+
return computed;
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
// Optional: a remove function
|
|
58
|
+
const remove = () => {
|
|
59
|
+
try {
|
|
60
|
+
window.localStorage.removeItem(key);
|
|
61
|
+
setValue(initialValue);
|
|
62
|
+
if (channelRef.current) {
|
|
63
|
+
channelRef.current.postMessage({ value: initialValue });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error('Failed to remove localStorage item:', err);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return { value, setValue: setValueAndBroadcast, remove };
|
|
71
|
+
}
|
package/es/utils/common.d.ts
CHANGED
|
@@ -66,17 +66,14 @@ export declare const searchParamsToObject: (searchParams?: string) => Record<str
|
|
|
66
66
|
export declare const getShuffleArray: <T>(array: T[]) => T[];
|
|
67
67
|
export declare const snakeCaseToCamelCase: <T = Record<string, any>>(object: Record<string, any> | Record<string, any>[], recursive?: boolean) => T;
|
|
68
68
|
export declare const camelCaseToSnakeCase: <T = Record<string, any>>(object: Record<string, any>, recursive?: boolean) => T;
|
|
69
|
-
export declare function generateKey():
|
|
69
|
+
export declare function generateKey(): string;
|
|
70
70
|
export declare const formatUserId: (userId?: number) => string;
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
/** Remove all accents and convert string to lower case, remove leading and trailing white space */
|
|
78
|
-
export declare const simplifyString: (str: string) => string;
|
|
79
|
-
/**
|
|
72
|
+
* Checks string matching based on a query, supporting fuzzy matching,
|
|
73
|
+
* where the query characters must appear in order within the target string.
|
|
74
|
+
* Allows for missing characters in the query relative to the target,
|
|
75
|
+
* and ignores case, diacritics, and spaces.
|
|
76
|
+
*
|
|
80
77
|
* @param str target string
|
|
81
78
|
* @param queryStr search query
|
|
82
79
|
* @returns true if target string includes search query
|