@logicflow/extension 2.1.5 → 2.1.7

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.
@@ -18,6 +18,7 @@ export class SelectionSelect {
18
18
  private disabled = true
19
19
  private isWholeNode = true
20
20
  private isWholeEdge = true
21
+ private originStatusSaved = false
21
22
  exclusiveMode = false // 框选独占模式:true 表示只能进行框选操作,false 表示可以同时进行其他画布操作
22
23
  // 用于区分选区和点击事件
23
24
  private mouseDownInfo: {
@@ -97,7 +98,6 @@ export class SelectionSelect {
97
98
 
98
99
  private addEventListeners() {
99
100
  if (!this.container) return
100
-
101
101
  if (this.exclusiveMode) {
102
102
  // 独占模式:监听 container 的 mousedown 事件
103
103
  this.container.style.pointerEvents = 'auto'
@@ -143,9 +143,12 @@ export class SelectionSelect {
143
143
  y: e.clientY,
144
144
  time: Date.now(),
145
145
  }
146
-
147
146
  // 记录原始设置并临时禁止画布移动
148
- this.originalStopMoveGraph = this.lf.getEditConfig().stopMoveGraph!
147
+ if (!this.originStatusSaved) {
148
+ // 为了防止在开启框选时用户多次点击画布导致缓存的stopMoveGraph变化,所以只在第一次点击时记录原始的stopMoveGraph issue #2263
149
+ this.originalStopMoveGraph = this.lf.getEditConfig().stopMoveGraph!
150
+ this.originStatusSaved = true
151
+ }
149
152
  this.lf.updateEditConfig({
150
153
  stopMoveGraph: true,
151
154
  })
@@ -249,6 +252,11 @@ export class SelectionSelect {
249
252
  }
250
253
  }
251
254
  private drawOff = (e: MouseEvent) => {
255
+ // 恢复原始的 stopMoveGraph 设置
256
+ this.lf.updateEditConfig({
257
+ stopMoveGraph: this.originalStopMoveGraph,
258
+ })
259
+ this.originStatusSaved = false
252
260
  // 处理鼠标抬起事件
253
261
  // 首先判断是否是点击,如果是,则清空框选
254
262
  if (this.mouseDownInfo) {
@@ -271,11 +279,6 @@ export class SelectionSelect {
271
279
  document.removeEventListener('mouseup', this.drawOff)
272
280
  }
273
281
 
274
- // 恢复原始的 stopMoveGraph 设置
275
- this.lf.updateEditConfig({
276
- stopMoveGraph: this.originalStopMoveGraph,
277
- })
278
-
279
282
  if (curStartPoint && curEndPoint) {
280
283
  const { x, y } = curStartPoint
281
284
  const { x: x1, y: y1 } = curEndPoint
@@ -4,7 +4,11 @@ import { forEach, merge } from 'lodash-es'
4
4
  import LabelPlugin from '.'
5
5
  import Label from './Label'
6
6
  import LabelModel from './LabelModel'
7
- import { MediumEditor, defaultOptions, ColorPickerButton } from './mediumEditor'
7
+ import {
8
+ MediumEditor,
9
+ defaultOptions,
10
+ createColorPickerButtonClass,
11
+ } from './mediumEditor'
8
12
 
9
13
  import LabelConfig = LogicFlow.LabelConfig
10
14
 
@@ -47,7 +51,7 @@ export class LabelOverlay extends Component<IToolProps, ILabelOverlayState> {
47
51
  merge(defaultOptions, {
48
52
  autoLink: true,
49
53
  extensions: {
50
- colorPicker: new ColorPickerButton(),
54
+ colorPicker: new (createColorPickerButtonClass(MediumEditor))(),
51
55
  },
52
56
  }),
53
57
  )
@@ -82,7 +86,7 @@ export class LabelOverlay extends Component<IToolProps, ILabelOverlayState> {
82
86
  merge(defaultOptions, {
83
87
  autoLink: true,
84
88
  extensions: {
85
- colorPicker: new ColorPickerButton(),
89
+ colorPicker: new (createColorPickerButtonClass(MediumEditor))(),
86
90
  },
87
91
  }),
88
92
  )
@@ -39,56 +39,83 @@ export const defaultOptions = {
39
39
  disableEditing: true,
40
40
  }
41
41
 
42
- export const ColorPickerButton = MediumEditor.extensions.button.extend({
43
- name: 'colorpicker',
44
- tagNames: ['mark'],
45
- contentDefault: '<b>Color</b>',
46
- aria: 'Color Picker',
47
- action: 'colorPicker',
48
- init: function () {
49
- rangy.init()
50
- MediumEditor.extensions.button.prototype.init.call(this)
51
- this.colorPicker = new Picker({
52
- parent: this.button,
53
- color: '#000',
54
- onDone: (res) => {
55
- if (this.coloredText && this.coloredText.isAppliedToSelection()) {
56
- this.coloredText.undoToSelection()
57
- }
58
- this.coloredText = rangy.createClassApplier('colored', {
59
- elementTagName: 'span',
60
- elementProperties: {
61
- style: {
62
- color: res.hex,
63
- },
64
- },
65
- normalize: true,
66
- })
67
- this.coloredText.toggleSelection()
68
- this.base.checkContentChanged()
69
- this.setInactive()
70
- },
71
- })
72
- },
73
- getButton: function () {
74
- return this.button
75
- },
76
- handleClick: function () {
77
- this.setActive()
78
- this.colorPicker.show()
79
- },
80
- isAlreadyApplied: function (node) {
81
- return node.nodeName.toLowerCase() === 'mark'
82
- },
83
- isActive: function () {
84
- return this.button.classList.contains('medium-editor-button-active')
85
- },
86
- setInactive: function () {
87
- this.button.classList.remove('medium-editor-button-active')
88
- },
89
- setActive: function () {
90
- this.button.classList.add('medium-editor-button-active')
91
- },
92
- })
42
+ export function createColorPickerButtonClass(MediumEditor?: any) {
43
+ const ButtonBase =
44
+ MediumEditor?.extensions?.button || MediumEditor?.extensions?.button
45
+ const ExtensionBase =
46
+ MediumEditor?.Extension || (MediumEditor as any)?.Extension
47
+
48
+ // Button 扩展基类不可用时,回退到 Extension 基类,避免在模块加载阶段抛错
49
+ const Base = ButtonBase || ExtensionBase
50
+ if (!Base) {
51
+ console.warn(
52
+ 'MediumEditor button/extension base not available; using noop extension',
53
+ )
54
+ return class {}
55
+ }
56
+
57
+ return Base.extend({
58
+ name: 'colorpicker',
59
+ tagNames: ['mark'],
60
+ contentDefault: '<b>Color</b>',
61
+ aria: 'Color Picker',
62
+ action: 'colorPicker',
63
+ init: function () {
64
+ try {
65
+ rangy.init()
66
+ } catch {
67
+ console.error('rangy.init failed')
68
+ }
69
+ // 初始化按钮(ButtonBase 才有 prototype.init)
70
+ try {
71
+ ;(ButtonBase as any)?.prototype?.init?.call(this)
72
+ } catch {
73
+ console.error('ButtonBase.init failed')
74
+ }
75
+ this.colorPicker = new Picker({
76
+ parent: (this as any).button || undefined,
77
+ color: '#000',
78
+ onDone: (res) => {
79
+ try {
80
+ if (this.coloredText && this.coloredText.isAppliedToSelection?.()) {
81
+ this.coloredText.undoToSelection()
82
+ }
83
+ this.coloredText = rangy.createClassApplier('colored', {
84
+ elementTagName: 'span',
85
+ elementProperties: { style: { color: res.hex } },
86
+ normalize: true,
87
+ })
88
+ this.coloredText.toggleSelection()
89
+ this.base?.checkContentChanged?.()
90
+ this.setInactive?.()
91
+ } catch {
92
+ console.error('Picker.onDone failed')
93
+ }
94
+ },
95
+ })
96
+ },
97
+ getButton: function () {
98
+ return (this as any).button
99
+ },
100
+ handleClick: function () {
101
+ this.setActive?.()
102
+ this.colorPicker?.show?.()
103
+ },
104
+ isAlreadyApplied: function (node) {
105
+ return node?.nodeName?.toLowerCase?.() === 'mark'
106
+ },
107
+ isActive: function () {
108
+ return (this as any).button?.classList?.contains(
109
+ 'medium-editor-button-active',
110
+ )
111
+ },
112
+ setInactive: function () {
113
+ ;(this as any).button?.classList?.remove('medium-editor-button-active')
114
+ },
115
+ setActive: function () {
116
+ ;(this as any).button?.classList?.add('medium-editor-button-active')
117
+ },
118
+ })
119
+ }
93
120
 
94
121
  export { MediumEditor }