@leafer-in/editor 1.0.0-rc.3 → 1.0.0-rc.30

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 (41) hide show
  1. package/dist/editor.cjs +1937 -0
  2. package/dist/editor.esm.js +1822 -422
  3. package/dist/editor.esm.min.js +1 -1
  4. package/dist/editor.js +1848 -428
  5. package/dist/editor.min.cjs +1 -0
  6. package/dist/editor.min.js +1 -1
  7. package/package.json +12 -9
  8. package/src/Editor.ts +396 -145
  9. package/src/config.ts +38 -0
  10. package/src/decorator/data.ts +16 -0
  11. package/src/display/EditBox.ts +342 -0
  12. package/src/display/EditMask.ts +37 -0
  13. package/src/display/EditPoint.ts +9 -0
  14. package/src/display/EditSelect.ts +255 -0
  15. package/src/display/SelectArea.ts +30 -0
  16. package/src/display/Stroker.ts +92 -0
  17. package/src/editor/cursor.ts +45 -0
  18. package/src/editor/simulate.ts +14 -0
  19. package/src/editor/target.ts +39 -0
  20. package/src/event/EditorEvent.ts +33 -0
  21. package/src/event/EditorGroupEvent.ts +23 -0
  22. package/src/event/EditorMoveEvent.ts +17 -0
  23. package/src/event/EditorRotateEvent.ts +4 -10
  24. package/src/event/EditorScaleEvent.ts +28 -0
  25. package/src/event/EditorSkewEvent.ts +18 -0
  26. package/src/event/InnerEditorEvent.ts +23 -0
  27. package/src/helper/EditDataHelper.ts +183 -0
  28. package/src/helper/EditSelectHelper.ts +34 -0
  29. package/src/helper/EditorHelper.ts +73 -0
  30. package/src/index.ts +50 -3
  31. package/src/svg.ts +54 -0
  32. package/src/tool/EditTool.ts +99 -0
  33. package/src/tool/EditToolCreator.ts +32 -0
  34. package/src/tool/InnerEditor.ts +68 -0
  35. package/src/tool/LineEditTool.ts +135 -0
  36. package/types/index.d.ts +293 -45
  37. package/src/cursor.ts +0 -57
  38. package/src/event/EditorResizeEvent.ts +0 -34
  39. package/src/resize.ts +0 -87
  40. package/src/tool/LineTool.ts +0 -88
  41. package/src/tool/RectTool.ts +0 -139
package/src/Editor.ts CHANGED
@@ -1,232 +1,483 @@
1
- import { IGroupInputData, IPolygon, IUI, IEventListenerId } from '@leafer-ui/interface'
2
- import { IEditor, IEditorConfig, IEditorTool, IDirection8 } from '@leafer-in/interface'
1
+ import { IGroupInputData, IUI, IEventListenerId, IPointData, ILeafList, IEditSize, IGroup, IObject, IAlign } from '@leafer-ui/interface'
2
+ import { Group, Rect, DataHelper, MathHelper, LeafList, Matrix, RenderEvent, LeafHelper } from '@leafer-ui/draw'
3
+ import { DragEvent, RotateEvent, KeyEvent, ZoomEvent } from '@leafer-ui/core'
3
4
 
4
- import { Group, Rect, Polygon, DragEvent, PointHelper, PointerEvent, KeyEvent, RotateEvent, DataHelper, MathHelper, RenderEvent } from '@leafer-ui/core'
5
+ import { IEditBox, IEditPoint, IEditor, IEditorConfig, IEditTool, IEditorScaleEvent, IInnerEditor } from '@leafer-in/interface'
5
6
 
6
- import { getResizeData } from './resize'
7
- import { updateCursor } from './cursor'
7
+ import { EditorMoveEvent } from './event/EditorMoveEvent'
8
+ import { EditorScaleEvent } from './event/EditorScaleEvent'
9
+ import { EditorRotateEvent } from './event/EditorRotateEvent'
10
+ import { EditorSkewEvent } from './event/EditorSkewEvent'
8
11
 
9
- import { LineTool } from './tool/LineTool'
10
- import { RectTool } from './tool/RectTool'
12
+ import { EditSelect } from './display/EditSelect'
13
+ import { EditBox } from './display/EditBox'
14
+ import { EditMask } from './display/EditMask'
11
15
 
12
- import { EditorResizeEvent } from './event/EditorResizeEvent'
13
- import { EditorRotateEvent } from './event/EditorRotateEvent'
16
+ import { config } from './config'
17
+
18
+ import { onTarget, onHover } from './editor/target'
19
+ import { targetAttr } from './decorator/data'
20
+ import { EditorHelper } from './helper/EditorHelper'
21
+ import { EditDataHelper } from './helper/EditDataHelper'
22
+ import { simulate } from './editor/simulate'
23
+ import { updateCursor } from './editor/cursor'
24
+ import { EditToolCreator } from './tool/EditToolCreator'
25
+ import { InnerEditorEvent } from './event/InnerEditorEvent'
26
+ import { EditorGroupEvent } from './event/EditorGroupEvent'
14
27
 
15
28
 
16
29
  export class Editor extends Group implements IEditor {
17
30
 
18
- public config: IEditorConfig = {
19
- type: 'pc',
20
- stroke: '#836DFF',
21
- pointFill: '#FFFFFF',
22
- pointSize: 10,
23
- pointRadius: 10,
24
- rotateGap: 90,
25
- hideOnMove: false,
26
- moveCursor: 'move',
27
- resizeType: 'auto',
28
- resizeCursor: ['nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize', 'nwse-resize', 'ns-resize', 'nesw-resize', 'ew-resize'],
29
- rotateCursor: ['ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize', 'n-resize'],
30
- resizeable: true,
31
- rotateable: true
31
+ public config = config
32
+
33
+ public get mergeConfig(): IEditorConfig {
34
+ const { element, config } = this
35
+ return this.single && element.editConfig ? { ...config, ...element.editConfig } : config // 实时合并,后期可优化
32
36
  }
33
37
 
34
- public resizePoints: IUI[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
35
- public rotatePoints: IUI[] = [] // topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left
36
- public resizeLines: IUI[] = [] // top, right, bottom, left
38
+ @targetAttr(onHover)
39
+ public hoverTarget?: IUI
37
40
 
38
- public targetRect: IUI = new Rect({ hitFill: 'all', hitRadius: 5 })
39
- public rect: IPolygon = new Polygon({ hittable: false, strokeAlign: 'center' })
40
- public circle: IUI = new Rect({ around: 'center', hitRadius: 10 }) // rotate point
41
+ @targetAttr(onTarget)
42
+ public target?: IUI | IUI[]
41
43
 
42
- public tool: IEditorTool
44
+ // 列表
43
45
 
44
- private _target: IUI
45
- public get target(): IUI { return this._target }
46
- public set target(value: IUI) {
47
- this.__removeTargetEvents()
48
- this.visible = !!value
46
+ public get list(): IUI[] { return this.leafList.list as IUI[] }
47
+ public leafList: ILeafList = new LeafList() // from target
48
+ public openedGroupList: ILeafList = new LeafList()
49
49
 
50
- this._target = value
51
- if (value) this.onTarget()
52
- }
50
+ // 状态
51
+
52
+ public get editing(): boolean { return !!this.list.length }
53
+ public innerEditing: boolean
54
+ public get groupOpening(): boolean { return !!this.openedGroupList.length }
55
+
56
+ public get multiple(): boolean { return this.list.length > 1 }
57
+ public get single(): boolean { return this.list.length === 1 }
58
+
59
+ public get dragging(): boolean { return this.editBox.dragging }
60
+
61
+ // 组件
62
+
63
+ public get element() { return this.multiple ? this.simulateTarget : this.list[0] as IUI }
64
+ public simulateTarget: IUI = new Rect({ visible: false })
65
+
66
+ public editBox: IEditBox = new EditBox(this)
67
+ public get buttons() { return this.editBox.buttons }
68
+
69
+ public editTool?: IEditTool
70
+
71
+ public innerEditor?: IInnerEditor
72
+ public editToolList: IObject = {}
73
+
74
+ public selector: EditSelect = new EditSelect(this)
75
+ public editMask: EditMask = new EditMask(this)
76
+
77
+ public dragStartPoint: IPointData
53
78
 
54
- public enterPoint: IUI
79
+ public targetEventIds: IEventListenerId[] = []
55
80
 
56
- protected __eventIds: IEventListenerId[] = []
57
- protected __targetEventIds: IEventListenerId[] = []
58
81
 
59
82
  constructor(userConfig?: IEditorConfig, data?: IGroupInputData) {
60
83
  super(data)
61
84
  if (userConfig) this.config = DataHelper.default(userConfig, this.config)
62
- this.init()
85
+ this.addMany(this.editMask, this.selector, this.editBox)
63
86
  }
64
87
 
65
- protected init() {
66
- let rotatePoint: IUI, resizeLine: IUI, resizePoint: IUI
67
- const { resizePoints, rotatePoints, resizeLines } = this
88
+ // select
68
89
 
69
- for (let i = 0; i < 8; i++) {
70
- rotatePoint = new Rect({ around: 'center', width: 30, height: 30, hitRadius: 10, hitFill: "all" })
71
- rotatePoints.push(rotatePoint)
72
- this.__listenPointEvents(rotatePoint, 'rotate', i)
73
-
74
- if (i % 2) {
75
- resizeLine = new Rect({ around: 'center', width: 10, height: 10, hitFill: "all" })
76
- resizeLines.push(resizeLine)
77
- this.__listenPointEvents(resizeLine, 'resize', i)
78
- }
90
+ public select(target: IUI | IUI[]): void {
91
+ this.target = target
92
+ }
79
93
 
80
- resizePoint = new Rect({ around: 'center', hitRadius: 5 })
81
- resizePoints.push(resizePoint)
82
- this.__listenPointEvents(resizePoint, 'resize', i)
83
- }
94
+ public cancel(): void {
95
+ this.target = null
96
+ }
84
97
 
85
- this.__listenPointEvents(this.circle, 'rotate', 1)
86
- this.addMany(...rotatePoints, this.targetRect, this.rect, this.circle, ...resizeLines, ...resizePoints)
98
+ // item
87
99
 
88
- this.__listenEvents()
100
+ public hasItem(item: IUI): boolean {
101
+ return this.leafList.has(item)
89
102
  }
90
103
 
104
+ public addItem(item: IUI): void {
105
+ if (!this.hasItem(item) && !item.locked) this.leafList.add(item), this.target = this.leafList.list as IUI[]
106
+ }
91
107
 
92
- protected onTarget(): void {
93
- this.tool = this.getTool(this.target)
94
- this.waitLeafer(() => {
95
- this.update()
96
- this.updateMoveCursor()
97
- this.__listenTargetEvents()
98
- })
108
+ public removeItem(item: IUI): void {
109
+ if (this.hasItem(item)) this.leafList.remove(item), this.target = this.leafList.list as IUI[]
99
110
  }
100
111
 
101
- public getTool(value: IUI): IEditorTool {
102
- return (value.tag === 'Line' && value.resizeable) ? LineTool : RectTool
112
+ public shiftItem(item: IUI): void {
113
+ this.hasItem(item) ? this.removeItem(item) : this.addItem(item)
103
114
  }
104
115
 
116
+ // update
117
+
105
118
  public update(): void {
106
- if (!this.target) return
107
- this.tool.update(this)
119
+ if (this.editing) {
120
+ if (this.innerEditing) this.innerEditor.update()
121
+ this.editTool.update()
122
+ this.selector.update()
123
+ }
108
124
  }
109
125
 
126
+ public updateEditBox(): void {
127
+ if (this.multiple) simulate(this)
128
+ this.update()
129
+ }
110
130
 
111
- protected onDrag(e: DragEvent): void {
112
- const { resizeable, rotateable } = this.config
113
- if (e.metaKey || e.ctrlKey || !resizeable) {
114
- if (rotateable) this.onRotate(e)
115
- } else {
116
- this.onResize(e)
131
+ public updateEditTool(): void {
132
+ const tool = this.editTool
133
+ if (tool) {
134
+ this.editBox.unload()
135
+ tool.unload()
136
+ this.editTool = null
137
+ }
138
+
139
+ if (this.editing) {
140
+ const tag = this.single ? this.list[0].editOuter as string : 'EditTool'
141
+ this.editTool = this.editToolList[tag] = this.editToolList[tag] || EditToolCreator.get(tag, this)
142
+ this.editBox.load()
143
+ this.editTool.load()
117
144
  }
118
145
  }
119
146
 
120
- protected onMove(e: DragEvent): void {
121
- const { target } = this
122
- const { x, y } = e.getLocalMove(target)
147
+
148
+ // get
149
+
150
+ public getEditSize(_ui: IUI): IEditSize {
151
+ return this.mergeConfig.editSize
152
+ }
153
+
154
+ // operate
155
+
156
+ public onMove(e: DragEvent): void {
157
+ const total = { x: e.totalX, y: e.totalY }
158
+
123
159
  if (e.shiftKey) {
124
- if (Math.abs(x) > Math.abs(y)) {
125
- target.x += x
126
- } else {
127
- target.y += y
160
+ if (Math.abs(total.x) > Math.abs(total.y)) total.y = 0
161
+ else total.x = 0
162
+ }
163
+
164
+ this.move(DragEvent.getValidMove(this.element, this.dragStartPoint, total))
165
+ }
166
+
167
+ public onScale(e: DragEvent | ZoomEvent): void {
168
+ const { element } = this
169
+
170
+ if (e instanceof ZoomEvent) {
171
+ if (this.mergeConfig.resizeable === 'zoom') {
172
+ e.stop()
173
+ this.scaleOf(element.getInnerPoint(e), e.scale, e.scale)
128
174
  }
129
175
  } else {
130
- target.x += x
131
- target.y += y
176
+
177
+ const { direction } = e.current as IEditPoint
178
+ let { around, lockRatio } = this.mergeConfig
179
+ if (e.shiftKey || element.lockRatio) lockRatio = true
180
+
181
+ const data = EditDataHelper.getScaleData(element.boxBounds, direction, e.getInnerMove(element), lockRatio, EditDataHelper.getAround(around, e.altKey))
182
+
183
+ if (this.editTool.onScaleWithDrag) {
184
+ data.drag = e
185
+ this.scaleWithDrag(data)
186
+ } else {
187
+ this.scaleOf(data.origin, data.scaleX, data.scaleY)
188
+ }
189
+
132
190
  }
191
+
133
192
  }
134
193
 
135
- protected onRotate(e: DragEvent | RotateEvent): void {
136
- const { target } = this
137
- const { rotateGap } = this.config
138
- const { x, y, width, height } = target.boxBounds
139
- const origin = { x: x + width / 2, y: y + height / 2 }
194
+ public onRotate(e: DragEvent | RotateEvent): void {
195
+ const { skewable, around, rotateGap } = this.mergeConfig
196
+ const { direction, name } = e.current as IEditPoint
197
+ if (skewable && name === 'resize-line') return this.onSkew(e as DragEvent)
140
198
 
141
- let rotation: number
199
+ const { element } = this
200
+ let origin: IPointData, rotation: number
142
201
 
143
202
  if (e instanceof RotateEvent) {
144
- rotation = e.rotation
203
+ if (this.mergeConfig.rotateable === 'rotate') {
204
+ e.stop()
205
+ rotation = e.rotation, origin = element.getInnerPoint(e)
206
+ } else return
145
207
  } else {
146
- const point = e
147
- const last = { x: point.x - e.moveX, y: point.y - e.moveY }
148
- rotation = PointHelper.getChangeAngle(last, target.getWorldPoint(origin), point)
208
+ const last = { x: e.x - e.moveX, y: e.y - e.moveY }
209
+ const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (around || 'center'))
210
+ rotation = data.rotation
211
+ origin = data.origin
149
212
  }
150
213
 
151
- rotation = MathHelper.getGapRotation(target.rotation + rotation, rotateGap) - target.rotation
214
+ rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation)
215
+ if (!rotation) return
216
+
217
+ if (element.scaleX * element.scaleY < 0) rotation = -rotation // flippedOne
218
+
219
+ this.rotateOf(origin, MathHelper.float(rotation, 2))
220
+ }
221
+
222
+
223
+ public onSkew(e: DragEvent): void {
224
+ const { element } = this
225
+ const { around } = this.mergeConfig
152
226
 
153
- const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { editor: this, target, origin, rotation })
227
+ const { origin, skewX, skewY } = EditDataHelper.getSkewData(element.boxBounds, (e.current as IEditPoint).direction, e.getInnerMove(element), EditDataHelper.getAround(around, e.altKey))
228
+ if (!skewX && !skewY) return
154
229
 
155
- this.tool.rotate(event)
156
- target.emitEvent(event)
230
+ this.skewOf(origin, skewX, skewY)
157
231
  }
158
232
 
159
- public onResize(e: DragEvent): void {
160
- const { target } = this
161
- const { __direction } = e.current.__
162
233
 
163
- let { resizeType, around, lockRatio } = this.config
234
+ // transform
164
235
 
165
- if (e.shiftKey) lockRatio = true
166
- if (e.altKey && !around) around = 'center'
236
+ public move(x: number | IPointData, y = 0): void {
237
+ if (!this.mergeConfig.moveable || this.element.locked) return
167
238
 
168
- if (resizeType === 'auto') resizeType = target.resizeable ? 'size' : 'scale'
169
- const data = getResizeData(target.boxBounds, __direction, e.getInnerMove(this.targetRect), lockRatio, around)
239
+ const { element } = this
240
+ const world = element.getWorldPointByLocal(typeof x === 'object' ? { ...x } : { x, y }, null, true)
241
+ const event = new EditorMoveEvent(EditorMoveEvent.MOVE, { target: element, editor: this, moveX: world.x, moveY: world.y })
170
242
 
171
- const event = new EditorResizeEvent(EditorResizeEvent.RESIZE, { ...data, target, editor: this, dragEvent: e, resizeType })
243
+ this.editTool.onMove(event)
244
+ this.emitEvent(event)
172
245
 
173
- this.tool.resize(event)
174
- target.emitEvent(event)
246
+ if (this.multiple) element.move(x, y)
175
247
  }
176
248
 
249
+ public scaleWithDrag(data: IEditorScaleEvent): void {
250
+ if (!this.mergeConfig.resizeable || this.element.locked) return
177
251
 
178
- public updateMoveCursor(): void {
179
- this.targetRect.cursor = this.config.moveCursor
252
+ const { element } = this
253
+ const worldOrigin = element.getWorldPoint(data.origin)
254
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { ...data, target: element, editor: this, worldOrigin })
255
+
256
+ this.editTool.onScaleWithDrag(event)
257
+ this.emitEvent(event)
180
258
  }
181
259
 
182
260
 
183
- protected __listenEvents(): void {
184
- this.__eventIds = [
185
- this.targetRect.on_(DragEvent.START, () => { this.opacity = this.config.hideOnMove ? 0 : 1 }),
186
- this.targetRect.on_(DragEvent.DRAG, this.onMove, this),
187
- this.targetRect.on_(DragEvent.END, () => { this.opacity = 1 }),
188
- this.targetRect.on_(PointerEvent.ENTER, this.updateMoveCursor, this)
189
- ]
261
+ public scaleOf(origin: IPointData | IAlign, scaleX: number, scaleY = scaleX, _resize?: boolean): void {
262
+ if (!this.mergeConfig.resizeable || this.element.locked) return
263
+
264
+ const { element } = this
265
+ const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
266
+
267
+ let transform: Matrix
268
+
269
+ if (this.multiple) {
270
+ const oldMatrix = new Matrix(element.worldTransform)
271
+ element.scaleOf(origin, scaleX, scaleY)
272
+ transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
273
+ }
274
+
275
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform })
276
+
277
+ this.editTool.onScale(event)
278
+ this.emitEvent(event)
190
279
  }
191
280
 
192
- protected __removeListenEvents(): void {
193
- this.targetRect.off_(this.__eventIds)
194
- this.__eventIds.length = 0
281
+ public rotateOf(origin: IPointData | IAlign, rotation: number): void {
282
+ if (!this.mergeConfig.rotateable || this.element.locked) return
283
+
284
+ const { element } = this
285
+ const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
286
+
287
+
288
+ let transform: Matrix
289
+
290
+ if (this.multiple) {
291
+ const oldMatrix = new Matrix(element.worldTransform)
292
+ element.rotateOf(origin, rotation)
293
+ transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
294
+ }
295
+
296
+ const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation, transform })
297
+
298
+ this.editTool.onRotate(event)
299
+ this.emitEvent(event)
300
+ }
301
+
302
+ public skewOf(origin: IPointData | IAlign, skewX: number, skewY = 0, _resize?: boolean): void {
303
+ if (!this.mergeConfig.skewable || this.element.locked) return
304
+
305
+ const { element } = this
306
+ const worldOrigin = element.getWorldPoint(LeafHelper.getInnerOrigin(element, origin))
307
+
308
+ let transform: Matrix
309
+
310
+ if (this.multiple) {
311
+ const oldMatrix = new Matrix(element.worldTransform)
312
+ element.skewOf(origin, skewX, skewY)
313
+ transform = new Matrix(element.worldTransform).divide(oldMatrix) // world change transform
314
+ }
315
+
316
+ const event = new EditorSkewEvent(EditorSkewEvent.SKEW, {
317
+ target: element, editor: this, skewX, skewY, transform, worldOrigin
318
+ })
319
+
320
+ this.editTool.onSkew(event)
321
+ this.emitEvent(event)
322
+ }
323
+
324
+ // group
325
+
326
+ public group(userGroup?: IGroup | IGroupInputData): IGroup {
327
+ if (this.multiple) {
328
+ this.target = EditorHelper.group(this.list, this.element, userGroup)
329
+ this.emitGroupEvent(EditorGroupEvent.GROUP, this.target as IGroup)
330
+ }
331
+ return this.target as IGroup
332
+ }
333
+
334
+ public ungroup(): IUI[] {
335
+ const { list } = this
336
+ if (list.length) {
337
+ list.forEach(item => item.isBranch && this.emitGroupEvent(EditorGroupEvent.BEFORE_UNGROUP, item as IGroup))
338
+ this.target = EditorHelper.ungroup(list)
339
+ list.forEach(item => item.isBranch && this.emitGroupEvent(EditorGroupEvent.UNGROUP, item as IGroup))
340
+ }
341
+ return this.list
342
+ }
343
+
344
+ public openGroup(group: IGroup): void {
345
+ this.openedGroupList.add(group)
346
+ group.hitChildren = true
347
+ this.emitGroupEvent(EditorGroupEvent.OPEN, group)
348
+ }
349
+
350
+ public closeGroup(group: IGroup): void {
351
+ this.openedGroupList.remove(group)
352
+ group.hitChildren = false
353
+ this.emitGroupEvent(EditorGroupEvent.CLOSE, group)
354
+ }
355
+
356
+ public checkOpenedGroups(): void {
357
+ const opened = this.openedGroupList
358
+ if (opened.length) {
359
+ let { list } = opened
360
+ if (this.editing) list = [], opened.forEach(item => this.list.every(leaf => !LeafHelper.hasParent(leaf, item)) && list.push(item))
361
+ list.forEach(item => this.closeGroup(item as IGroup))
362
+ }
363
+ if (this.editing && !this.selector.dragging) this.checkDeepSelect()
364
+ }
365
+
366
+ public checkDeepSelect(): void {
367
+ let parent: IGroup, { list } = this
368
+ for (let i = 0; i < list.length; i++) {
369
+ parent = list[i].parent
370
+ while (parent && !parent.hitChildren) {
371
+ this.openGroup(parent)
372
+ parent = parent.parent
373
+ }
374
+ }
375
+ }
376
+
377
+ public emitGroupEvent(type: string, group: IGroup): void {
378
+ const event = new EditorGroupEvent(type, { editTarget: group })
379
+ this.emitEvent(event)
380
+ group.emitEvent(event)
195
381
  }
196
382
 
383
+ // inner
384
+
385
+ public openInnerEditor(target?: IUI): void {
386
+ if (target) this.target = target
387
+ if (this.single) {
388
+ const editTarget = this.element
389
+ const tag = editTarget.editInner
390
+ if (tag && EditToolCreator.list[tag]) {
391
+ this.editTool.unload()
392
+ this.innerEditing = true
393
+ this.innerEditor = this.editToolList[tag] || EditToolCreator.get(tag, this)
394
+ this.innerEditor.editTarget = editTarget
395
+
396
+ this.emitInnerEvent(InnerEditorEvent.BEFORE_OPEN)
397
+ this.innerEditor.load()
398
+ this.emitInnerEvent(InnerEditorEvent.OPEN)
399
+ }
400
+ }
401
+ }
402
+
403
+ public closeInnerEditor(): void {
404
+ if (this.innerEditing) {
405
+ this.innerEditing = false
406
+
407
+ this.emitInnerEvent(InnerEditorEvent.BEFORE_CLOSE)
408
+ this.innerEditor.unload()
409
+ this.emitInnerEvent(InnerEditorEvent.CLOSE)
410
+
411
+ this.editTool.load()
412
+ this.innerEditor = null
413
+ }
414
+ }
197
415
 
198
- protected __listenPointEvents(point: IUI, type: 'rotate' | 'resize', direction: IDirection8): void {
199
- point.__.__direction = direction
200
- const resize = point.__.__isResizePoint = type === 'resize'
201
- point.on_(DragEvent.DRAG, resize ? this.onDrag : this.onRotate, this) // i % 2 ? this.onSkew :
202
- point.on_(PointerEvent.LEAVE, () => this.enterPoint = null)
203
- point.on_(PointerEvent.ENTER, (e) => { this.enterPoint = point; updateCursor(this, e) })
416
+ public emitInnerEvent(type: string): void {
417
+ const { innerEditor } = this
418
+ const { editTarget } = innerEditor
419
+ const event = new InnerEditorEvent(type, { editTarget, innerEditor })
420
+ this.emitEvent(event)
421
+ editTarget.emitEvent(event)
204
422
  }
205
423
 
424
+ // lock
206
425
 
207
- protected __listenTargetEvents(): void {
208
- if (this.target) {
209
- const { leafer } = this.target
210
- this.__targetEventIds = [
426
+ public lock(): void {
427
+ this.list.forEach(leaf => leaf.locked = true)
428
+ this.update()
429
+ }
430
+
431
+ public unlock(): void {
432
+ this.list.forEach(leaf => leaf.locked = false)
433
+ this.update()
434
+ }
435
+
436
+ // level
437
+
438
+ public toTop(): void {
439
+ if (this.list.length) {
440
+ EditorHelper.toTop(this.list)
441
+ this.leafList.update()
442
+ }
443
+ }
444
+
445
+ public toBottom(): void {
446
+ if (this.list.length) {
447
+ EditorHelper.toBottom(this.list)
448
+ this.leafList.update()
449
+ }
450
+ }
451
+
452
+ // event
453
+
454
+ public listenTargetEvents(): void {
455
+ if (!this.targetEventIds.length) {
456
+ const { leafer } = this.list[0]
457
+ this.targetEventIds = [
211
458
  leafer.on_(RenderEvent.START, this.update, this),
212
- leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e) => { updateCursor(this, e) })
459
+ leafer.on_([KeyEvent.HOLD, KeyEvent.UP], (e: KeyEvent) => { updateCursor(this, e) }),
460
+ leafer.on_(KeyEvent.DOWN, this.editBox.onArrow, this.editBox)
213
461
  ]
214
462
  }
215
463
  }
216
464
 
217
- protected __removeTargetEvents(): void {
218
- if (this.__targetEventIds.length) {
219
- const { leafer } = this.target
220
- if (leafer) leafer.off_(this.__targetEventIds)
221
- this.__targetEventIds.length = 0
465
+ public removeTargetEvents(): void {
466
+ const { targetEventIds } = this
467
+ if (targetEventIds.length) {
468
+ this.off_(targetEventIds)
469
+ targetEventIds.length = 0
222
470
  }
223
471
  }
224
472
 
225
-
226
473
  public destroy(): void {
227
- this.__removeListenEvents()
228
- this._target = null
229
- super.destroy()
474
+ if (!this.destroyed) {
475
+ this.simulateTarget.destroy()
476
+ Object.values(this.editToolList).forEach(item => item.destroy())
477
+ this.editToolList = {}
478
+ this.target = this.hoverTarget = this.simulateTarget = this.editTool = this.innerEditor = null
479
+ super.destroy()
480
+ }
230
481
  }
231
482
 
232
483
  }
package/src/config.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { IEditorConfig } from '@leafer-in/interface'
2
+ import { resizeSVG, rotateSVG, skewSVG } from './svg'
3
+
4
+
5
+ export const config: IEditorConfig = {
6
+ editSize: 'size',
7
+ keyEvent: true,
8
+
9
+ stroke: '#836DFF',
10
+ strokeWidth: 2,
11
+
12
+ pointFill: '#FFFFFF',
13
+ pointSize: 10,
14
+ pointRadius: 16,
15
+
16
+ rotateGap: 45,
17
+
18
+ buttonsDirection: 'bottom',
19
+ buttonsMargin: 12,
20
+
21
+ hideOnSmall: true,
22
+
23
+ moveCursor: 'move',
24
+ resizeCursor: { url: resizeSVG, x: 12, y: 12 },
25
+ rotateCursor: { url: rotateSVG, x: 12, y: 12 },
26
+ skewCursor: { url: skewSVG, x: 12, y: 12 },
27
+
28
+ selector: true,
29
+ hover: true,
30
+ select: 'press',
31
+ openInner: 'double',
32
+ boxSelect: true,
33
+
34
+ moveable: true,
35
+ resizeable: true,
36
+ rotateable: true,
37
+ skewable: true
38
+ }