@logicflow/extension 2.1.6 → 2.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/CHANGELOG.md +22 -0
  3. package/dist/index.min.js +1 -1
  4. package/dist/index.min.js.map +1 -1
  5. package/es/components/dnd-panel/index.js +6 -2
  6. package/es/components/mini-map/index.js +6 -6
  7. package/es/components/selection-select/index.js +18 -9
  8. package/es/insert-node-in-polyline/index.js +11 -35
  9. package/es/tools/label/Label.d.ts +2 -2
  10. package/es/tools/label/Label.js +1 -1
  11. package/es/tools/label/LabelOverlay.js +3 -3
  12. package/es/tools/label/mediumEditor.d.ts +1 -1
  13. package/es/tools/label/mediumEditor.js +89 -52
  14. package/es/tools/snapshot/index.js +26 -13
  15. package/lib/components/dnd-panel/index.js +6 -2
  16. package/lib/components/mini-map/index.js +6 -6
  17. package/lib/components/selection-select/index.js +18 -9
  18. package/lib/insert-node-in-polyline/index.js +10 -34
  19. package/lib/tools/label/Label.d.ts +2 -2
  20. package/lib/tools/label/Label.js +1 -1
  21. package/lib/tools/label/LabelOverlay.js +2 -2
  22. package/lib/tools/label/mediumEditor.d.ts +1 -1
  23. package/lib/tools/label/mediumEditor.js +91 -53
  24. package/lib/tools/snapshot/index.js +26 -13
  25. package/package.json +5 -5
  26. package/src/components/dnd-panel/index.ts +10 -2
  27. package/src/components/menu/index.ts +0 -1
  28. package/src/components/mini-map/index.ts +8 -8
  29. package/src/components/selection-select/index.ts +22 -14
  30. package/src/insert-node-in-polyline/index.ts +17 -11
  31. package/src/tools/label/Label.tsx +4 -4
  32. package/src/tools/label/LabelOverlay.tsx +7 -3
  33. package/src/tools/label/mediumEditor.ts +78 -51
  34. package/src/tools/snapshot/index.ts +12 -0
  35. package/stats.html +1 -1
@@ -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 }
@@ -646,6 +646,18 @@ export class Snapshot {
646
646
  const { fileType = baseFileType } = toImageOptions ?? {}
647
647
  const svg = this.getSvgRootElement(this.lf)
648
648
  await updateImageSource(svg as SVGElement)
649
+ if (fileType === 'svg') {
650
+ const copy = await this.cloneSvg(svg)
651
+ const svgString = new XMLSerializer().serializeToString(copy)
652
+ const blob = new Blob([svgString], {
653
+ type: 'image/svg+xml;charset=utf-8',
654
+ })
655
+ return {
656
+ data: blob,
657
+ width: 0,
658
+ height: 0,
659
+ }
660
+ }
649
661
  return new Promise((resolve) => {
650
662
  this.getCanvasData(svg, {
651
663
  backgroundColor,