@chenyomi/leafer-htmltext-editor 1.0.0 → 1.0.2
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/dist/TextEditTool/index.d.ts +2 -2
- package/dist/TextEditTool/index.d.ts.map +1 -1
- package/dist/TextEditTool/index.js +44 -70
- package/dist/TextEditTool/utils.d.ts.map +1 -1
- package/dist/TextEditTool/utils.js +96 -13
- package/dist/TextEditor.d.ts +9 -6
- package/dist/TextEditor.d.ts.map +1 -1
- package/dist/TextEditor.js +66 -63
- package/dist/esm/TextEditTool/index.d.ts +2 -2
- package/dist/esm/TextEditTool/index.d.ts.map +1 -1
- package/dist/esm/TextEditTool/index.js +46 -72
- package/dist/esm/TextEditTool/utils.d.ts.map +1 -1
- package/dist/esm/TextEditTool/utils.js +96 -13
- package/dist/esm/TextEditor.d.ts +9 -6
- package/dist/esm/TextEditor.d.ts.map +1 -1
- package/dist/esm/TextEditor.js +66 -63
- package/dist/esm/index.d.ts +17 -5
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +1 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +29 -48
- package/dist/index.d.ts +17 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +130 -72
- package/dist/index.js +164 -83
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +29 -48
- package/package.json +3 -3
- package/src/TextEditTool/index.ts +77 -92
- package/src/TextEditTool/utils.ts +101 -29
- package/src/TextEditor.ts +104 -90
- package/src/index.ts +141 -79
- package/src/utils.ts +140 -178
|
@@ -1,145 +1,130 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import { EditTool, Editor, registerEditTool, EditorScaleEvent, EditorMoveEvent } from '@leafer-in/editor';
|
|
10
|
-
import { updataHtmlText } from '../utils';
|
|
11
|
-
import { TextEditor } from '../TextEditor';
|
|
12
|
-
|
|
13
|
-
// 简单的防抖函数实现
|
|
14
|
-
function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
|
|
15
|
-
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
16
|
-
return function(this: any, ...args: Parameters<T>) {
|
|
17
|
-
if (timeout) clearTimeout(timeout);
|
|
18
|
-
timeout = setTimeout(() => func.apply(this, args), wait);
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
1
|
+
import {
|
|
2
|
+
EditTool,
|
|
3
|
+
EditorScaleEvent,
|
|
4
|
+
registerEditTool
|
|
5
|
+
} from "@leafer-in/editor";
|
|
6
|
+
import { PointerEvent } from "leafer-ui";
|
|
7
|
+
import { quillManager } from "../";
|
|
8
|
+
import { updataHtmlText } from "../utils";
|
|
22
9
|
@registerEditTool()
|
|
10
|
+
// 定义插件类,继承自 EditTool,处理矩形圆角编辑交互
|
|
23
11
|
export class TextEditTool extends EditTool {
|
|
12
|
+
// 插件标识标签
|
|
24
13
|
public get tag() {
|
|
25
|
-
return
|
|
14
|
+
return "TextEditTool";
|
|
26
15
|
}
|
|
27
|
-
|
|
28
16
|
public quill: any = null;
|
|
29
|
-
private _dragRAF: number | null = null;
|
|
30
17
|
private updateBoxDebounced: (text: any) => void;
|
|
31
|
-
|
|
18
|
+
// 构造函数,初始化控制点并加入视图
|
|
32
19
|
constructor(editor: any) {
|
|
33
20
|
super(editor);
|
|
34
|
-
this.eventIds = [];
|
|
35
|
-
this.updateBoxDebounced = debounce((text: any) => {
|
|
21
|
+
this.eventIds = []; // 存储事件绑定ID
|
|
22
|
+
this.updateBoxDebounced = this.debounce((text: any) => {
|
|
36
23
|
updataHtmlText(text);
|
|
37
24
|
}, 300);
|
|
38
25
|
}
|
|
39
|
-
|
|
26
|
+
// 自定义防抖函数替代 lodash/debounce
|
|
27
|
+
private debounce<T extends (...args: any[]) => any>(
|
|
28
|
+
func: T,
|
|
29
|
+
wait: number,
|
|
30
|
+
): T {
|
|
31
|
+
let timeout: number | null = null;
|
|
32
|
+
return ((...args: any[]) => {
|
|
33
|
+
if (timeout !== null) {
|
|
34
|
+
window.clearTimeout(timeout);
|
|
35
|
+
}
|
|
36
|
+
timeout = window.setTimeout(
|
|
37
|
+
() => func.apply(this, args),
|
|
38
|
+
wait,
|
|
39
|
+
) as unknown as number;
|
|
40
|
+
}) as T;
|
|
41
|
+
}
|
|
42
|
+
// 绑定事件
|
|
40
43
|
public addEvent(): void {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const text = this.editor.element.findOne('HTMLText');
|
|
44
|
-
if (!text) return;
|
|
45
|
-
|
|
44
|
+
const { editor } = quillManager.getCanvas();
|
|
45
|
+
const text = editor._target.findOne("HTMLText");
|
|
46
46
|
const { scaleX, scaleY } = text.worldTransform;
|
|
47
47
|
const zoomScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
|
|
48
|
-
const div: any = document.querySelector(
|
|
49
|
-
|
|
50
|
-
if (!div) return;
|
|
51
|
-
|
|
48
|
+
const div: any = document.querySelector("#textInnerEditor");
|
|
52
49
|
const { style } = div;
|
|
53
|
-
|
|
54
50
|
this.eventIds = [
|
|
55
|
-
|
|
56
|
-
if (!text.data) text.data = {};
|
|
51
|
+
editor.on_(EditorScaleEvent.SCALE, (e: any) => {
|
|
57
52
|
if (!text.data.canChangeBox) {
|
|
58
53
|
text.data.canChangeBox = true;
|
|
59
54
|
}
|
|
60
|
-
if (text.data.canChangeBox
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
style.width = parentWidth * zoomScale + 'px';
|
|
64
|
-
style.height = 'auto';
|
|
65
|
-
}
|
|
55
|
+
if (text.data.canChangeBox) {
|
|
56
|
+
style.width = text.parent.width * zoomScale + "px";
|
|
57
|
+
style.height = "auto";
|
|
66
58
|
}
|
|
67
59
|
this.updateBoxDebounced(text);
|
|
68
60
|
}),
|
|
69
|
-
|
|
70
|
-
if (!text.parent
|
|
71
|
-
|
|
61
|
+
editor.on_(PointerEvent.DOUBLE_TAP, () => {
|
|
62
|
+
if (!text.parent.locked) {
|
|
63
|
+
editor.openInnerEditor(text, true);
|
|
72
64
|
}
|
|
73
|
-
})
|
|
65
|
+
}),
|
|
74
66
|
];
|
|
75
67
|
}
|
|
76
68
|
|
|
69
|
+
// 生命周期钩子:插件加载时绑定事件
|
|
77
70
|
public onLoad(): void {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const text: any =
|
|
81
|
-
if (!text) return;
|
|
82
|
-
|
|
71
|
+
console.log(22222222)
|
|
72
|
+
const { editor } = quillManager.getCanvas();
|
|
73
|
+
const text: any = editor._target.findOne("HTMLText");
|
|
83
74
|
const { scaleX, scaleY } = text.worldTransform;
|
|
84
75
|
const zoomScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
|
|
85
|
-
|
|
86
76
|
this.addEvent();
|
|
87
|
-
this.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (this.quill && text.text) {
|
|
91
|
-
this.quill.clipboard.dangerouslyPasteHTML(text.text);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const div: any = document.querySelector('#textInnerEditor');
|
|
95
|
-
if (!div) return;
|
|
96
|
-
|
|
77
|
+
this.quill = quillManager.getQuill();
|
|
78
|
+
this.quill.clipboard.dangerouslyPasteHTML(text.text);
|
|
79
|
+
const div: any = document.querySelector("#textInnerEditor");
|
|
97
80
|
const { style } = div;
|
|
98
81
|
|
|
99
|
-
if (text.data
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (parentWidth !== undefined) {
|
|
103
|
-
style.width = parentWidth * zoomScale + 'px';
|
|
104
|
-
}
|
|
105
|
-
if (parentHeight !== undefined) {
|
|
106
|
-
style.height = parentHeight * zoomScale + 'px';
|
|
107
|
-
}
|
|
82
|
+
if (text.data.canChangeBox) {
|
|
83
|
+
style.width = text.parent.width * zoomScale + "px";
|
|
84
|
+
style.height = text.parent.height * zoomScale + "px";
|
|
108
85
|
} else {
|
|
109
|
-
style.width =
|
|
110
|
-
style.height =
|
|
86
|
+
style.width = "auto";
|
|
87
|
+
style.height = "auto";
|
|
111
88
|
}
|
|
89
|
+
// 每次进来就恢复初始的 canChangeBox 和 自动的宽高
|
|
90
|
+
// text.set({
|
|
91
|
+
// width: 0,
|
|
92
|
+
// height: 0
|
|
93
|
+
// })
|
|
94
|
+
// text.data.canChangeBox = false
|
|
112
95
|
}
|
|
113
96
|
|
|
114
97
|
private isUpdatingPoints = false;
|
|
115
98
|
private curveAmount = 0;
|
|
116
|
-
|
|
117
99
|
public updateChangeBoxBound(text: any): void {
|
|
118
|
-
|
|
100
|
+
text &&
|
|
119
101
|
text.set({
|
|
120
102
|
width: text.__layout.boxBounds.width,
|
|
121
|
-
height: text.__layout.boxBounds.height
|
|
103
|
+
height: text.__layout.boxBounds.height,
|
|
122
104
|
});
|
|
123
|
-
}
|
|
124
105
|
}
|
|
125
|
-
|
|
106
|
+
// 生命周期钩子:插件更新时,因为这是全局的生命周期所以判断一定要细致仔细
|
|
126
107
|
public onUpdate(): void {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const el = this.editor.element;
|
|
133
|
-
console.log('文本bound更新');
|
|
108
|
+
const { editor } = quillManager.getCanvas();
|
|
109
|
+
const text = editor._target.findOne("HTMLText");
|
|
110
|
+
const el = editor._target;
|
|
111
|
+
console.log("文本bound更新");
|
|
134
112
|
|
|
135
|
-
|
|
136
|
-
if (this.curveAmount === (text as any).curveAmount) return;
|
|
113
|
+
if (this.curveAmount == (text as any).curveAmount) return;
|
|
137
114
|
if (this.isUpdatingPoints) return;
|
|
115
|
+
// 每次进来就恢复初始的 canChangeBox 和 自动的宽高
|
|
116
|
+
// text.set({
|
|
117
|
+
// width: 0,
|
|
118
|
+
// height: 0
|
|
119
|
+
// })
|
|
138
120
|
}
|
|
139
121
|
|
|
122
|
+
// 生命周期钩子:插件卸载时解绑事件
|
|
140
123
|
public onUnload(): void {
|
|
141
|
-
|
|
124
|
+
const { editor } = quillManager.getCanvas();
|
|
125
|
+
editor.off_(this.eventIds);
|
|
142
126
|
}
|
|
143
127
|
|
|
128
|
+
// 生命周期钩子:销毁插件时清理资源
|
|
144
129
|
public onDestroy(): void {}
|
|
145
130
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { HTMLText } from '@leafer-in/html'; // 导入 html 插件
|
|
2
|
+
import { Box, Path } from 'leafer-ui'
|
|
3
3
|
export function getArcRadius(fontSize: number, curveAmount: number): number {
|
|
4
4
|
if (curveAmount === 0) return Infinity
|
|
5
5
|
const theta = (330 * fontSize * 72) / 96
|
|
@@ -82,22 +82,105 @@ export const handleShowCurve = (element: any, op: boolean) => {
|
|
|
82
82
|
|
|
83
83
|
// base 映射:只需把普通字符 -> 上标/下标(任意已有的上/下标字符)列出来一次
|
|
84
84
|
const baseSuperscript: Record<string, string> = {
|
|
85
|
-
'0': '⁰',
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
'
|
|
85
|
+
'0': '⁰',
|
|
86
|
+
'1': '¹',
|
|
87
|
+
'2': '²',
|
|
88
|
+
'3': '³',
|
|
89
|
+
'4': '⁴',
|
|
90
|
+
'5': '⁵',
|
|
91
|
+
'6': '⁶',
|
|
92
|
+
'7': '⁷',
|
|
93
|
+
'8': '⁸',
|
|
94
|
+
'9': '⁹',
|
|
95
|
+
a: 'ᵃ',
|
|
96
|
+
b: 'ᵇ',
|
|
97
|
+
c: 'ᶜ',
|
|
98
|
+
d: 'ᵈ',
|
|
99
|
+
e: 'ᵉ',
|
|
100
|
+
f: 'ᶠ',
|
|
101
|
+
g: 'ᵍ',
|
|
102
|
+
h: 'ʰ',
|
|
103
|
+
i: 'ⁱ',
|
|
104
|
+
j: 'ʲ',
|
|
105
|
+
k: 'ᵏ',
|
|
106
|
+
l: 'ˡ',
|
|
107
|
+
m: 'ᵐ',
|
|
108
|
+
n: 'ⁿ',
|
|
109
|
+
o: 'ᵒ',
|
|
110
|
+
p: 'ᵖ',
|
|
111
|
+
r: 'ʳ',
|
|
112
|
+
s: 'ˢ',
|
|
113
|
+
t: 'ᵗ',
|
|
114
|
+
u: 'ᵘ',
|
|
115
|
+
v: 'ᵛ',
|
|
116
|
+
w: 'ʷ',
|
|
117
|
+
x: 'ˣ',
|
|
118
|
+
y: 'ʸ',
|
|
119
|
+
z: 'ᶻ',
|
|
120
|
+
A: 'ᴬ',
|
|
121
|
+
B: 'ᴮ',
|
|
122
|
+
D: 'ᴰ',
|
|
123
|
+
E: 'ᴱ',
|
|
124
|
+
G: 'ᴳ',
|
|
125
|
+
H: 'ᴴ',
|
|
126
|
+
I: 'ᴵ',
|
|
127
|
+
J: 'ᴶ',
|
|
128
|
+
K: 'ᴷ',
|
|
129
|
+
L: 'ᴸ',
|
|
130
|
+
M: 'ᴹ',
|
|
131
|
+
N: 'ᴺ',
|
|
132
|
+
O: 'ᴼ',
|
|
133
|
+
P: 'ᴾ',
|
|
134
|
+
R: 'ᴿ',
|
|
135
|
+
T: 'ᵀ',
|
|
136
|
+
U: 'ᵁ',
|
|
137
|
+
W: 'ᵂ',
|
|
138
|
+
'+': '⁺',
|
|
139
|
+
'-': '⁻',
|
|
140
|
+
'=': '⁼',
|
|
141
|
+
'(': '⁽',
|
|
142
|
+
')': '⁾'
|
|
92
143
|
}
|
|
93
144
|
|
|
94
145
|
const baseSubscript: Record<string, string> = {
|
|
95
|
-
'0': '₀',
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
'
|
|
146
|
+
'0': '₀',
|
|
147
|
+
'1': '₁',
|
|
148
|
+
'2': '₂',
|
|
149
|
+
'3': '₃',
|
|
150
|
+
'4': '₄',
|
|
151
|
+
'5': '₅',
|
|
152
|
+
'6': '₆',
|
|
153
|
+
'7': '₇',
|
|
154
|
+
'8': '₈',
|
|
155
|
+
'9': '₉',
|
|
156
|
+
a: 'ₐ',
|
|
157
|
+
e: 'ₑ',
|
|
158
|
+
h: 'ₕ',
|
|
159
|
+
i: 'ᵢ',
|
|
160
|
+
j: 'ⱼ',
|
|
161
|
+
k: 'ₖ',
|
|
162
|
+
l: 'ₗ',
|
|
163
|
+
m: 'ₘ',
|
|
164
|
+
n: 'ₙ',
|
|
165
|
+
o: 'ₒ',
|
|
166
|
+
p: 'ₚ',
|
|
167
|
+
r: 'ᵣ',
|
|
168
|
+
s: 'ₛ',
|
|
169
|
+
t: 'ₜ',
|
|
170
|
+
u: 'ᵤ',
|
|
171
|
+
v: 'ᵥ',
|
|
172
|
+
x: 'ₓ',
|
|
173
|
+
'+': '₊',
|
|
174
|
+
'-': '₋',
|
|
175
|
+
'=': '₌',
|
|
176
|
+
'(': '₍',
|
|
177
|
+
')': '₎',
|
|
99
178
|
// 常见希腊字母的下标形式(如需要可加入)
|
|
100
|
-
|
|
179
|
+
β: 'ᵦ',
|
|
180
|
+
γ: 'ᵧ',
|
|
181
|
+
ρ: 'ᵨ',
|
|
182
|
+
φ: 'ᵩ',
|
|
183
|
+
χ: 'ᵪ'
|
|
101
184
|
}
|
|
102
185
|
|
|
103
186
|
// helper: 从 base 映射中收集所有已知上标/下标字符(用于反向映射)
|
|
@@ -110,13 +193,10 @@ function invertMap(map: Record<string, string>): Record<string, string> {
|
|
|
110
193
|
}
|
|
111
194
|
|
|
112
195
|
const knownSupers = invertMap(baseSuperscript) // '¹' -> '¹', 'ᵃ'->'ᵃ' ...
|
|
113
|
-
const knownSubs = invertMap(baseSubscript)
|
|
196
|
+
const knownSubs = invertMap(baseSubscript) // '₁' -> '₁', 'ₐ'->'ₐ' ...
|
|
114
197
|
|
|
115
198
|
// 生成最终的“鲁棒”映射:接受普通字符、上标字符、下标字符,统一输出目标形式
|
|
116
|
-
function buildSuperscriptMap(
|
|
117
|
-
baseSup: Record<string, string>,
|
|
118
|
-
baseSub: Record<string, string>
|
|
119
|
-
): Record<string, string> {
|
|
199
|
+
function buildSuperscriptMap(baseSup: Record<string, string>, baseSub: Record<string, string>): Record<string, string> {
|
|
120
200
|
const out: Record<string, string> = {}
|
|
121
201
|
|
|
122
202
|
// 普通字符 -> 上标
|
|
@@ -136,10 +216,7 @@ function buildSuperscriptMap(
|
|
|
136
216
|
return out
|
|
137
217
|
}
|
|
138
218
|
|
|
139
|
-
function buildSubscriptMap(
|
|
140
|
-
baseSup: Record<string, string>,
|
|
141
|
-
baseSub: Record<string, string>
|
|
142
|
-
): Record<string, string> {
|
|
219
|
+
function buildSubscriptMap(baseSup: Record<string, string>, baseSub: Record<string, string>): Record<string, string> {
|
|
143
220
|
const out: Record<string, string> = {}
|
|
144
221
|
|
|
145
222
|
// 普通字符 -> 下标
|
|
@@ -177,16 +254,12 @@ export function toSubscript(input: string): string {
|
|
|
177
254
|
return out
|
|
178
255
|
}
|
|
179
256
|
|
|
180
|
-
|
|
181
257
|
export const superscriptMapVal = Object.values(superscriptMap)
|
|
182
258
|
|
|
183
259
|
export const subscriptMapVal = Object.values(subscriptMap)
|
|
184
260
|
|
|
185
261
|
// 构建 normalMap:所有上标、下标字符 → 对应的普通 base 字符
|
|
186
|
-
function buildNormalMap(
|
|
187
|
-
baseSup: Record<string, string>,
|
|
188
|
-
baseSub: Record<string, string>
|
|
189
|
-
): Record<string, string> {
|
|
262
|
+
function buildNormalMap(baseSup: Record<string, string>, baseSub: Record<string, string>): Record<string, string> {
|
|
190
263
|
const normal: Record<string, string> = {}
|
|
191
264
|
|
|
192
265
|
// 上标的 value → key(普通)
|
|
@@ -213,4 +286,3 @@ export function toNormal(input: string): string {
|
|
|
213
286
|
}
|
|
214
287
|
return out
|
|
215
288
|
}
|
|
216
|
-
|