@visactor/vrender-core 0.22.0-vstory.1 → 0.22.0-vstory.11

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.
Files changed (88) hide show
  1. package/cjs/core/global.d.ts +0 -3
  2. package/cjs/core/global.js +1 -7
  3. package/cjs/core/global.js.map +1 -1
  4. package/cjs/graphic/builtin-symbol/utils.js +1 -1
  5. package/cjs/graphic/builtin-symbol/utils.js.map +1 -1
  6. package/cjs/graphic/config.js +1 -0
  7. package/cjs/graphic/config.js.map +1 -1
  8. package/cjs/graphic/graphic.d.ts +1 -1
  9. package/cjs/graphic/graphic.js +9 -9
  10. package/cjs/graphic/graphic.js.map +1 -1
  11. package/cjs/graphic/group.d.ts +1 -0
  12. package/cjs/graphic/group.js +6 -1
  13. package/cjs/graphic/group.js.map +1 -1
  14. package/cjs/graphic/richtext/line.js +13 -1
  15. package/cjs/graphic/richtext/line.js.map +1 -1
  16. package/cjs/graphic/richtext/paragraph.d.ts +9 -1
  17. package/cjs/graphic/richtext/paragraph.js +50 -11
  18. package/cjs/graphic/richtext/paragraph.js.map +1 -1
  19. package/cjs/graphic/richtext/utils.js +4 -4
  20. package/cjs/graphic/richtext/utils.js.map +1 -1
  21. package/cjs/graphic/richtext.d.ts +2 -1
  22. package/cjs/graphic/richtext.js +10 -1
  23. package/cjs/graphic/richtext.js.map +1 -1
  24. package/cjs/interface/global.d.ts +0 -1
  25. package/cjs/interface/global.js.map +1 -1
  26. package/cjs/interface/graphic/richText.d.ts +11 -0
  27. package/cjs/interface/graphic/richText.js.map +1 -1
  28. package/cjs/interface/graphic.d.ts +1 -1
  29. package/cjs/interface/graphic.js.map +1 -1
  30. package/cjs/plugins/builtin-plugin/edit-module.d.ts +2 -1
  31. package/cjs/plugins/builtin-plugin/edit-module.js +20 -15
  32. package/cjs/plugins/builtin-plugin/edit-module.js.map +1 -1
  33. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.d.ts +37 -11
  34. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.js +329 -136
  35. package/cjs/plugins/builtin-plugin/richtext-edit-plugin.js.map +1 -1
  36. package/cjs/render/contributions/render/contributions/image-contribution-render.d.ts +1 -1
  37. package/cjs/render/contributions/render/contributions/image-contribution-render.js +2 -2
  38. package/cjs/render/contributions/render/contributions/image-contribution-render.js.map +1 -1
  39. package/cjs/render/contributions/render/draw-contribution.js +3 -2
  40. package/cjs/render/contributions/render/draw-contribution.js.map +1 -1
  41. package/cjs/render/contributions/render/image-render.js.map +1 -1
  42. package/cjs/resource-loader/loader.js +1 -1
  43. package/cjs/resource-loader/loader.js.map +1 -1
  44. package/dist/index.es.js +521 -113
  45. package/es/core/global.d.ts +0 -3
  46. package/es/core/global.js +1 -8
  47. package/es/core/global.js.map +1 -1
  48. package/es/graphic/builtin-symbol/utils.js +1 -1
  49. package/es/graphic/builtin-symbol/utils.js.map +1 -1
  50. package/es/graphic/config.js +1 -0
  51. package/es/graphic/config.js.map +1 -1
  52. package/es/graphic/graphic.d.ts +1 -1
  53. package/es/graphic/graphic.js +10 -10
  54. package/es/graphic/graphic.js.map +1 -1
  55. package/es/graphic/group.d.ts +1 -0
  56. package/es/graphic/group.js +6 -1
  57. package/es/graphic/group.js.map +1 -1
  58. package/es/graphic/richtext/line.js +13 -1
  59. package/es/graphic/richtext/line.js.map +1 -1
  60. package/es/graphic/richtext/paragraph.d.ts +9 -1
  61. package/es/graphic/richtext/paragraph.js +50 -11
  62. package/es/graphic/richtext/paragraph.js.map +1 -1
  63. package/es/graphic/richtext/utils.js +4 -4
  64. package/es/graphic/richtext/utils.js.map +1 -1
  65. package/es/graphic/richtext.d.ts +2 -1
  66. package/es/graphic/richtext.js +10 -1
  67. package/es/graphic/richtext.js.map +1 -1
  68. package/es/interface/global.d.ts +0 -1
  69. package/es/interface/global.js.map +1 -1
  70. package/es/interface/graphic/richText.d.ts +11 -0
  71. package/es/interface/graphic/richText.js.map +1 -1
  72. package/es/interface/graphic.d.ts +1 -1
  73. package/es/interface/graphic.js.map +1 -1
  74. package/es/plugins/builtin-plugin/edit-module.d.ts +2 -1
  75. package/es/plugins/builtin-plugin/edit-module.js +17 -13
  76. package/es/plugins/builtin-plugin/edit-module.js.map +1 -1
  77. package/es/plugins/builtin-plugin/richtext-edit-plugin.d.ts +37 -11
  78. package/es/plugins/builtin-plugin/richtext-edit-plugin.js +327 -135
  79. package/es/plugins/builtin-plugin/richtext-edit-plugin.js.map +1 -1
  80. package/es/render/contributions/render/contributions/image-contribution-render.d.ts +1 -1
  81. package/es/render/contributions/render/contributions/image-contribution-render.js +2 -2
  82. package/es/render/contributions/render/contributions/image-contribution-render.js.map +1 -1
  83. package/es/render/contributions/render/draw-contribution.js +2 -2
  84. package/es/render/contributions/render/draw-contribution.js.map +1 -1
  85. package/es/render/contributions/render/image-render.js.map +1 -1
  86. package/es/resource-loader/loader.js +1 -1
  87. package/es/resource-loader/loader.js.map +1 -1
  88. package/package.json +3 -3
@@ -2,11 +2,11 @@ import { isObject, merge } from "@visactor/vutils";
2
2
 
3
3
  import { Generator } from "../../common/generator";
4
4
 
5
- import { createGroup, createLine, createRect, RichText } from "../../graphic";
5
+ import { createGroup, createLine, createRect, createRichText, getRichTextBounds, RichText } from "../../graphic";
6
6
 
7
7
  import { DefaultTicker, DefaultTimeline } from "../../animate";
8
8
 
9
- import { EditModule, findConfigIndexByCursorIdx } from "./edit-module";
9
+ import { EditModule, findConfigIndexByCursorIdx, getDefaultCharacterConfig } from "./edit-module";
10
10
 
11
11
  import { application } from "../../application";
12
12
 
@@ -36,18 +36,19 @@ class Selection {
36
36
  if (!this.rt) return null;
37
37
  let idx = Math.round(cursorIdx);
38
38
  const config = this.rt.attribute.textConfig;
39
+ if (!config.length) return null;
39
40
  for (let i = 0; i < config.length; i++) if ("\n" !== config[i].text && (idx--, idx < 0)) return config[i][key];
40
41
  return null !== (_a = config[Math.min(idx, config.length - 1)][key]) && void 0 !== _a ? _a : this.rt.attribute[key];
41
42
  }
42
43
  getFormat(key) {
43
44
  return this.getAllFormat(key)[0];
44
45
  }
45
- getAllFormat(key) {
46
+ getAllFormat(key, includeUndefined) {
46
47
  const valSet = new Set, minCursorIdx = Math.min(this.selectionStartCursorIdx, this.curCursorIdx), maxCursorIdx = Math.max(this.selectionStartCursorIdx, this.curCursorIdx);
47
48
  if (minCursorIdx === maxCursorIdx) return [ this._getFormat(key, minCursorIdx) ];
48
49
  for (let i = Math.ceil(minCursorIdx); i <= Math.floor(maxCursorIdx); i++) {
49
50
  const val = this._getFormat(key, i);
50
- val && valSet.add(val);
51
+ (includeUndefined || void 0 !== val) && valSet.add(val);
51
52
  }
52
53
  return Array.from(valSet.values());
53
54
  }
@@ -55,6 +56,8 @@ class Selection {
55
56
 
56
57
  export const FORMAT_TEXT_COMMAND = "FORMAT_TEXT_COMMAND";
57
58
 
59
+ export const FORMAT_ALL_TEXT_COMMAND = "FORMAT_ALL_TEXT_COMMAND";
60
+
58
61
  export const FORMAT_ELEMENT_COMMAND = "FORMAT_ELEMENT_COMMAND";
59
62
 
60
63
  export class RichTextEditPlugin {
@@ -74,43 +77,59 @@ export class RichTextEditPlugin {
74
77
  }
75
78
  constructor() {
76
79
  this.name = "RichTextEditPlugin", this.activeEvent = "onRegister", this._uid = Generator.GenAutoIncrementId(),
77
- this.key = this.name + this._uid, this.editing = !1, this.pointerDown = !1, this.handleKeyDown = e => {
80
+ this.key = this.name + this._uid, this.editing = !1, this.focusing = !1, this.pointerDown = !1,
81
+ this.formatTextCommandCb = (payload, p) => {
82
+ const rt = p.currRt;
83
+ if (!rt) return;
84
+ const selectionData = p.getSelection();
85
+ if (!selectionData) return;
86
+ const {selectionStartCursorIdx: selectionStartCursorIdx, curCursorIdx: curCursorIdx} = selectionData, minCursorIdx = Math.min(selectionStartCursorIdx, curCursorIdx), maxCursorIdx = Math.max(selectionStartCursorIdx, curCursorIdx), minConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, minCursorIdx), maxConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, maxCursorIdx), config = rt.attribute.textConfig.slice(minConfigIdx, maxConfigIdx);
87
+ this._formatTextCommand(payload, config, rt);
88
+ }, this.formatAllTextCommandCb = (payload, p) => {
89
+ const rt = p.currRt;
90
+ if (!rt) return;
91
+ const config = rt.attribute.textConfig;
92
+ this._formatTextCommand(payload, config, rt);
93
+ }, this.handleKeyDown = e => {
78
94
  this.currRt && this.editing && (this.copyToClipboard(e) || this.fullSelection(e) || this.directKey(e));
79
95
  }, this.handleInput = (text, isComposing, cursorIdx, rt) => {
80
- this.hideSelection(), this.updateCbs.forEach((cb => cb("input", this)));
96
+ this.currRt && (this.tryShowShadowPlaceholder(), this.tryShowInputBounds(), this.hideSelection(),
97
+ this.updateCbs.forEach((cb => cb("input", this))));
81
98
  }, this.handleChange = (text, isComposing, cursorIdx, rt) => {
82
- this.curCursorIdx = cursorIdx, this.selectionStartCursorIdx = cursorIdx;
99
+ if (!this.currRt) return;
100
+ this.tryShowShadowPlaceholder(), this.tryShowInputBounds(), this.curCursorIdx = cursorIdx,
101
+ this.selectionStartCursorIdx = cursorIdx;
83
102
  const p = this.computedCursorPosByCursorIdx(cursorIdx, rt);
84
103
  this.setCursorAndTextArea(p.x, p.y1, p.y2, rt), this.hideSelection(), this.updateCbs.forEach((cb => cb("change", this)));
85
- }, this.handleFocusIn = () => {}, this.handleFocusOut = () => {
86
- this.editing = !1, this.deFocus(), this.pointerDown = !1, this.triggerRender(),
87
- this.updateCbs.forEach((cb => cb("defocus", this)));
104
+ }, this.handleFocusIn = () => {
105
+ throw new Error("不会走到这里 handleFocusIn");
106
+ }, this.handleFocusOut = () => {
107
+ throw new Error("不会走到这里 handleFocusOut");
88
108
  }, this.handleMove = e => {
89
- this.isRichtext(e) && (this.currRt = e.target, this.handleEnter(e), e.target.once("pointerleave", this.handleLeave),
90
- this.tryShowSelection(e, !1));
91
- }, this.handleEnter = e => {
109
+ this.currRt && !this.currRt.attribute.editable && this.deFocus(!0), this.isEditableRichtext(e) ? (this.handleEnter(),
110
+ e.target.once("pointerleave", this.handleLeave), this.tryShowSelection(e, !1)) : this.handleLeave();
111
+ }, this.handleEnter = () => {
92
112
  this.editing = !0, this.pluginService.stage.setCursor("text");
93
- }, this.handleLeave = e => {
113
+ }, this.handleLeave = () => {
94
114
  this.editing = !1, this.pluginService.stage.setCursor("default");
95
115
  }, this.handlePointerDown = e => {
96
- this.editing ? this.onFocus(e) : this.deFocus(), this.triggerRender(), this.pointerDown = !0,
97
- this.updateCbs.forEach((cb => cb(this.editing ? "onfocus" : "defocus", this)));
116
+ this.editing && this.isEditableRichtext(e) ? this.onFocus(e) : this.deFocus(!0),
117
+ this.triggerRender(), this.pointerDown = !0, this.updateCbs.forEach((cb => cb(this.editing ? "onfocus" : "defocus", this)));
98
118
  }, this.handlePointerUp = e => {
99
119
  this.pointerDown = !1;
100
120
  }, this.handleDBLClick = e => {
101
121
  this.editing && this.tryShowSelection(e, !0);
102
122
  }, this.commandCbs = new Map, this.commandCbs.set(FORMAT_TEXT_COMMAND, [ this.formatTextCommandCb ]),
103
- this.updateCbs = [], this.timeline = new DefaultTimeline, this.ticker = new DefaultTicker([ this.timeline ]),
123
+ this.commandCbs.set(FORMAT_ALL_TEXT_COMMAND, [ this.formatAllTextCommandCb ]), this.updateCbs = [],
124
+ this.timeline = new DefaultTimeline, this.ticker = new DefaultTicker([ this.timeline ]),
104
125
  this.deltaX = 0, this.deltaY = 0;
105
126
  }
106
- formatTextCommandCb(payload, p) {
107
- const rt = p.currRt;
108
- if (!rt) return;
109
- const selectionData = p.getSelection();
110
- if (!selectionData) return;
111
- const {selectionStartCursorIdx: selectionStartCursorIdx, curCursorIdx: curCursorIdx} = selectionData, minCursorIdx = Math.min(selectionStartCursorIdx, curCursorIdx), maxCursorIdx = Math.max(selectionStartCursorIdx, curCursorIdx), minConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, minCursorIdx), maxConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, maxCursorIdx), config = rt.attribute.textConfig.slice(minConfigIdx, maxConfigIdx);
127
+ _formatTextCommand(payload, config, rt) {
112
128
  "bold" === payload ? config.forEach((item => item.fontWeight = "bold")) : "italic" === payload ? config.forEach((item => item.fontStyle = "italic")) : "underline" === payload ? config.forEach((item => item.underline = !0)) : "lineThrough" === payload ? config.forEach((item => item.lineThrough = !0)) : isObject(payload) && config.forEach((item => merge(item, payload))),
113
129
  rt.setAttributes(rt.attribute);
130
+ const cache = rt.getFrameCache();
131
+ cache && (this.selectionRangeByCursorIdx(this.selectionStartCursorIdx, this.curCursorIdx, cache),
132
+ this.tryShowInputBounds());
114
133
  }
115
134
  dispatchCommand(command, payload) {
116
135
  const cbs = this.commandCbs.get(command);
@@ -119,9 +138,17 @@ export class RichTextEditPlugin {
119
138
  registerCommand(command, cb) {
120
139
  (this.commandCbs.get(command) || []).push(cb);
121
140
  }
141
+ removeCommand(command, cb) {
142
+ const cbs = this.commandCbs.get(command) || [], idx = cbs.indexOf(cb);
143
+ idx > -1 && cbs.splice(idx, 1);
144
+ }
122
145
  registerUpdateListener(cb) {
123
146
  (this.updateCbs || []).push(cb);
124
147
  }
148
+ removeUpdateListener(cb) {
149
+ const cbs = this.updateCbs || [], idx = cbs.indexOf(cb);
150
+ idx > -1 && cbs.splice(idx, 1);
151
+ }
125
152
  activate(context) {
126
153
  this.pluginService = context, this.editModule = new EditModule, context.stage.on("pointermove", this.handleMove),
127
154
  context.stage.on("pointerdown", this.handlePointerDown), context.stage.on("pointerup", this.handlePointerUp),
@@ -143,8 +170,10 @@ export class RichTextEditPlugin {
143
170
  if (!cache) return;
144
171
  const {lines: lines} = cache, totalCursorCount = lines.reduce(((total, line) => total + line.paragraphs.length), 0) - 1;
145
172
  startIdx > endIdx && ([startIdx, endIdx] = [ endIdx, startIdx ]), startIdx = Math.min(Math.max(startIdx, -.1), totalCursorCount + .1),
146
- endIdx = Math.min(Math.max(endIdx, -.1), totalCursorCount + .1), this.curCursorIdx = endIdx,
147
- this.selectionStartCursorIdx = startIdx;
173
+ endIdx = Math.min(Math.max(endIdx, -.1), totalCursorCount + .1), this.selectionRangeByCursorIdx(startIdx, endIdx, cache);
174
+ }
175
+ selectionRangeByCursorIdx(startCursorIdx, endCursorIdx, cache) {
176
+ this.curCursorIdx = endCursorIdx, this.selectionStartCursorIdx = startCursorIdx;
148
177
  const {x: x, y1: y1, y2: y2} = this.computedCursorPosByCursorIdx(this.selectionStartCursorIdx, this.currRt);
149
178
  this.startCursorPos = {
150
179
  x: x,
@@ -159,7 +188,10 @@ export class RichTextEditPlugin {
159
188
  if (!currRt) return;
160
189
  const cache = currRt.getFrameCache();
161
190
  if (!cache) return;
162
- const {lines: lines} = cache, totalCursorCount = lines.reduce(((total, line) => total + line.paragraphs.length), 0) - 1;
191
+ const {lines: lines} = cache;
192
+ if (0 === lines.length) return;
193
+ if (!lines[0].paragraphs || 0 === lines[0].paragraphs.length) return;
194
+ const totalCursorCount = lines.reduce(((total, line) => total + line.paragraphs.length), 0) - 1;
163
195
  return this.selectionRange(-.1, totalCursorCount + .1), e.preventDefault(), !0;
164
196
  }
165
197
  return !1;
@@ -173,7 +205,8 @@ export class RichTextEditPlugin {
173
205
  const {lineInfo: lineInfo, columnInfo: columnInfo} = this.getColumnByIndex(cache, Math.round(this.curCursorIdx)), {lines: lines} = cache, totalCursorCount = lines.reduce(((total, line) => total + line.paragraphs.length), 0) - 1;
174
206
  if (x) {
175
207
  x > 0 && columnInfo === lineInfo.paragraphs[lineInfo.paragraphs.length - 2] && this.curCursorIdx < Math.round(this.curCursorIdx) ? this.curCursorIdx = this.curCursorIdx + .2 : x > 0 && columnInfo === lineInfo.paragraphs[lineInfo.paragraphs.length - 1] && this.curCursorIdx > Math.round(this.curCursorIdx) ? this.curCursorIdx = this.curCursorIdx + 1 - .2 : x < 0 && columnInfo === lineInfo.paragraphs[0] && this.curCursorIdx > Math.round(this.curCursorIdx) ? this.curCursorIdx = this.curCursorIdx - .2 : x < 0 && columnInfo === lineInfo.paragraphs[0] && this.curCursorIdx < Math.round(this.curCursorIdx) ? this.curCursorIdx = this.curCursorIdx - 1 + .2 : this.curCursorIdx += x,
176
- this.curCursorIdx < -.1 ? this.curCursorIdx = -.1 : this.curCursorIdx > totalCursorCount + .1 && (this.curCursorIdx = totalCursorCount + .1);
208
+ this.curCursorIdx < -.1 ? this.curCursorIdx = -.1 : this.curCursorIdx > totalCursorCount + .1 && (this.curCursorIdx = totalCursorCount + .1),
209
+ this.selectionStartCursorIdx = this.curCursorIdx;
177
210
  const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt);
178
211
  this.setCursorAndTextArea(pos.x, pos.y1, pos.y2, this.currRt), this.hideSelection();
179
212
  }
@@ -197,60 +230,164 @@ export class RichTextEditPlugin {
197
230
  }
198
231
  return !0;
199
232
  }
233
+ tryShowShadowPlaceholder() {
234
+ if (!this.currRt) return;
235
+ const shadowRoot = this.currRt.shadowRoot;
236
+ if (shadowRoot) {
237
+ const placeholder = shadowRoot.getElementsByType("richtext")[0];
238
+ placeholder && shadowRoot.removeChild(placeholder);
239
+ }
240
+ const {textConfig: textConfig, editOptions: editOptions} = this.currRt.attribute;
241
+ if (textConfig && textConfig.length) return;
242
+ if (!editOptions || !editOptions.placeholder) return;
243
+ const {placeholder: placeholder, placeholderColor: placeholderColor = "rgba(0, 0, 0, 0.6)", placeholderFontFamily: placeholderFontFamily, placeholderFontSize: placeholderFontSize} = editOptions, shadow = this.getShadow(this.currRt), textConfigItem = Object.assign(Object.assign({}, getDefaultCharacterConfig(this.currRt.attribute)), {
244
+ text: placeholder
245
+ });
246
+ placeholderColor && (textConfigItem.fill = placeholderColor), placeholderFontFamily && (textConfigItem.fontFamily = placeholderFontFamily),
247
+ placeholderFontSize && (textConfigItem.fontSize = placeholderFontSize), this.shadowPlaceHolder = createRichText(Object.assign(Object.assign({}, this.currRt.attribute), {
248
+ x: 0,
249
+ y: 0,
250
+ pickable: !1,
251
+ editable: !1,
252
+ editOptions: null,
253
+ angle: 0,
254
+ _debug_bounds: !1,
255
+ textConfig: [ textConfigItem ]
256
+ })), shadow.add(this.shadowPlaceHolder);
257
+ }
258
+ tryShowInputBounds() {
259
+ if (!this.currRt || !this.focusing) return;
260
+ const {editOptions: editOptions = {}} = this.currRt.attribute, {boundsStrokeWhenInput: boundsStrokeWhenInput} = editOptions;
261
+ if (!editOptions || !boundsStrokeWhenInput) return;
262
+ const {attribute: attribute} = this.currRt;
263
+ let b = this.currRt.AABBBounds, h = b.height();
264
+ if (!attribute.textConfig.length && this.editLine) {
265
+ const {points: points} = this.editLine.attribute;
266
+ h = points[1].y - points[0].y, b = getRichTextBounds(Object.assign({}, this.shadowPlaceHolder.attribute));
267
+ }
268
+ this.shadowBounds = this.shadowBounds || createRect({}), this.shadowBounds.setAttributes({
269
+ x: 0,
270
+ y: 0,
271
+ width: b.width(),
272
+ height: h,
273
+ fill: !1,
274
+ stroke: boundsStrokeWhenInput,
275
+ lineWidth: 1,
276
+ zIndex: -1
277
+ });
278
+ this.getShadow(this.currRt).add(this.shadowBounds), this.offsetLineBgAndShadowBounds();
279
+ }
280
+ trySyncPlaceholderToTextConfig() {
281
+ if (!this.currRt) return;
282
+ const {textConfig: textConfig, editOptions: editOptions} = this.currRt.attribute;
283
+ if (textConfig && textConfig.length) return;
284
+ if (!(editOptions && editOptions.placeholder && editOptions.syncPlaceHolderToTextConfig)) return;
285
+ const {placeholder: placeholder} = editOptions;
286
+ this.currRt.setAttributes({
287
+ textConfig: [ Object.assign({
288
+ text: placeholder
289
+ }, getDefaultCharacterConfig(this.currRt.attribute)) ]
290
+ });
291
+ }
200
292
  deactivate(context) {
201
293
  context.stage.off("pointermove", this.handleMove), context.stage.off("pointerdown", this.handlePointerDown),
202
294
  context.stage.off("pointerup", this.handlePointerUp), context.stage.off("pointerleave", this.handlePointerUp),
203
295
  context.stage.off("dblclick", this.handleDBLClick), application.global.addEventListener("keydown", this.handleKeyDown);
204
296
  }
205
- onFocus(e) {
206
- this.deFocus(), this.currRt = e.target;
297
+ onFocus(e, data) {
298
+ this.updateCbs && this.updateCbs.forEach((cb => cb("beforeOnfocus", this))), this.deFocus(!1),
299
+ this.focusing = !0;
207
300
  const target = e.target;
208
- RichTextEditPlugin.tryUpdateRichtext(target);
209
- const shadowRoot = target.attachShadow(), cache = target.getFrameCache();
210
- if (!cache) return;
211
- if (this.computeGlobalDelta(cache), shadowRoot.setAttributes({
212
- shadowRootIdx: 1,
213
- pickable: !1,
214
- x: this.deltaX,
215
- y: this.deltaY
216
- }), !this.editLine) {
217
- const line = createLine({
218
- x: 0,
219
- y: 0,
220
- lineWidth: 1,
221
- stroke: "black"
222
- });
223
- this.addAnimateToLine(line), this.editLine = line, this.ticker.start(!0);
224
- const g = createGroup({
225
- x: 0,
226
- y: 0,
227
- width: 0,
228
- height: 0
229
- });
230
- this.editBg = g, shadowRoot.add(this.editLine), shadowRoot.add(this.editBg);
231
- }
232
- const data = this.computedCursorPosByEvent(e, cache);
233
- if (data) {
234
- const {x: x, y1: y1, y2: y2, cursorIndex: cursorIndex} = data;
235
- this.startCursorPos = {
236
- x: x,
237
- y: (y1 + y2) / 2
238
- }, this.curCursorIdx = cursorIndex, this.selectionStartCursorIdx = cursorIndex,
239
- this.setCursorAndTextArea(x, y1, y2, target);
301
+ if (!target || "richtext" !== target.type) return;
302
+ this.currRt = target, RichTextEditPlugin.tryUpdateRichtext(target);
303
+ const shadowRoot = this.getShadow(target), cache = target.getFrameCache();
304
+ if (cache) {
305
+ if (this.computeGlobalDelta(cache), shadowRoot.setAttributes({
306
+ shadowRootIdx: 1,
307
+ pickable: !1,
308
+ x: this.deltaX,
309
+ y: this.deltaY
310
+ }), !this.editLine) {
311
+ const line = createLine({
312
+ x: 0,
313
+ y: 0,
314
+ lineWidth: 1,
315
+ stroke: "black"
316
+ });
317
+ this.addAnimateToLine(line), this.editLine = line, this.ticker.start(!0);
318
+ const g = createGroup({
319
+ x: 0,
320
+ y: 0,
321
+ width: 0,
322
+ height: 0
323
+ });
324
+ this.editBg = g, shadowRoot.add(this.editLine), shadowRoot.add(this.editBg);
325
+ }
326
+ if (data = data || this.computedCursorPosByEvent(e, cache)) {
327
+ const {x: x, y1: y1, y2: y2, cursorIndex: cursorIndex} = data;
328
+ this.startCursorPos = {
329
+ x: x,
330
+ y: (y1 + y2) / 2
331
+ }, this.curCursorIdx = cursorIndex, this.selectionStartCursorIdx = cursorIndex,
332
+ this.setCursorAndTextArea(x, y1, y2, target);
333
+ } else {
334
+ const x = 0, y1 = 0, y2 = getRichTextBounds(Object.assign(Object.assign({}, target.attribute), {
335
+ textConfig: [ {
336
+ text: "a"
337
+ } ]
338
+ })).height();
339
+ this.startCursorPos = {
340
+ x: x,
341
+ y: (y1 + y2) / 2
342
+ }, this.curCursorIdx = -.1, this.selectionStartCursorIdx = -.1, this.setCursorAndTextArea(x, y1, y2, target);
343
+ }
344
+ this.tryShowShadowPlaceholder(), this.tryShowInputBounds(), this.currRt.addUpdateBoundTag();
240
345
  }
241
346
  }
242
- deFocus() {
243
- const target = this.currRt;
244
- target && (target.detachShadow(), this.currRt = null, this.editLine && (this.editLine.parent.removeChild(this.editLine),
245
- this.editLine.release(), this.editLine = null, this.editBg.parent.removeChild(this.editBg),
246
- this.editBg.release(), this.editBg = null));
347
+ offsetLineBgAndShadowBounds() {
348
+ const rt = this.currRt, {textBaseline: textBaseline} = rt.attribute;
349
+ let b, dy = 0, attr = rt.attribute;
350
+ "middle" !== textBaseline && "bottom" !== textBaseline || (attr.textConfig.length || (attr = Object.assign(Object.assign({}, attr), {
351
+ textConfig: [ {
352
+ text: "a"
353
+ } ]
354
+ })), b = getRichTextBounds(attr)), "middle" === textBaseline ? dy = -b.height() / 2 : "bottom" === textBaseline && (dy = -b.height()),
355
+ this.editLine && this.editLine.setAttributes({
356
+ dy: dy
357
+ }), this.editBg && this.editBg.setAttributes({
358
+ dy: dy
359
+ }), this.shadowBounds && this.shadowBounds.setAttributes({
360
+ dy: dy
361
+ });
362
+ }
363
+ deFocus(trulyDeFocus = !1) {
364
+ const currRt = this.currRt;
365
+ if (!currRt) return;
366
+ this.updateCbs && this.updateCbs.forEach((cb => cb("beforeDefocus", this, {
367
+ trulyDeFocus: trulyDeFocus
368
+ }))), trulyDeFocus && (this.trySyncPlaceholderToTextConfig(), currRt.detachShadow()),
369
+ this.currRt = null, this.editLine && (this.editLine.parent && this.editLine.parent.removeChild(this.editLine),
370
+ this.editLine.release(), this.editLine = null, this.editBg.parent && this.editBg.parent.removeChild(this.editBg),
371
+ this.editBg.release(), this.editBg = null), trulyDeFocus && (this.shadowBounds && (this.shadowBounds.parent && this.shadowBounds.parent.removeChild(this.shadowBounds),
372
+ this.shadowBounds.release(), this.shadowBounds = null), this.shadowPlaceHolder && (this.shadowPlaceHolder.parent && this.shadowPlaceHolder.parent.removeChild(this.shadowPlaceHolder),
373
+ this.shadowPlaceHolder.release(), this.shadowPlaceHolder = null)), this.focusing = !1;
374
+ const textConfig = currRt.attribute.textConfig;
375
+ let lastConfig = textConfig[textConfig.length - 1], cleared = !1;
376
+ for (;lastConfig && "\n" === lastConfig.text; ) textConfig.pop(), lastConfig = textConfig[textConfig.length - 1],
377
+ cleared = !0;
378
+ cleared && currRt.setAttributes({
379
+ textConfig: textConfig
380
+ }), currRt.removeEventListener("pointerleave", this.handleLeave);
247
381
  }
248
382
  addAnimateToLine(line) {
249
- line.animates && line.animates.forEach((animate => {
383
+ line.setAttributes({
384
+ opacity: 1
385
+ }), line.animates && line.animates.forEach((animate => {
250
386
  animate.stop(), animate.release();
251
387
  }));
252
- const animate = line.animate();
253
- animate.setTimeline(this.timeline), animate.to({
388
+ line.animate({
389
+ timeline: this.timeline
390
+ }).to({
254
391
  opacity: 1
255
392
  }, 10, "linear").wait(700).to({
256
393
  opacity: 0
@@ -283,67 +420,75 @@ export class RichTextEditPlugin {
283
420
  x: currCursorData.x,
284
421
  y: (currCursorData.y1 + currCursorData.y2) / 2
285
422
  }, line0Info = this.getLineByPoint(cache, startCursorPos), line1Info = this.getLineByPoint(cache, endCursorPos);
286
- if ((startCursorPos.y > endCursorPos.y || startCursorPos.y === endCursorPos.y && startCursorPos.x > endCursorPos.x) && ([startCursorPos, endCursorPos] = [ endCursorPos, startCursorPos ],
287
- [line1Info, line0Info] = [ line0Info, line1Info ]), this.hideSelection(), line0Info === line1Info) this.editBg.setAttributes({
288
- x: startCursorPos.x,
289
- y: line0Info.top,
290
- width: endCursorPos.x - startCursorPos.x,
291
- height: line0Info.height,
292
- fill: "#336df4",
293
- fillOpacity: .2
294
- }); else {
295
- this.editBg.setAttributes({
296
- x: 0,
423
+ if (line0Info && line1Info) {
424
+ if ((startCursorPos.y > endCursorPos.y || startCursorPos.y === endCursorPos.y && startCursorPos.x > endCursorPos.x) && ([startCursorPos, endCursorPos] = [ endCursorPos, startCursorPos ],
425
+ [line1Info, line0Info] = [ line0Info, line1Info ]), this.hideSelection(), line0Info === line1Info) this.editBg.setAttributes({
426
+ x: startCursorPos.x,
297
427
  y: line0Info.top,
298
- width: 0,
299
- height: 0
300
- });
301
- const startIdx = cache.lines.findIndex((item => item === line0Info)), endIdx = cache.lines.findIndex((item => item === line1Info));
302
- let y = 0;
303
- for (let i = startIdx; i <= endIdx; i++) {
304
- const line = cache.lines[i];
305
- if (i === startIdx) {
306
- const p = line.paragraphs[line.paragraphs.length - 1];
307
- this.editBg.add(createRect({
308
- x: startCursorPos.x,
309
- y: y,
310
- width: p.left + p.width - startCursorPos.x,
311
- height: line.height,
312
- fill: "#336df4",
313
- fillOpacity: .2
314
- }));
315
- } else if (i === endIdx) {
316
- const p = line.paragraphs[0];
317
- this.editBg.add(createRect({
318
- x: p.left,
319
- y: y,
320
- width: endCursorPos.x - p.left,
321
- height: line.height,
322
- fill: "#336df4",
323
- fillOpacity: .2
324
- }));
325
- } else {
326
- const p0 = line.paragraphs[0], p1 = line.paragraphs[line.paragraphs.length - 1];
327
- this.editBg.add(createRect({
328
- x: p0.left,
329
- y: y,
330
- width: p1.left + p1.width - p0.left,
331
- height: line.height,
332
- fill: "#336df4",
333
- fillOpacity: .2
334
- }));
428
+ width: endCursorPos.x - startCursorPos.x,
429
+ height: line0Info.height,
430
+ fill: "#336df4",
431
+ fillOpacity: .2
432
+ }); else {
433
+ this.editBg.setAttributes({
434
+ x: 0,
435
+ y: line0Info.top,
436
+ width: 0,
437
+ height: 0
438
+ });
439
+ const startIdx = cache.lines.findIndex((item => item === line0Info)), endIdx = cache.lines.findIndex((item => item === line1Info));
440
+ let y = 0;
441
+ for (let i = startIdx; i <= endIdx; i++) {
442
+ const line = cache.lines[i];
443
+ if (i === startIdx) {
444
+ const p = line.paragraphs[line.paragraphs.length - 1];
445
+ this.editBg.add(createRect({
446
+ x: startCursorPos.x,
447
+ y: y,
448
+ width: p.left + p.width - startCursorPos.x,
449
+ height: line.height,
450
+ fill: "#336df4",
451
+ fillOpacity: .2
452
+ }));
453
+ } else if (i === endIdx) {
454
+ const p = line.paragraphs[0];
455
+ this.editBg.add(createRect({
456
+ x: p.left,
457
+ y: y,
458
+ width: endCursorPos.x - p.left,
459
+ height: line.height,
460
+ fill: "#336df4",
461
+ fillOpacity: .2
462
+ }));
463
+ } else {
464
+ const p0 = line.paragraphs[0], p1 = line.paragraphs[line.paragraphs.length - 1];
465
+ this.editBg.add(createRect({
466
+ x: p0.left,
467
+ y: y,
468
+ width: p1.left + p1.width - p0.left,
469
+ height: line.height,
470
+ fill: "#336df4",
471
+ fillOpacity: .2
472
+ }));
473
+ }
474
+ y += line.height;
335
475
  }
336
- y += line.height;
337
476
  }
477
+ this.setCursorAndTextArea(currCursorData.x, currCursorData.y1, currCursorData.y2, this.currRt),
478
+ this.triggerRender(), this.updateCbs.forEach((cb => cb("selection", this)));
338
479
  }
339
- this.setCursorAndTextArea(currCursorData.x, currCursorData.y1 + 2, currCursorData.y2 - 2, this.currRt),
340
- this.triggerRender(), this.updateCbs.forEach((cb => cb("selection", this)));
341
480
  }
342
481
  hideSelection() {
343
482
  this.editBg && (this.editBg.removeAllChild(), this.editBg.setAttributes({
344
483
  fill: "transparent"
345
484
  }));
346
485
  }
486
+ getShadow(rt) {
487
+ const sr = rt.shadowRoot || rt.attachShadow();
488
+ return sr.setAttributes({
489
+ boundsMode: "empty"
490
+ }), sr;
491
+ }
347
492
  getLineByPoint(cache, p1) {
348
493
  let lineInfo = cache.lines[0];
349
494
  for (let i = 0; i < cache.lines.length && !(lineInfo.top <= p1.y && lineInfo.top + lineInfo.height >= p1.y); i++) lineInfo = cache.lines[i + 1];
@@ -375,7 +520,10 @@ export class RichTextEditPlugin {
375
520
  return -1;
376
521
  }
377
522
  isRichtext(e) {
378
- return !(!e.target || "richtext" !== e.target.type || !e.target.attribute.editable);
523
+ return !(!e.target || "richtext" !== e.target.type);
524
+ }
525
+ isEditableRichtext(e) {
526
+ return this.isRichtext(e) && !!e.target.attribute.editable;
379
527
  }
380
528
  triggerRender() {
381
529
  this.pluginService.stage.renderNextFrame();
@@ -391,8 +539,15 @@ export class RichTextEditPlugin {
391
539
  x: 0,
392
540
  y: 0
393
541
  };
394
- return e.target.globalTransMatrix.transformPoint(p, p1), p1.x -= this.deltaX, p1.y -= this.deltaY,
395
- p1;
542
+ e.target.globalTransMatrix.transformPoint(p, p1), p1.x -= this.deltaX, p1.y -= this.deltaY;
543
+ const rt = this.currRt, {textBaseline: textBaseline} = rt.attribute;
544
+ let dy = 0;
545
+ if ("middle" === textBaseline) {
546
+ dy = getRichTextBounds(rt.attribute).height() / 2;
547
+ } else if ("bottom" === textBaseline) {
548
+ dy = getRichTextBounds(rt.attribute).height();
549
+ }
550
+ return p1.y += dy, p1;
396
551
  }
397
552
  setCursorAndTextArea(x, y1, y2, rt) {
398
553
  this.editLine.setAttributes({
@@ -413,15 +568,14 @@ export class RichTextEditPlugin {
413
568
  y: y1
414
569
  }, out);
415
570
  const {left: left, top: top} = this.pluginService.stage.window.getBoundingClientRect();
416
- out.x += left, out.y += top, this.editModule.moveTo(out.x, out.y, rt, this.curCursorIdx, this.selectionStartCursorIdx);
571
+ out.x += left, out.y += top, this.offsetLineBgAndShadowBounds(), this.editModule.moveTo(out.x, out.y, rt, this.curCursorIdx, this.selectionStartCursorIdx);
417
572
  }
418
573
  computedCursorPosByEvent(e, cache) {
419
574
  const p1 = this.getEventPosition(e), lineInfo = this.getLineByPoint(cache, p1);
420
575
  if (!lineInfo) return;
421
576
  const {columnInfo: columnInfo, delta: delta} = this.getColumnAndIndexByLinePoint(lineInfo, p1);
422
577
  if (!columnInfo) return;
423
- let y1 = lineInfo.top, y2 = lineInfo.top + lineInfo.height;
424
- y1 += 2, y2 -= 2;
578
+ const y1 = lineInfo.top, y2 = lineInfo.top + lineInfo.height;
425
579
  let cursorIndex = this.getColumnIndex(cache, columnInfo);
426
580
  cursorIndex += delta;
427
581
  return {
@@ -436,17 +590,31 @@ export class RichTextEditPlugin {
436
590
  computedCursorPosByCursorIdx(cursorIdx, rt) {
437
591
  var _a, _b, _c;
438
592
  const idx = Math.round(cursorIdx), leftRight = cursorIdx - idx, cache = rt.getFrameCache(), column = this.getColumnByIndex(cache, idx), height = null !== (_a = rt.attribute.fontSize) && void 0 !== _a ? _a : null === (_c = null === (_b = rt.attribute.textConfig) || void 0 === _b ? void 0 : _b[0]) || void 0 === _c ? void 0 : _c.fontSize;
439
- if (!column) return {
440
- x: 0,
441
- y1: 0,
442
- y2: height
443
- };
444
- const {lineInfo: lineInfo, columnInfo: columnInfo} = column;
445
- let y1 = lineInfo.top, y2 = lineInfo.top + lineInfo.height;
446
- return y1 += 2, y2 -= 2, {
593
+ if (!column) {
594
+ if (!cache.lines.length) {
595
+ return {
596
+ x: 0,
597
+ y1: 0,
598
+ y2: getRichTextBounds(Object.assign(Object.assign({}, rt.attribute), {
599
+ textConfig: [ {
600
+ text: "a"
601
+ } ]
602
+ })).height()
603
+ };
604
+ }
605
+ return {
606
+ x: 0,
607
+ y1: 0,
608
+ y2: height
609
+ };
610
+ }
611
+ const {lineInfo: lineInfo, columnInfo: columnInfo} = column, y1 = lineInfo.top, y2 = lineInfo.top + lineInfo.height;
612
+ return {
447
613
  x: columnInfo.left + (leftRight < 0 ? 0 : columnInfo.width),
448
614
  y1: y1,
449
- y2: y2
615
+ y2: y2,
616
+ lineInfo: lineInfo,
617
+ columnInfo: columnInfo
450
618
  };
451
619
  }
452
620
  getColumnByIndex(cache, index) {
@@ -469,5 +637,29 @@ export class RichTextEditPlugin {
469
637
  getSelection(defaultAll = !1) {
470
638
  return this.currRt ? null != this.selectionStartCursorIdx && null != this.curCursorIdx ? new Selection(this.selectionStartCursorIdx, this.curCursorIdx, this.currRt) : defaultAll ? RichTextEditPlugin.CreateSelection(this.currRt) : null : null;
471
639
  }
640
+ forceFocus(params) {
641
+ const {target: target, e: e, cursorIndex: cursorIndex} = params;
642
+ target && (this.currRt = target, e ? this._forceFocusByEvent(e) : this._forceFocusByCursorIndex(null != cursorIndex ? cursorIndex : -.1));
643
+ }
644
+ _forceFocusByEvent(e) {
645
+ this.handleEnter(), this.handlePointerDown(e), this.handlePointerUp(e);
646
+ }
647
+ _forceFocusByCursorIndex(cursorIndex) {
648
+ const richtext = this.currRt;
649
+ if (!richtext) return;
650
+ let x = 0, y1 = 0, y2 = 2, lineInfo = null, columnInfo = null;
651
+ const data = this.computedCursorPosByCursorIdx(cursorIndex, richtext);
652
+ x = data.x, y1 = data.y1, y2 = data.y2, lineInfo = data.lineInfo, columnInfo = data.columnInfo,
653
+ this.onFocus({
654
+ target: this.currRt
655
+ }, {
656
+ x: x,
657
+ y1: y1,
658
+ y2: y2,
659
+ cursorIndex: cursorIndex,
660
+ lineInfo: lineInfo,
661
+ columnInfo: columnInfo
662
+ });
663
+ }
472
664
  }
473
665
  //# sourceMappingURL=richtext-edit-plugin.js.map