@antscorp/antsomi-ui 1.3.7-beta.6 → 1.3.7-beta.61
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/Input/Input.js +3 -1
- 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,4 +1,7 @@
|
|
|
1
|
-
import { Node, mergeAttributes } from '@tiptap/core';
|
|
1
|
+
import { Node, getMarksBetween, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
3
|
+
import uniqid from 'uniqid';
|
|
4
|
+
import { isSmartTagNode } from '../types';
|
|
2
5
|
export const EXTENSION_NAME = 'smartTag';
|
|
3
6
|
/**
|
|
4
7
|
* Represents a dynamic tag node in the editor.
|
|
@@ -12,6 +15,7 @@ export const SmartTag = Node.create({
|
|
|
12
15
|
addOptions() {
|
|
13
16
|
return {
|
|
14
17
|
HTMLAttributes: {},
|
|
18
|
+
generateSmartTagId: () => uniqid(),
|
|
15
19
|
};
|
|
16
20
|
},
|
|
17
21
|
addAttributes() {
|
|
@@ -29,6 +33,11 @@ export const SmartTag = Node.create({
|
|
|
29
33
|
parseHTML: el => el.getAttribute('tag'),
|
|
30
34
|
renderHTML: attrs => (attrs.tag ? { tag: attrs.tag } : null),
|
|
31
35
|
},
|
|
36
|
+
// Transient attribute - not persisted to HTML, used for tracking paste operations
|
|
37
|
+
sourceId: {
|
|
38
|
+
default: null,
|
|
39
|
+
rendered: false, // Don't include in HTML output
|
|
40
|
+
},
|
|
32
41
|
};
|
|
33
42
|
},
|
|
34
43
|
parseHTML() {
|
|
@@ -57,9 +66,10 @@ export const SmartTag = Node.create({
|
|
|
57
66
|
addCommands() {
|
|
58
67
|
return {
|
|
59
68
|
setSmartTag: attrs => ({ chain, state }) => {
|
|
60
|
-
const { selection
|
|
61
|
-
const {
|
|
62
|
-
|
|
69
|
+
const { selection } = state;
|
|
70
|
+
const { from, to } = selection;
|
|
71
|
+
// Get marks from inside the selection to capture boundary marks
|
|
72
|
+
const marks = getMarksBetween(from, to, state.doc).map(markRange => markRange.mark);
|
|
63
73
|
const smartTagNode = this.type.create(attrs);
|
|
64
74
|
const nodeWithMarks = marks.length > 0 ? smartTagNode.mark(marks) : smartTagNode;
|
|
65
75
|
return chain()
|
|
@@ -99,4 +109,86 @@ export const SmartTag = Node.create({
|
|
|
99
109
|
},
|
|
100
110
|
};
|
|
101
111
|
},
|
|
112
|
+
addProseMirrorPlugins() {
|
|
113
|
+
// Smart Tag Deduplication Plugin
|
|
114
|
+
// Responsibility: Set sourceId for pasted smart tags (for external component to handle cloning)
|
|
115
|
+
const deduplicationPlugin = new Plugin({
|
|
116
|
+
key: new PluginKey('smartTagDeduplication'),
|
|
117
|
+
appendTransaction: (transactions, oldState, newState) => {
|
|
118
|
+
// Only process if there was a paste or document change
|
|
119
|
+
const hasPaste = transactions.some(tr => tr.getMeta('paste'));
|
|
120
|
+
const hasDocChange = transactions.some(tr => tr.docChanged);
|
|
121
|
+
if (!hasPaste && !hasDocChange) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
// Build position mapping from oldState to newState
|
|
125
|
+
// This accounts for position shifts when pasting
|
|
126
|
+
const { mapping } = transactions[0];
|
|
127
|
+
// Build a map of existing smart tag IDs in oldState (before paste)
|
|
128
|
+
const oldStateIds = new Map();
|
|
129
|
+
oldState.doc.descendants((node, pos) => {
|
|
130
|
+
if (isSmartTagNode(node)) {
|
|
131
|
+
oldStateIds.set(node.attrs.id, { pos });
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
// Collect all smart tag IDs in newState (after paste)
|
|
135
|
+
const newStateIds = new Map();
|
|
136
|
+
newState.doc.descendants((node, pos) => {
|
|
137
|
+
if (isSmartTagNode(node)) {
|
|
138
|
+
const { id } = node.attrs;
|
|
139
|
+
if (!newStateIds.has(id)) {
|
|
140
|
+
newStateIds.set(id, []);
|
|
141
|
+
}
|
|
142
|
+
newStateIds.get(id).push({ pos, node });
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// Find duplicates: IDs that appear multiple times in newState
|
|
146
|
+
const nodesToSetSourceId = new Map();
|
|
147
|
+
newStateIds.forEach((positions, id) => {
|
|
148
|
+
if (positions.length > 1) {
|
|
149
|
+
// This ID has duplicates
|
|
150
|
+
const oldInfo = oldStateIds.get(id);
|
|
151
|
+
if (oldInfo) {
|
|
152
|
+
// Map old position to new position accounting for document changes
|
|
153
|
+
const mappedPos = mapping.map(oldInfo.pos);
|
|
154
|
+
// Filter out the original node (by mapped position), keep only pasted nodes
|
|
155
|
+
const pastedNodes = positions.filter(({ pos }) => pos !== mappedPos);
|
|
156
|
+
if (pastedNodes.length > 0) {
|
|
157
|
+
nodesToSetSourceId.set(id, pastedNodes);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// No original in oldState - all are new (e.g., paste multiple new smart tags)
|
|
162
|
+
// Pick first as "original", rest get sourceId
|
|
163
|
+
const [_first, ...rest] = positions;
|
|
164
|
+
if (rest.length > 0) {
|
|
165
|
+
nodesToSetSourceId.set(id, rest);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
// If no duplicates found, no action needed
|
|
171
|
+
if (nodesToSetSourceId.size === 0) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
// Set sourceId for pasted nodes (do NOT generate new IDs)
|
|
175
|
+
// External component will handle ID generation and attrs cloning
|
|
176
|
+
const { tr } = newState;
|
|
177
|
+
let hasChanges = false;
|
|
178
|
+
nodesToSetSourceId.forEach((positions, sourceId) => {
|
|
179
|
+
positions.forEach(({ pos, node }) => {
|
|
180
|
+
// Only set sourceId, keep original ID
|
|
181
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
182
|
+
...node.attrs,
|
|
183
|
+
sourceId,
|
|
184
|
+
id: this.options.generateSmartTagId?.() || uniqid(),
|
|
185
|
+
});
|
|
186
|
+
hasChanges = true;
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
return hasChanges ? tr : null;
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
return [deduplicationPlugin];
|
|
193
|
+
},
|
|
102
194
|
});
|
|
@@ -2,6 +2,7 @@ import { useBroadcastedLocalStorage, useDeepCompareEffect } from '@antscorp/ants
|
|
|
2
2
|
import { useTextEditorStore } from '../provider';
|
|
3
3
|
import { ANTSOMI_COMPONENT_PREFIX_CLS } from '@antscorp/antsomi-ui/es/constants';
|
|
4
4
|
import { useCallback } from 'react';
|
|
5
|
+
import isEqual from 'react-fast-compare';
|
|
5
6
|
export const useColorSet = () => {
|
|
6
7
|
const colors = useTextEditorStore(s => s.colors);
|
|
7
8
|
const setColors = useTextEditorStore(s => s.setColors);
|
|
@@ -9,9 +10,15 @@ export const useColorSet = () => {
|
|
|
9
10
|
useDeepCompareEffect(() => {
|
|
10
11
|
if (storageColors === undefined && colors !== undefined) {
|
|
11
12
|
setStorageColors(colors);
|
|
13
|
+
return;
|
|
12
14
|
}
|
|
13
15
|
if (colors === undefined && storageColors !== undefined) {
|
|
14
16
|
setColors(storageColors);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// Sync store → localStorage when both defined but different
|
|
20
|
+
if (colors !== undefined && storageColors !== undefined && !isEqual(colors, storageColors)) {
|
|
21
|
+
setStorageColors(colors);
|
|
15
22
|
}
|
|
16
23
|
}, [colors, storageColors, setColors, setStorageColors]);
|
|
17
24
|
const composeSetColors = useCallback((newColors) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { textBetween } from '../utils';
|
|
2
3
|
export function useMarkTracking(editor, options = {}) {
|
|
3
4
|
const { maxSnapshots = 10, excludeMarks = ['link', 'smartTag'], debounceDelay = 500, autoCapture = true, } = options;
|
|
4
5
|
const [snapshots, setSnapshots] = useState([]);
|
|
@@ -14,7 +15,7 @@ export function useMarkTracking(editor, options = {}) {
|
|
|
14
15
|
marks,
|
|
15
16
|
position: $from.pos,
|
|
16
17
|
timestamp: Date.now(),
|
|
17
|
-
textContent: editor.state
|
|
18
|
+
textContent: textBetween(editor.state, Math.max(0, $from.pos - 50), Math.min(editor.state.doc.content.size, $from.pos + 50)),
|
|
18
19
|
};
|
|
19
20
|
setSnapshots(prev => {
|
|
20
21
|
const updated = [snapshot, ...prev];
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { JSONContent } from '@tiptap/core';
|
|
3
|
-
export type { TextEditorProps, TextEditorRef, TextEditorComponentsRender, LinkAttrs, FontConfig, } from './types';
|
|
3
|
+
export type { TextEditorProps, TextEditorAllProps, TextEditorRef, TextEditorWithProviderRef, TextEditorComponentsRender, LinkAttrs, FontConfig, } from './types';
|
|
4
4
|
export { isLinkMark, isLinkMarkRange } from './types';
|
|
5
5
|
export { CUSTOM_LINK_EXTENSION_NAME } from './constants';
|
|
6
6
|
export type { JSONContent as TextEditorJSONContent };
|
|
7
7
|
export { TextEditorProvider, type TextEditorProviderProps, type TextEditorProviderRefHandler, } from './provider';
|
|
8
|
-
export declare const TextEditor: import("react").
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export declare const TextEditor: import("react").ForwardRefExoticComponent<import("./types").TextEditorProps & {
|
|
9
|
+
colors?: string[] | undefined;
|
|
10
|
+
onChangeColors?: ((colors: string[]) => void) | undefined;
|
|
11
|
+
} & import("react").RefAttributes<import("./types").TextEditorWithProviderRef>> & {
|
|
12
|
+
Provider: import("react").ForwardRefExoticComponent<import("./provider").TextEditorProviderProps & import("react").RefAttributes<import("./provider").TextEditorProviderRefHandler>>;
|
|
13
|
+
Internal: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<import("./types").TextEditorProps & import("react").RefAttributes<import("./types").TextEditorRef>>>;
|
|
12
14
|
} & {
|
|
13
15
|
Utils: {
|
|
14
16
|
htmlMinifyForEmail: (htmlEditorContent: string) => string;
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
position: absolute;
|
|
4
4
|
pointer-events: auto;
|
|
5
5
|
z-index: 999;
|
|
6
|
+
background-color: white;
|
|
7
|
+
border-radius: 4px;
|
|
8
|
+
padding: 15px;
|
|
9
|
+
box-shadow: var(--antsomi-box-shadow-secondary);
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
.antsomi-text-editor-emoji-popover {
|
|
@@ -59,10 +63,3 @@
|
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
|
-
|
|
63
|
-
.antsomi-text-editor-bubble-menu {
|
|
64
|
-
background-color: white;
|
|
65
|
-
border-radius: 4px;
|
|
66
|
-
padding: 15px;
|
|
67
|
-
box-shadow: var(--antsomi-box-shadow-secondary);
|
|
68
|
-
}
|
|
@@ -8,6 +8,7 @@ export interface TextEditorProviderRefHandler {
|
|
|
8
8
|
}
|
|
9
9
|
export interface TextEditorProviderProps {
|
|
10
10
|
children: React.ReactNode | ((props: TextEditorStoreApi) => React.ReactNode);
|
|
11
|
+
colors?: string[];
|
|
11
12
|
onChangeColors?: (colors: string[]) => void;
|
|
12
13
|
}
|
|
13
14
|
export declare const TextEditorProvider: import("react").ForwardRefExoticComponent<TextEditorProviderProps & import("react").RefAttributes<TextEditorProviderRefHandler>>;
|
|
@@ -5,10 +5,12 @@ import { useStore } from 'zustand';
|
|
|
5
5
|
// Store
|
|
6
6
|
import { createTextEditorStore } from './store';
|
|
7
7
|
export const TextEditorStoreContext = createContext(null);
|
|
8
|
-
export const TextEditorProvider = forwardRef(({ children, onChangeColors }, ref) => {
|
|
8
|
+
export const TextEditorProvider = forwardRef(({ children, colors, onChangeColors }, ref) => {
|
|
9
9
|
const storeRef = useRef();
|
|
10
10
|
if (!storeRef.current) {
|
|
11
|
-
storeRef.current = createTextEditorStore(
|
|
11
|
+
storeRef.current = createTextEditorStore({
|
|
12
|
+
colors,
|
|
13
|
+
});
|
|
12
14
|
}
|
|
13
15
|
useEffect(() => {
|
|
14
16
|
storeRef.current?.setState({
|
|
@@ -20,7 +22,8 @@ export const TextEditorProvider = forwardRef(({ children, onChangeColors }, ref)
|
|
|
20
22
|
}, [onChangeColors]);
|
|
21
23
|
useImperativeHandle(ref, () => ({
|
|
22
24
|
updateColors: colors => {
|
|
23
|
-
|
|
25
|
+
// Use getInitialState to bypass the wrapped setColors and avoid triggering onChangeColors
|
|
26
|
+
storeRef.current?.getInitialState().setColors(colors);
|
|
24
27
|
},
|
|
25
28
|
}));
|
|
26
29
|
return (_jsx(TextEditorStoreContext.Provider, { value: storeRef.current, children: typeof children === 'function' ? children(storeRef.current) : children }));
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import type { LinkFormData, LinkFormState } from './types';
|
|
1
2
|
export type TextEditorState = {
|
|
2
|
-
bubbleMenuContainer:
|
|
3
|
-
isShowBubbleMenu: boolean;
|
|
3
|
+
bubbleMenuContainer: HTMLElement | null;
|
|
4
4
|
colors?: string[];
|
|
5
|
+
/** Link form state for default link insert/edit UI */
|
|
6
|
+
linkFormState: LinkFormState;
|
|
5
7
|
};
|
|
6
8
|
export type TextEditorActions = {
|
|
7
|
-
setBubbleMenuContainer: (container:
|
|
8
|
-
setIsShowBubbleMenu: (isShow: boolean) => void;
|
|
9
|
+
setBubbleMenuContainer: (container: HTMLElement | null) => void;
|
|
9
10
|
setColors: (newColorSet: string[]) => void;
|
|
11
|
+
/** Show link form with initial data */
|
|
12
|
+
showLinkForm: (mode: 'insert' | 'edit', initialData: LinkFormData) => void;
|
|
13
|
+
/** Hide link form */
|
|
14
|
+
hideLinkForm: () => void;
|
|
15
|
+
/** Update link form data (partial update) */
|
|
16
|
+
updateLinkFormData: (data: Partial<LinkFormData>) => void;
|
|
10
17
|
};
|
|
11
18
|
export type TextEditorStore = TextEditorState & TextEditorActions;
|
|
12
19
|
export declare const defaultTextEditorState: TextEditorState;
|
|
@@ -3,13 +3,12 @@ import isEqual from 'react-fast-compare';
|
|
|
3
3
|
import { createStore } from 'zustand';
|
|
4
4
|
export const defaultTextEditorState = {
|
|
5
5
|
bubbleMenuContainer: null,
|
|
6
|
-
|
|
6
|
+
linkFormState: null,
|
|
7
7
|
};
|
|
8
8
|
export const createTextEditorStore = (initState = {}) => createStore()((set, get) => ({
|
|
9
9
|
...defaultTextEditorState,
|
|
10
10
|
...initState,
|
|
11
11
|
setBubbleMenuContainer: container => set(() => ({ bubbleMenuContainer: container })),
|
|
12
|
-
setIsShowBubbleMenu: isShow => set(() => ({ isShowBubbleMenu: isShow })),
|
|
13
12
|
setColors: newColors => {
|
|
14
13
|
const currentColors = get().colors;
|
|
15
14
|
if (isEqual(currentColors, newColors)) {
|
|
@@ -17,4 +16,25 @@ export const createTextEditorStore = (initState = {}) => createStore()((set, get
|
|
|
17
16
|
}
|
|
18
17
|
set(() => ({ colors: newColors }));
|
|
19
18
|
},
|
|
19
|
+
showLinkForm: (mode, initialData) => set(() => ({
|
|
20
|
+
linkFormState: {
|
|
21
|
+
isVisible: true,
|
|
22
|
+
mode,
|
|
23
|
+
data: initialData,
|
|
24
|
+
},
|
|
25
|
+
})),
|
|
26
|
+
hideLinkForm: () => set(() => ({ linkFormState: null })),
|
|
27
|
+
updateLinkFormData: data => set(state => {
|
|
28
|
+
if (!state.linkFormState)
|
|
29
|
+
return state;
|
|
30
|
+
return {
|
|
31
|
+
linkFormState: {
|
|
32
|
+
...state.linkFormState,
|
|
33
|
+
data: {
|
|
34
|
+
...state.linkFormState.data,
|
|
35
|
+
...data,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}),
|
|
20
40
|
}));
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rawHTML": "<div class=\"fr-element fr-view\" dir=\"auto\" contenteditable=\"true\" aria-disabled=\"false\" spellcheck=\"true\"><p><span style=\"font-family: Montserrat; font-size: 22px; letter-spacing: 0px; color: #000000;\"><a data-link-id=\"j24jwuk2\" target=\"_blank\" href=\"https://ant.design/components/modal\"><span data-dynamic=\"true\" data-dynamic-id=\"i6fapgk6\" style=\"direction: unset; unicode-bidi: bidi-override; background-color: rgba(0, 199, 97, 0.2);\">Last modified by</span></a> Special <a data-link-id=\"rrd48wh5\" target=\"_blank\" href=\"https://ant.design\">Bonus <span data-dynamic=\"true\" data-dynamic-id=\"4ip5g3w4\" style=\"direction: unset; unicode-bidi: bidi-override; background-color: rgba(0, 199, 97, 0.2);\">Created date</span> Has</a> Been <span data-dynamic=\"true\" data-dynamic-id=\"vd3tmfc3\" style=\"direction: unset; unicode-bidi: bidi-override; background-color: rgba(0, 199, 97, 0.2);\"><a data-link-id=\"ir1h7e67\" target=\"_blank\" href=\"https://fireup.pro/news/goodbye-useeffect-exploring-use-in-react-19?ref=dailydev\">Name</a></span> Special <a data-link-id=\"rrd48wh5\" href=\"https://ant.design\" target=\"_blank\" id=\"isPasted\">Bonus</a> fasdfas sdfadf</span></p></div>",
|
|
3
|
+
"dynamic": {
|
|
4
|
+
"data": {
|
|
5
|
+
"4ip5g3w4": {
|
|
6
|
+
"type": "visitor-attribute",
|
|
7
|
+
"attribute": {
|
|
8
|
+
"label": "Created date",
|
|
9
|
+
"value": "date_created",
|
|
10
|
+
"status": 1,
|
|
11
|
+
"dataType": "datetime",
|
|
12
|
+
"disabled": false,
|
|
13
|
+
"datetimeFormatSettings": {
|
|
14
|
+
"type": "datetime",
|
|
15
|
+
"language": "en",
|
|
16
|
+
"hasDateFormat": true,
|
|
17
|
+
"hasTimeFormat": true,
|
|
18
|
+
"dateParseFormat": "MM/DD/YYYY",
|
|
19
|
+
"dateParseOption": "medium",
|
|
20
|
+
"timeParseFormat": "12hour",
|
|
21
|
+
"timeParseOption": "medium",
|
|
22
|
+
"dateFormatString": "MMM DD, YYYY h:mm:ss A"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"mappingKey": "lg5pk39o2qmxyc7oano5-4ip5g3w4",
|
|
26
|
+
"mappingFields": "visitor.date_created"
|
|
27
|
+
},
|
|
28
|
+
"i6fapgk6": {
|
|
29
|
+
"type": "event-attribute",
|
|
30
|
+
"event": "226539:17",
|
|
31
|
+
"source": [556657814],
|
|
32
|
+
"attribute": {
|
|
33
|
+
"type": 1,
|
|
34
|
+
"label": "Last modified by",
|
|
35
|
+
"value": "ad_zone.u_user_id",
|
|
36
|
+
"status": 1,
|
|
37
|
+
"children": [],
|
|
38
|
+
"dataType": "number",
|
|
39
|
+
"itemTypeId": -1013,
|
|
40
|
+
"itemTypeName": "ad_zone",
|
|
41
|
+
"propertyName": "u_user_id",
|
|
42
|
+
"eventPropertySyntax": "dims.ad_zone_id",
|
|
43
|
+
"numberFormatSettings": {
|
|
44
|
+
"type": "number",
|
|
45
|
+
"decimal": ".",
|
|
46
|
+
"grouping": ",",
|
|
47
|
+
"isCompact": false,
|
|
48
|
+
"prefixType": "code",
|
|
49
|
+
"currencyCode": "USD",
|
|
50
|
+
"decimalPlaces": 2
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"mappingKey": "lg5pk39o2qmxyc7oano5-i6fapgk6",
|
|
54
|
+
"mappingFields": "event.ad_zone.u_user_id"
|
|
55
|
+
},
|
|
56
|
+
"vd3tmfc3": {
|
|
57
|
+
"type": "customer-attribute",
|
|
58
|
+
"attribute": {
|
|
59
|
+
"label": "Name",
|
|
60
|
+
"value": "name",
|
|
61
|
+
"status": 1,
|
|
62
|
+
"dataType": "string",
|
|
63
|
+
"disabled": false
|
|
64
|
+
},
|
|
65
|
+
"mappingKey": "lg5pk39o2qmxyc7oano5-vd3tmfc3",
|
|
66
|
+
"mappingFields": "customer.name"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"highlight": true,
|
|
70
|
+
"selectedId": ""
|
|
71
|
+
},
|
|
72
|
+
"link": {
|
|
73
|
+
"data": {
|
|
74
|
+
"ir1h7e67": {
|
|
75
|
+
"url": "https://fireup.pro/news/goodbye-useeffect-exploring-use-in-react-19?ref=dailydev",
|
|
76
|
+
"text": "Name",
|
|
77
|
+
"linkType": "static",
|
|
78
|
+
"openNewTab": true
|
|
79
|
+
},
|
|
80
|
+
"j24jwuk2": {
|
|
81
|
+
"url": "https://ant.design/components/modal",
|
|
82
|
+
"text": "Your",
|
|
83
|
+
"linkType": "static",
|
|
84
|
+
"openNewTab": true
|
|
85
|
+
},
|
|
86
|
+
"rrd48wh5": {
|
|
87
|
+
"url": "https://ant.design",
|
|
88
|
+
"text": "Bonus Offer Has",
|
|
89
|
+
"linkType": "static",
|
|
90
|
+
"openNewTab": true
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"selectedId": ""
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⚠️ LEGACY FORMAT TYPES
|
|
3
|
+
* These types represent the OLD format from Froala editor
|
|
4
|
+
* DO NOT modify unless you understand the legacy compatibility requirements
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Dynamic tag data structure from Froala editor
|
|
8
|
+
* Used for backwards compatibility with old HTML format
|
|
9
|
+
*/
|
|
10
|
+
export type DynamicData = {
|
|
11
|
+
type: string;
|
|
12
|
+
attribute?: {
|
|
13
|
+
label: string;
|
|
14
|
+
value: string;
|
|
15
|
+
dataType?: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
18
|
+
event?: string;
|
|
19
|
+
source?: number[];
|
|
20
|
+
mappingKey: string;
|
|
21
|
+
mappingFields: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Link data structure from Froala editor
|
|
25
|
+
* Used for backwards compatibility with old HTML format
|
|
26
|
+
*/
|
|
27
|
+
export type LinkData = {
|
|
28
|
+
url: string;
|
|
29
|
+
text: string;
|
|
30
|
+
linkType: string;
|
|
31
|
+
openNewTab: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* State management for old format demo
|
|
35
|
+
*/
|
|
36
|
+
export type State = {
|
|
37
|
+
link: {
|
|
38
|
+
data: Record<string, LinkData>;
|
|
39
|
+
selectedId: string;
|
|
40
|
+
};
|
|
41
|
+
dynamic: {
|
|
42
|
+
data: Record<string, DynamicData>;
|
|
43
|
+
selectedId: string;
|
|
44
|
+
highlight: boolean;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Actions for state reducer
|
|
49
|
+
*/
|
|
50
|
+
export type Action = {
|
|
51
|
+
type: 'add_smart_tag';
|
|
52
|
+
payload: {
|
|
53
|
+
selectionText: string;
|
|
54
|
+
};
|
|
55
|
+
} | {
|
|
56
|
+
type: 'edit_smart_tag';
|
|
57
|
+
payload: {
|
|
58
|
+
id: string;
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
type: 'delete_smart_tag';
|
|
62
|
+
payload: {
|
|
63
|
+
id: string;
|
|
64
|
+
};
|
|
65
|
+
} | {
|
|
66
|
+
type: 'save_smart_tag';
|
|
67
|
+
payload: {
|
|
68
|
+
id: string;
|
|
69
|
+
data: DynamicData;
|
|
70
|
+
};
|
|
71
|
+
} | {
|
|
72
|
+
type: 'add_link';
|
|
73
|
+
payload: {
|
|
74
|
+
selectionText: string;
|
|
75
|
+
};
|
|
76
|
+
} | {
|
|
77
|
+
type: 'edit_link';
|
|
78
|
+
payload: {
|
|
79
|
+
id: string;
|
|
80
|
+
data?: Partial<LinkData>;
|
|
81
|
+
};
|
|
82
|
+
} | {
|
|
83
|
+
type: 'delete_link';
|
|
84
|
+
payload: {
|
|
85
|
+
id: string;
|
|
86
|
+
};
|
|
87
|
+
} | {
|
|
88
|
+
type: 'close_smart_tag_modal';
|
|
89
|
+
} | {
|
|
90
|
+
type: 'close_link_modal';
|
|
91
|
+
} | {
|
|
92
|
+
type: 'toggle_highlight';
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Reducer for managing old format demo state
|
|
96
|
+
*/
|
|
97
|
+
export declare const reducer: (state: State, action: Action) => State;
|
|
98
|
+
/**
|
|
99
|
+
* Constants for dynamic tag types
|
|
100
|
+
*/
|
|
101
|
+
export declare const DYNAMIC_TAG_TYPES: {
|
|
102
|
+
label: string;
|
|
103
|
+
value: string;
|
|
104
|
+
}[];
|
|
105
|
+
/**
|
|
106
|
+
* Constants for data types
|
|
107
|
+
*/
|
|
108
|
+
export declare const DATA_TYPES: {
|
|
109
|
+
label: string;
|
|
110
|
+
value: string;
|
|
111
|
+
}[];
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { produce } from 'immer';
|
|
2
|
+
import uniqid from 'uniqid';
|
|
3
|
+
/**
|
|
4
|
+
* Reducer for managing old format demo state
|
|
5
|
+
*/
|
|
6
|
+
export const reducer = (state, action) => produce(state, draft => {
|
|
7
|
+
switch (action.type) {
|
|
8
|
+
case 'add_smart_tag': {
|
|
9
|
+
draft.dynamic.selectedId = uniqid();
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
case 'edit_smart_tag': {
|
|
13
|
+
draft.dynamic.selectedId = action.payload.id;
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
case 'delete_smart_tag': {
|
|
17
|
+
delete draft.dynamic.data[action.payload.id];
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case 'save_smart_tag': {
|
|
21
|
+
draft.dynamic.data[action.payload.id] = action.payload.data;
|
|
22
|
+
draft.dynamic.selectedId = '';
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'close_smart_tag_modal': {
|
|
26
|
+
draft.dynamic.selectedId = '';
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case 'add_link': {
|
|
30
|
+
const newLinkId = uniqid();
|
|
31
|
+
draft.link.selectedId = newLinkId;
|
|
32
|
+
draft.link.data[newLinkId] = {
|
|
33
|
+
url: '',
|
|
34
|
+
text: action.payload.selectionText,
|
|
35
|
+
linkType: 'static',
|
|
36
|
+
openNewTab: true,
|
|
37
|
+
};
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case 'edit_link': {
|
|
41
|
+
draft.link.selectedId = action.payload.id;
|
|
42
|
+
if (action.payload.data) {
|
|
43
|
+
draft.link.data[action.payload.id] = {
|
|
44
|
+
...state.link.data[action.payload.id],
|
|
45
|
+
...action.payload.data,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case 'delete_link': {
|
|
51
|
+
delete draft.link.data[action.payload.id];
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'close_link_modal': {
|
|
55
|
+
draft.link.selectedId = '';
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case 'toggle_highlight': {
|
|
59
|
+
draft.dynamic.highlight = !draft.dynamic.highlight;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
default:
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Constants for dynamic tag types
|
|
68
|
+
*/
|
|
69
|
+
export const DYNAMIC_TAG_TYPES = [
|
|
70
|
+
{ label: 'Customer Attribute', value: 'customer-attribute' },
|
|
71
|
+
{ label: 'Visitor Attribute', value: 'visitor-attribute' },
|
|
72
|
+
{ label: 'Event Attribute', value: 'event-attribute' },
|
|
73
|
+
];
|
|
74
|
+
/**
|
|
75
|
+
* Constants for data types
|
|
76
|
+
*/
|
|
77
|
+
export const DATA_TYPES = [
|
|
78
|
+
{ label: 'String', value: 'string' },
|
|
79
|
+
{ label: 'Number', value: 'number' },
|
|
80
|
+
{ label: 'Datetime', value: 'datetime' },
|
|
81
|
+
{ label: 'Boolean', value: 'boolean' },
|
|
82
|
+
];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse HTML content from mock data
|
|
3
|
+
*/
|
|
4
|
+
export declare const htmlContent: string;
|
|
5
|
+
/**
|
|
6
|
+
* State type for TextBlock component
|
|
7
|
+
*/
|
|
8
|
+
export type State = {
|
|
9
|
+
link: {
|
|
10
|
+
data: Record<string, {
|
|
11
|
+
url: string;
|
|
12
|
+
text: string;
|
|
13
|
+
title: string;
|
|
14
|
+
}>;
|
|
15
|
+
selectedId: string;
|
|
16
|
+
};
|
|
17
|
+
dynamic: {
|
|
18
|
+
data: Record<string, unknown>;
|
|
19
|
+
selectedId: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Action types for TextBlock reducer
|
|
24
|
+
*/
|
|
25
|
+
export type Action = {
|
|
26
|
+
type: 'add_smart_tag';
|
|
27
|
+
payload: {
|
|
28
|
+
selectionText: string;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
type: 'edit_smart_tag';
|
|
32
|
+
payload: {
|
|
33
|
+
id: string;
|
|
34
|
+
};
|
|
35
|
+
} | {
|
|
36
|
+
type: 'add_link';
|
|
37
|
+
payload: {
|
|
38
|
+
selectionText: string;
|
|
39
|
+
};
|
|
40
|
+
} | {
|
|
41
|
+
type: 'edit_link';
|
|
42
|
+
payload: {
|
|
43
|
+
id: string;
|
|
44
|
+
data?: Partial<{
|
|
45
|
+
url: string;
|
|
46
|
+
text: string;
|
|
47
|
+
title: string;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
} | {
|
|
51
|
+
type: 'close_smart_tag_modal';
|
|
52
|
+
} | {
|
|
53
|
+
type: 'close_link_modal';
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Reducer for TextBlock component state management
|
|
57
|
+
*/
|
|
58
|
+
export declare const reducer: (state: State, action: Action) => State;
|
|
59
|
+
/**
|
|
60
|
+
* Props for TextBlock component
|
|
61
|
+
*/
|
|
62
|
+
export type TextBlockProps = {
|
|
63
|
+
defaultValue?: string;
|
|
64
|
+
};
|