@leafer-editor/worker 1.4.1 → 1.5.0

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.
@@ -3635,7 +3635,12 @@ const Resource = {
3635
3635
  return R.map[key];
3636
3636
  },
3637
3637
  remove(key) {
3638
- delete R.map[key];
3638
+ const r = R.map[key];
3639
+ if (r) {
3640
+ if (r.destroy)
3641
+ r.destroy();
3642
+ delete R.map[key];
3643
+ }
3639
3644
  },
3640
3645
  loadImage(key, format) {
3641
3646
  return new Promise((resolve, reject) => {
@@ -3661,6 +3666,7 @@ const Resource = {
3661
3666
  const R = Resource;
3662
3667
 
3663
3668
  const ImageManager = {
3669
+ maxRecycled: 100,
3664
3670
  recycledList: [],
3665
3671
  patternTasker: new TaskProcessor(),
3666
3672
  get(config) {
@@ -3677,13 +3683,8 @@ const ImageManager = {
3677
3683
  },
3678
3684
  clearRecycled() {
3679
3685
  const list = I$1.recycledList;
3680
- if (list.length > 100) {
3681
- list.forEach(image => {
3682
- if (!image.use && image.url) {
3683
- Resource.remove(image.url);
3684
- image.destroy();
3685
- }
3686
- });
3686
+ if (list.length > I$1.maxRecycled) {
3687
+ list.forEach(image => (!image.use && image.url) && Resource.remove(image.url));
3687
3688
  list.length = 0;
3688
3689
  }
3689
3690
  },
@@ -4069,12 +4070,11 @@ function defineDataProcessor(target, key, defaultValue) {
4069
4070
  if (defaultValue === undefined) {
4070
4071
  property.get = function () { return this[computedKey]; };
4071
4072
  }
4072
- else if (typeof defaultValue === 'object') {
4073
- const { clone } = DataHelper;
4073
+ else if (typeof defaultValue === 'function') {
4074
4074
  property.get = function () {
4075
4075
  let v = this[computedKey];
4076
4076
  if (v === undefined)
4077
- this[computedKey] = v = clone(defaultValue);
4077
+ this[computedKey] = v = defaultValue(this.__leaf);
4078
4078
  return v;
4079
4079
  };
4080
4080
  }
@@ -5721,10 +5721,10 @@ let Leaf = class Leaf {
5721
5721
  static changeAttr(attrName, defaultValue, fn) {
5722
5722
  fn ? this.addAttr(attrName, defaultValue, fn) : defineDataProcessor(this.prototype, attrName, defaultValue);
5723
5723
  }
5724
- static addAttr(attrName, defaultValue, fn) {
5724
+ static addAttr(attrName, defaultValue, fn, helpValue) {
5725
5725
  if (!fn)
5726
5726
  fn = boundsType;
5727
- fn(defaultValue)(this.prototype, attrName);
5727
+ fn(defaultValue, helpValue)(this.prototype, attrName);
5728
5728
  }
5729
5729
  __emitLifeEvent(type) {
5730
5730
  if (this.hasEvent(type))
@@ -6051,7 +6051,7 @@ class LeafLevelList {
6051
6051
  }
6052
6052
  }
6053
6053
 
6054
- const version = "1.4.1";
6054
+ const version = "1.5.0";
6055
6055
 
6056
6056
  class LeaferCanvas extends LeaferCanvasBase {
6057
6057
  get allowBackgroundColor() { return true; }
@@ -6938,7 +6938,11 @@ const State = {
6938
6938
  setStyleName() { return Plugin.need('state'); },
6939
6939
  set() { return Plugin.need('state'); }
6940
6940
  };
6941
- const Transition = {};
6941
+ const Transition = {
6942
+ list: {},
6943
+ register(attrName, fn) { Transition.list[attrName] = fn; },
6944
+ get(attrName) { return Transition.list[attrName]; }
6945
+ };
6942
6946
 
6943
6947
  const { parse, objectToCanvasData } = PathConvert;
6944
6948
  const emptyPaint = {};
@@ -7362,9 +7366,6 @@ let UI = UI_1 = class UI extends Leaf {
7362
7366
  this.__drawPathByBox(pen);
7363
7367
  return pen;
7364
7368
  }
7365
- get editConfig() { return undefined; }
7366
- get editOuter() { return ''; }
7367
- get editInner() { return ''; }
7368
7369
  constructor(data) {
7369
7370
  super(data);
7370
7371
  }
@@ -7446,8 +7447,11 @@ let UI = UI_1 = class UI extends Leaf {
7446
7447
  export(_filename, _options) {
7447
7448
  return Plugin.need('export');
7448
7449
  }
7450
+ syncExport(_filename, _options) {
7451
+ return Plugin.need('export');
7452
+ }
7449
7453
  clone(data) {
7450
- const json = this.toJSON();
7454
+ const json = DataHelper.clone(this.toJSON());
7451
7455
  if (data)
7452
7456
  Object.assign(json, data);
7453
7457
  return UI_1.one(json);
@@ -7746,7 +7750,7 @@ let Leafer = Leafer_1 = class Leafer extends Group {
7746
7750
  get layoutLocked() { return !this.layouter.running; }
7747
7751
  get FPS() { return this.renderer ? this.renderer.FPS : 60; }
7748
7752
  get cursorPoint() { return (this.interaction && this.interaction.hoverData) || { x: this.width / 2, y: this.height / 2 }; }
7749
- get clientBounds() { return this.canvas && this.canvas.getClientBounds(); }
7753
+ get clientBounds() { return (this.canvas && this.canvas.getClientBounds(true)) || getBoundsData(); }
7750
7754
  constructor(userConfig, data) {
7751
7755
  super(data);
7752
7756
  this.config = {
@@ -8048,6 +8052,10 @@ let Leafer = Leafer_1 = class Leafer extends Group {
8048
8052
  getPagePointByClient(clientPoint, updateClient) {
8049
8053
  return this.getPagePoint(this.getWorldPointByClient(clientPoint, updateClient));
8050
8054
  }
8055
+ getClientPointByWorld(worldPoint) {
8056
+ const { x, y } = this.clientBounds;
8057
+ return { x: x + worldPoint.x, y: y + worldPoint.y };
8058
+ }
8051
8059
  updateClientBounds() {
8052
8060
  this.canvas && this.canvas.updateClientBounds();
8053
8061
  }
@@ -9987,8 +9995,8 @@ leaf$1.__drawHitPath = function (canvas) { if (canvas)
9987
9995
  this.__drawRenderPath(canvas); };
9988
9996
 
9989
9997
  const matrix$2 = new Matrix();
9990
- const ui$3 = UI.prototype;
9991
- ui$3.__updateHitCanvas = function () {
9998
+ const ui$2 = UI.prototype;
9999
+ ui$2.__updateHitCanvas = function () {
9992
10000
  const data = this.__, { hitCanvasManager } = this.leafer;
9993
10001
  const isHitPixelFill = (data.__pixelFill || data.__isCanvas) && data.hitFill === 'pixel';
9994
10002
  const isHitPixelStroke = data.__pixelStroke && data.hitStroke === 'pixel';
@@ -10015,9 +10023,7 @@ ui$3.__updateHitCanvas = function () {
10015
10023
  this.__drawHitPath(h);
10016
10024
  h.setStrokeOptions(data);
10017
10025
  };
10018
- ui$3.__hit = function (inner) {
10019
- if (Platform.name === 'miniapp')
10020
- this.__drawHitPath(this.__hitCanvas);
10026
+ ui$2.__hit = function (inner) {
10021
10027
  const data = this.__;
10022
10028
  if (data.__isHitPixel && this.__hitPixel(inner))
10023
10029
  return true;
@@ -10055,15 +10061,15 @@ ui$3.__hit = function (inner) {
10055
10061
  return hitWidth ? this.__hitStroke(inner, hitWidth) : false;
10056
10062
  };
10057
10063
 
10058
- const ui$2 = UI.prototype, rect = Rect.prototype, box$1 = Box.prototype;
10064
+ const ui$1 = UI.prototype, rect = Rect.prototype, box$1 = Box.prototype;
10059
10065
  rect.__updateHitCanvas = box$1.__updateHitCanvas = function () {
10060
10066
  if (this.stroke || this.cornerRadius || ((this.fill || this.__.__isCanvas) && this.hitFill === 'pixel') || this.hitStroke === 'all')
10061
- ui$2.__updateHitCanvas.call(this);
10067
+ ui$1.__updateHitCanvas.call(this);
10062
10068
  else if (this.__hitCanvas)
10063
10069
  this.__hitCanvas = null;
10064
10070
  };
10065
10071
  rect.__hitFill = box$1.__hitFill = function (inner) {
10066
- return this.__hitCanvas ? ui$2.__hitFill.call(this, inner) : BoundsHelper.hitRadiusPoint(this.__layout.boxBounds, inner);
10072
+ return this.__hitCanvas ? ui$1.__hitFill.call(this, inner) : BoundsHelper.hitRadiusPoint(this.__layout.boxBounds, inner);
10067
10073
  };
10068
10074
 
10069
10075
  function getSelector$1(ui) {
@@ -11372,13 +11378,14 @@ function toChar(data, charX, rowData, isOverflow) {
11372
11378
  }
11373
11379
 
11374
11380
  function layoutText(drawData, style) {
11375
- const { rows, bounds } = drawData;
11381
+ const { rows, bounds } = drawData, countRows = rows.length;
11376
11382
  const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing, autoSizeAlign } = style;
11377
- let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
11383
+ let { x, y, width, height } = bounds, realHeight = __lineHeight * countRows + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
11378
11384
  let starY = __baseLine;
11379
11385
  if (__clipText && realHeight > height) {
11380
11386
  realHeight = Math.max(height, __lineHeight);
11381
- drawData.overflow = rows.length;
11387
+ if (countRows > 1)
11388
+ drawData.overflow = countRows;
11382
11389
  }
11383
11390
  else if (height || autoSizeAlign) {
11384
11391
  switch (verticalAlign) {
@@ -11390,7 +11397,7 @@ function layoutText(drawData, style) {
11390
11397
  }
11391
11398
  starY += y;
11392
11399
  let row, rowX, rowWidth, layoutWidth = (width || autoSizeAlign) ? width : drawData.maxWidth;
11393
- for (let i = 0, len = rows.length; i < len; i++) {
11400
+ for (let i = 0, len = countRows; i < len; i++) {
11394
11401
  row = rows[i];
11395
11402
  row.x = x;
11396
11403
  if (row.width < width || (row.width > width && !__clipText)) {
@@ -11459,7 +11466,7 @@ function clipText(drawData, style, x, width) {
11459
11466
  if (i === end && charRight < right) {
11460
11467
  break;
11461
11468
  }
11462
- else if (charRight < right && char.char !== ' ') {
11469
+ else if ((charRight < right && char.char !== ' ') || !i) {
11463
11470
  row.data.splice(i + 1);
11464
11471
  row.width -= char.width;
11465
11472
  break;
@@ -11611,6 +11618,7 @@ class EditorMoveEvent extends EditorEvent {
11611
11618
  super(type, data);
11612
11619
  }
11613
11620
  }
11621
+ EditorMoveEvent.BEFORE_MOVE = 'editor.before_move';
11614
11622
  EditorMoveEvent.MOVE = 'editor.move';
11615
11623
 
11616
11624
  class EditorScaleEvent extends EditorEvent {
@@ -11618,6 +11626,7 @@ class EditorScaleEvent extends EditorEvent {
11618
11626
  super(type, data);
11619
11627
  }
11620
11628
  }
11629
+ EditorScaleEvent.BEFORE_SCALE = 'editor.before_scale';
11621
11630
  EditorScaleEvent.SCALE = 'editor.scale';
11622
11631
 
11623
11632
  class EditorRotateEvent extends EditorEvent {
@@ -11625,6 +11634,7 @@ class EditorRotateEvent extends EditorEvent {
11625
11634
  super(type, data);
11626
11635
  }
11627
11636
  }
11637
+ EditorRotateEvent.BEFORE_ROTATE = 'editor.before_rotate';
11628
11638
  EditorRotateEvent.ROTATE = 'editor.rotate';
11629
11639
 
11630
11640
  class EditorSkewEvent extends EditorEvent {
@@ -11632,6 +11642,7 @@ class EditorSkewEvent extends EditorEvent {
11632
11642
  super(type, data);
11633
11643
  }
11634
11644
  }
11645
+ EditorSkewEvent.BEFORE_SKEW = 'editor.before_skew';
11635
11646
  EditorSkewEvent.SKEW = 'editor.skew';
11636
11647
 
11637
11648
  function targetAttr(fn) {
@@ -11684,7 +11695,7 @@ class Stroker extends UI {
11684
11695
  for (let i = 0; i < list.length; i++) {
11685
11696
  leaf = list[i];
11686
11697
  const { worldTransform, worldRenderBounds } = leaf;
11687
- if (!bounds || bounds.hit(worldRenderBounds, options.matrix)) {
11698
+ if (worldRenderBounds.width && worldRenderBounds.height && (!bounds || bounds.hit(worldRenderBounds, options.matrix))) {
11688
11699
  const aScaleX = abs$1(worldTransform.scaleX), aScaleY = abs$1(worldTransform.scaleY);
11689
11700
  if (aScaleX !== aScaleY) {
11690
11701
  copy$2(matrix$1, worldTransform);
@@ -11810,9 +11821,9 @@ class EditSelect extends Group {
11810
11821
  }
11811
11822
  onSelect() {
11812
11823
  if (this.running) {
11813
- const { mergeConfig: config, list } = this.editor;
11814
- const { stroke, strokeWidth } = config;
11815
- this.targetStroker.setTarget(list, { stroke, strokeWidth: Math.max(1, strokeWidth / 2) });
11824
+ const { mergeConfig, list } = this.editor;
11825
+ const { stroke, strokeWidth, selectedStyle } = mergeConfig;
11826
+ this.targetStroker.setTarget(list, Object.assign({ stroke, strokeWidth: Math.max(1, strokeWidth / 2) }, (selectedStyle || {})));
11816
11827
  this.hoverStroker.target = null;
11817
11828
  }
11818
11829
  }
@@ -11999,7 +12010,7 @@ const { within } = MathHelper;
11999
12010
  const EditDataHelper = {
12000
12011
  getScaleData(element, startBounds, direction, totalMove, lockRatio, around, flipable, scaleMode) {
12001
12012
  let align, origin = {}, scaleX = 1, scaleY = 1;
12002
- const { boxBounds, widthRange, heightRange, dragBounds } = element;
12013
+ const { boxBounds, widthRange, heightRange, dragBounds, worldBoxBounds } = element;
12003
12014
  const { width, height } = startBounds;
12004
12015
  if (around) {
12005
12016
  totalMove.x *= 2;
@@ -12013,10 +12024,6 @@ const EditDataHelper = {
12013
12024
  const changedScaleY = scaleMode ? originChangedScaleY : signY * boxBounds.height / height;
12014
12025
  totalMove.x *= scaleMode ? originChangedScaleX : signX;
12015
12026
  totalMove.y *= scaleMode ? originChangedScaleY : signY;
12016
- if (Math.abs(totalMove.x) === width)
12017
- totalMove.x += 0.1;
12018
- if (Math.abs(totalMove.y) === height)
12019
- totalMove.y += 0.1;
12020
12027
  const topScale = (-totalMove.y + height) / height;
12021
12028
  const rightScale = (totalMove.x + width) / width;
12022
12029
  const bottomScale = (totalMove.y + height) / height;
@@ -12106,6 +12113,10 @@ const EditDataHelper = {
12106
12113
  const nowHeight = boxBounds.height * element.scaleY;
12107
12114
  scaleY = within(nowHeight * scaleY, heightRange) / nowHeight;
12108
12115
  }
12116
+ if (Math.abs(scaleX * worldBoxBounds.width) < 1)
12117
+ scaleX = (scaleX < 0 ? -1 : 1) / worldBoxBounds.width;
12118
+ if (Math.abs(scaleY * worldBoxBounds.height) < 1)
12119
+ scaleY = (scaleY < 0 ? -1 : 1) / worldBoxBounds.height;
12109
12120
  return { origin, scaleX, scaleY, direction, lockRatio, around };
12110
12121
  },
12111
12122
  getRotateData(bounds, direction, current, last, around) {
@@ -12234,7 +12245,7 @@ function updateCursor(editor, e) {
12234
12245
  let { rotation } = editBox;
12235
12246
  const { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editor.mergeConfig;
12236
12247
  const { pointType } = point, { flippedX, flippedY } = editBox;
12237
- let showResize = pointType === 'resize';
12248
+ let showResize = pointType.includes('resize');
12238
12249
  if (showResize && rotateable && (e.metaKey || e.ctrlKey || !resizeable))
12239
12250
  showResize = false;
12240
12251
  const showSkew = skewable && !showResize && point.name === 'resize-line';
@@ -12261,7 +12272,7 @@ function toDataURL(svg, rotation) {
12261
12272
  class EditPoint extends Box {
12262
12273
  }
12263
12274
 
12264
- const fourDirection = ['top', 'right', 'bottom', 'left'];
12275
+ const fourDirection = ['top', 'right', 'bottom', 'left'], editConfig = undefined;
12265
12276
  class EditBox extends Group {
12266
12277
  get flipped() { return this.flippedX || this.flippedY; }
12267
12278
  get flippedX() { return this.scaleX < 0; }
@@ -12276,6 +12287,7 @@ class EditBox extends Group {
12276
12287
  this.resizePoints = [];
12277
12288
  this.rotatePoints = [];
12278
12289
  this.resizeLines = [];
12290
+ this.dragStartData = {};
12279
12291
  this.__eventIds = [];
12280
12292
  this.editor = editor;
12281
12293
  this.visible = false;
@@ -12317,7 +12329,7 @@ class EditBox extends Group {
12317
12329
  resizeP.rotation = (i / 2) * 90;
12318
12330
  }
12319
12331
  circle.set(this.getPointStyle(mergeConfig.circle || mergeConfig.rotatePoint || pointsStyle[0]));
12320
- rect.set(Object.assign({ stroke, strokeWidth }, (mergeConfig.rect || {})));
12332
+ rect.set(Object.assign({ stroke, strokeWidth, editConfig }, (mergeConfig.rect || {})));
12321
12333
  rect.hittable = !single;
12322
12334
  rect.syncEventer = single && this.editor;
12323
12335
  if (single) {
@@ -12326,14 +12338,14 @@ class EditBox extends Group {
12326
12338
  }
12327
12339
  }
12328
12340
  update(bounds) {
12329
- this.visible = !this.editor.element.locked;
12341
+ const { mergeConfig, element, multiple } = this.editor;
12342
+ const { middlePoint, resizeable, rotateable, hideOnSmall, editBox } = mergeConfig;
12343
+ this.visible = !element.locked;
12330
12344
  if (this.view.worldOpacity) {
12331
- const { mergeConfig } = this.editor;
12332
12345
  const { width, height } = bounds;
12333
12346
  const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this;
12334
- const { middlePoint, resizeable, rotateable, hideOnSmall } = mergeConfig;
12335
12347
  const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10;
12336
- const showPoints = !(hideOnSmall && width < smallSize && height < smallSize);
12348
+ const showPoints = editBox && !(hideOnSmall && width < smallSize && height < smallSize);
12337
12349
  let point = {}, rotateP, resizeP, resizeL;
12338
12350
  for (let i = 0; i < 8; i++) {
12339
12351
  AroundHelper.toPoint(AroundHelper.directionData[i], bounds, point);
@@ -12349,13 +12361,13 @@ class EditBox extends Group {
12349
12361
  resizeP.visible = rotateP.visible = showPoints && !!middlePoint;
12350
12362
  if (((i + 1) / 2) % 2) {
12351
12363
  resizeL.width = width;
12352
- if (resizeP.width > width - 30)
12364
+ if (hideOnSmall && resizeP.width * 2 > width)
12353
12365
  resizeP.visible = false;
12354
12366
  }
12355
12367
  else {
12356
12368
  resizeL.height = height;
12357
12369
  resizeP.rotation = 90;
12358
- if (resizeP.width > height - 30)
12370
+ if (hideOnSmall && resizeP.width * 2 > height)
12359
12371
  resizeP.visible = false;
12360
12372
  }
12361
12373
  }
@@ -12365,7 +12377,7 @@ class EditBox extends Group {
12365
12377
  this.layoutCircle(mergeConfig);
12366
12378
  if (rect.path)
12367
12379
  rect.path = null;
12368
- rect.set(Object.assign(Object.assign({}, bounds), { visible: true }));
12380
+ rect.set(Object.assign(Object.assign({}, bounds), { visible: multiple ? true : editBox }));
12369
12381
  buttons.visible = showPoints && buttons.children.length > 0;
12370
12382
  if (buttons.visible)
12371
12383
  this.layoutButtons(mergeConfig);
@@ -12412,7 +12424,7 @@ class EditBox extends Group {
12412
12424
  }
12413
12425
  getPointStyle(userStyle) {
12414
12426
  const { stroke, strokeWidth, pointFill, pointSize, pointRadius } = this.editor.mergeConfig;
12415
- const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0 };
12427
+ const defaultStyle = { fill: pointFill, stroke, strokeWidth, around: 'center', strokeAlign: 'center', width: pointSize, height: pointSize, cornerRadius: pointRadius, offsetX: 0, offsetY: 0, editConfig };
12416
12428
  return userStyle ? Object.assign(defaultStyle, userStyle) : defaultStyle;
12417
12429
  }
12418
12430
  getPointsStyle() {
@@ -12432,34 +12444,32 @@ class EditBox extends Group {
12432
12444
  }
12433
12445
  onDragStart(e) {
12434
12446
  this.dragging = true;
12435
- const { editor } = this;
12436
- if (e.current.name === 'rect') {
12447
+ const point = this.dragPoint = e.current;
12448
+ const { editor, dragStartData } = this, { element } = editor;
12449
+ if (point.name === 'rect') {
12437
12450
  this.moving = true;
12438
- editor.dragStartPoint = { x: editor.element.x, y: editor.element.y };
12439
12451
  editor.opacity = editor.mergeConfig.hideOnMove ? 0 : 1;
12440
12452
  }
12441
- else if (e.current.pointType === 'resize') {
12442
- editor.dragStartBounds = Object.assign({}, editor.element.getLayoutBounds('box', 'local'));
12443
- editor.resizeDirection = e.current.direction;
12444
- }
12453
+ dragStartData.x = e.x;
12454
+ dragStartData.y = e.y;
12455
+ dragStartData.point = { x: element.x, y: element.y };
12456
+ dragStartData.bounds = Object.assign({}, element.getLayoutBounds('box', 'local'));
12457
+ dragStartData.rotation = element.rotation;
12445
12458
  }
12446
12459
  onDragEnd(e) {
12447
12460
  this.dragging = false;
12461
+ this.dragPoint = null;
12448
12462
  this.moving = false;
12449
12463
  if (e.current.name === 'rect')
12450
12464
  this.editor.opacity = 1;
12451
- this.editor.resizeDirection = undefined;
12452
12465
  }
12453
12466
  onDrag(e) {
12454
12467
  const { editor } = this;
12455
- const point = this.enterPoint = e.current;
12456
- if (point.pointType === 'rotate' || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable) {
12457
- if (editor.mergeConfig.rotateable)
12458
- editor.onRotate(e);
12459
- }
12460
- else if (point.pointType === 'resize') {
12468
+ const { pointType } = this.enterPoint = e.current;
12469
+ if (pointType.includes('rotate') || e.metaKey || e.ctrlKey || !editor.mergeConfig.resizeable)
12470
+ editor.onRotate(e);
12471
+ if (pointType.includes('resize'))
12461
12472
  editor.onScale(e);
12462
- }
12463
12473
  updateCursor(editor, e);
12464
12474
  }
12465
12475
  onArrow(e) {
@@ -12637,6 +12647,7 @@ const config = {
12637
12647
  rotateCursor: { url: rotateSVG, x: 12, y: 12 },
12638
12648
  skewCursor: { url: skewSVG, x: 12, y: 12 },
12639
12649
  selector: true,
12650
+ editBox: true,
12640
12651
  hover: true,
12641
12652
  select: 'press',
12642
12653
  openInner: 'double',
@@ -12652,14 +12663,25 @@ const bounds$1 = new Bounds();
12652
12663
  function simulate(editor) {
12653
12664
  const { simulateTarget, list } = editor;
12654
12665
  const { zoomLayer } = list[0].leafer.zoomLayer;
12655
- simulateTarget.safeChange(() => simulateTarget.reset(bounds$1.setListWithFn(list, (leaf) => leaf.getBounds('box', 'page')).get()));
12666
+ simulateTarget.safeChange(() => {
12667
+ bounds$1.setListWithFn(list, (leaf) => leaf.getBounds('box', 'page'));
12668
+ if (bounds$1.width === 0)
12669
+ bounds$1.width = 0.1;
12670
+ if (bounds$1.height === 0)
12671
+ bounds$1.height = 0.1;
12672
+ simulateTarget.reset(bounds$1.get());
12673
+ });
12656
12674
  zoomLayer.add(simulateTarget);
12657
12675
  }
12658
12676
 
12659
12677
  function onTarget(editor, oldValue) {
12660
12678
  const { target } = editor;
12661
12679
  if (target) {
12662
- editor.leafList = target instanceof LeafList ? target : new LeafList(target instanceof Array ? target : target);
12680
+ const { list } = editor.leafList = target instanceof LeafList ? target : new LeafList(target instanceof Array ? target : target);
12681
+ if (!list.every(checkEditable)) {
12682
+ editor.target = list.filter(checkEditable);
12683
+ return;
12684
+ }
12663
12685
  if (editor.multiple)
12664
12686
  simulate(editor);
12665
12687
  }
@@ -12686,6 +12708,9 @@ function onTarget(editor, oldValue) {
12686
12708
  function onHover(editor, oldValue) {
12687
12709
  editor.emitEvent(new EditorEvent(EditorEvent.HOVER, { editor, value: editor.hoverTarget, oldValue }));
12688
12710
  }
12711
+ function checkEditable(item) {
12712
+ return item.editable && !item.locked;
12713
+ }
12689
12714
 
12690
12715
  const order = (a, b) => a.parent.children.indexOf(a) - b.parent.children.indexOf(b);
12691
12716
  const reverseOrder = (a, b) => b.parent.children.indexOf(b) - a.parent.children.indexOf(a);
@@ -12783,10 +12808,13 @@ class EditorGroupEvent extends EditorEvent {
12783
12808
  super(type, data);
12784
12809
  }
12785
12810
  }
12811
+ EditorGroupEvent.BEFORE_GROUP = 'editor.before_group';
12786
12812
  EditorGroupEvent.GROUP = 'editor.group';
12787
12813
  EditorGroupEvent.BEFORE_UNGROUP = 'editor.before_ungroup';
12788
12814
  EditorGroupEvent.UNGROUP = 'editor.ungroup';
12815
+ EditorGroupEvent.BEFORE_OPEN = 'editor.before_open_group';
12789
12816
  EditorGroupEvent.OPEN = 'editor.open_group';
12817
+ EditorGroupEvent.BEFORE_CLOSE = 'editor.before_close_group';
12790
12818
  EditorGroupEvent.CLOSE = 'editor.close_group';
12791
12819
 
12792
12820
  const { updateMatrix } = LeafHelper;
@@ -12849,8 +12877,20 @@ class SimulateElement extends Rect {
12849
12877
 
12850
12878
  class Editor extends Group {
12851
12879
  get mergeConfig() {
12852
- const { element, config } = this;
12853
- return this.single && element.editConfig ? Object.assign(Object.assign({}, config), element.editConfig) : config;
12880
+ const { config, element, dragPoint } = this, mergeConfig = Object.assign({}, config);
12881
+ if (element && element.editConfig)
12882
+ Object.assign(mergeConfig, element.editConfig);
12883
+ if (dragPoint) {
12884
+ if (dragPoint.editConfig)
12885
+ Object.assign(mergeConfig, dragPoint.editConfig);
12886
+ if (mergeConfig.editSize === 'font-size')
12887
+ mergeConfig.lockRatio = true;
12888
+ if (dragPoint.pointType === 'resize-rotate') {
12889
+ mergeConfig.around || (mergeConfig.around = 'center');
12890
+ isNull(mergeConfig.lockRatio) && (mergeConfig.lockRatio = true);
12891
+ }
12892
+ }
12893
+ return mergeConfig;
12854
12894
  }
12855
12895
  get list() { return this.leafList.list; }
12856
12896
  get dragHoverExclude() { return [this.editBox.rect]; }
@@ -12860,6 +12900,7 @@ class Editor extends Group {
12860
12900
  get single() { return this.list.length === 1; }
12861
12901
  get dragging() { return this.editBox.dragging; }
12862
12902
  get moving() { return this.editBox.moving; }
12903
+ get dragPoint() { return this.editBox.dragPoint; }
12863
12904
  get element() { return this.multiple ? this.simulateTarget : this.list[0]; }
12864
12905
  get buttons() { return this.editBox.buttons; }
12865
12906
  constructor(userConfig, data) {
@@ -12950,7 +12991,7 @@ class Editor extends Group {
12950
12991
  else
12951
12992
  total.x = 0;
12952
12993
  }
12953
- this.move(DragEvent.getValidMove(this.element, this.dragStartPoint, total));
12994
+ this.move(DragEvent.getValidMove(this.element, this.editBox.dragStartData.point, total));
12954
12995
  }
12955
12996
  }
12956
12997
  onScale(e) {
@@ -12964,7 +13005,7 @@ class Editor extends Group {
12964
13005
  const { direction } = e.current;
12965
13006
  if (e.shiftKey || element.lockRatio)
12966
13007
  lockRatio = true;
12967
- const data = EditDataHelper.getScaleData(element, this.dragStartBounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale');
13008
+ const data = EditDataHelper.getScaleData(element, this.editBox.dragStartData.bounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale');
12968
13009
  if (this.editTool.onScaleWithDrag) {
12969
13010
  data.drag = e;
12970
13011
  this.scaleWithDrag(data);
@@ -12979,26 +13020,29 @@ class Editor extends Group {
12979
13020
  const { direction, name } = e.current;
12980
13021
  if (skewable && name === 'resize-line')
12981
13022
  return this.onSkew(e);
12982
- const { element } = this;
13023
+ const { element } = this, { dragStartData } = this.editBox;
12983
13024
  let origin, rotation;
12984
13025
  if (e instanceof RotateEvent) {
12985
13026
  if (rotateable === 'rotate')
12986
13027
  e.stop(), rotation = e.rotation, origin = element.getBoxPoint(e);
12987
13028
  else
12988
13029
  return;
13030
+ if (element.scaleX * element.scaleY < 0)
13031
+ rotation = -rotation;
12989
13032
  }
12990
13033
  else {
12991
- const last = { x: e.x - e.moveX, y: e.y - e.moveY };
12992
- const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getBoxPoint(element), element.getBoxPoint(last), e.shiftKey ? null : (element.around || element.origin || around || 'center'));
13034
+ const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getBoxPoint(element), element.getBoxPoint(dragStartData), e.shiftKey ? null : (element.around || element.origin || around || 'center'));
12993
13035
  rotation = data.rotation;
12994
13036
  origin = data.origin;
12995
13037
  }
12996
- rotation = MathHelper.getGapRotation(rotation, rotateGap, element.rotation);
12997
- if (!rotation)
12998
- return;
12999
13038
  if (element.scaleX * element.scaleY < 0)
13000
13039
  rotation = -rotation;
13001
- this.rotateOf(origin, MathHelper.float(rotation, 2));
13040
+ if (e instanceof DragEvent)
13041
+ rotation = dragStartData.rotation + rotation - element.rotation;
13042
+ rotation = MathHelper.float(MathHelper.getGapRotation(rotation, rotateGap, element.rotation), 2);
13043
+ if (!rotation)
13044
+ return;
13045
+ this.rotateOf(origin, rotation);
13002
13046
  }
13003
13047
  onSkew(e) {
13004
13048
  const { element } = this;
@@ -13015,7 +13059,9 @@ class Editor extends Group {
13015
13059
  const world = element.getWorldPointByLocal(typeof x === 'object' ? Object.assign({}, x) : { x, y }, null, true);
13016
13060
  if (this.multiple)
13017
13061
  element.safeChange(() => element.move(x, y));
13018
- const event = new EditorMoveEvent(EditorMoveEvent.MOVE, { target: element, editor: this, moveX: world.x, moveY: world.y });
13062
+ const data = { target: element, editor: this, moveX: world.x, moveY: world.y };
13063
+ this.emitEvent(new EditorMoveEvent(EditorMoveEvent.BEFORE_MOVE, data));
13064
+ const event = new EditorMoveEvent(EditorMoveEvent.MOVE, data);
13019
13065
  this.editTool.onMove(event);
13020
13066
  this.emitEvent(event);
13021
13067
  }
@@ -13023,7 +13069,9 @@ class Editor extends Group {
13023
13069
  if (!this.checkTransform('resizeable'))
13024
13070
  return;
13025
13071
  const { element } = this;
13026
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, Object.assign(Object.assign({}, data), { target: element, editor: this, worldOrigin: element.getWorldPoint(data.origin) }));
13072
+ data = Object.assign(Object.assign({}, data), { target: element, editor: this, worldOrigin: element.getWorldPoint(data.origin) });
13073
+ this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data));
13074
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data);
13027
13075
  this.editTool.onScaleWithDrag(event);
13028
13076
  this.emitEvent(event);
13029
13077
  }
@@ -13033,7 +13081,9 @@ class Editor extends Group {
13033
13081
  const { element } = this;
13034
13082
  const worldOrigin = this.getWorldOrigin(origin);
13035
13083
  const transform = this.multiple && this.getChangedTransform(() => element.safeChange(() => element.scaleOf(origin, scaleX, scaleY)));
13036
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform });
13084
+ const data = { target: element, editor: this, worldOrigin, scaleX, scaleY, transform };
13085
+ this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data));
13086
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data);
13037
13087
  this.editTool.onScale(event);
13038
13088
  this.emitEvent(event);
13039
13089
  }
@@ -13043,7 +13093,9 @@ class Editor extends Group {
13043
13093
  const { element } = this;
13044
13094
  const worldOrigin = this.getWorldOrigin('center');
13045
13095
  const transform = this.multiple ? this.getChangedTransform(() => element.safeChange(() => element.flip(axis))) : new Matrix(LeafHelper.getFlipTransform(element, axis));
13046
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform });
13096
+ const data = { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform };
13097
+ this.emitEvent(new EditorScaleEvent(EditorScaleEvent.BEFORE_SCALE, data));
13098
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, data);
13047
13099
  this.editTool.onScale(event);
13048
13100
  this.emitEvent(event);
13049
13101
  }
@@ -13053,7 +13105,9 @@ class Editor extends Group {
13053
13105
  const { element } = this;
13054
13106
  const worldOrigin = this.getWorldOrigin(origin);
13055
13107
  const transform = this.multiple && this.getChangedTransform(() => element.safeChange(() => element.rotateOf(origin, rotation)));
13056
- const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation, transform });
13108
+ const data = { target: element, editor: this, worldOrigin, rotation, transform };
13109
+ this.emitEvent(new EditorRotateEvent(EditorRotateEvent.BEFORE_ROTATE, data));
13110
+ const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, data);
13057
13111
  this.editTool.onRotate(event);
13058
13112
  this.emitEvent(event);
13059
13113
  }
@@ -13063,7 +13117,9 @@ class Editor extends Group {
13063
13117
  const { element } = this;
13064
13118
  const worldOrigin = this.getWorldOrigin(origin);
13065
13119
  const transform = this.multiple && this.getChangedTransform(() => element.safeChange(() => element.skewOf(origin, skewX, skewY)));
13066
- const event = new EditorSkewEvent(EditorSkewEvent.SKEW, { target: element, editor: this, worldOrigin, skewX, skewY, transform });
13120
+ const data = { target: element, editor: this, worldOrigin, skewX, skewY, transform };
13121
+ this.emitEvent(new EditorSkewEvent(EditorSkewEvent.BEFORE_SKEW, data));
13122
+ const event = new EditorSkewEvent(EditorSkewEvent.SKEW, data);
13067
13123
  this.editTool.onSkew(event);
13068
13124
  this.emitEvent(event);
13069
13125
  }
@@ -13081,6 +13137,7 @@ class Editor extends Group {
13081
13137
  }
13082
13138
  group(userGroup) {
13083
13139
  if (this.multiple) {
13140
+ this.emitGroupEvent(EditorGroupEvent.BEFORE_GROUP);
13084
13141
  this.target = EditorHelper.group(this.list, this.element, userGroup);
13085
13142
  this.emitGroupEvent(EditorGroupEvent.GROUP, this.target);
13086
13143
  }
@@ -13096,11 +13153,13 @@ class Editor extends Group {
13096
13153
  return this.list;
13097
13154
  }
13098
13155
  openGroup(group) {
13156
+ this.emitGroupEvent(EditorGroupEvent.BEFORE_OPEN, group);
13099
13157
  this.openedGroupList.add(group);
13100
13158
  group.hitChildren = true;
13101
13159
  this.emitGroupEvent(EditorGroupEvent.OPEN, group);
13102
13160
  }
13103
13161
  closeGroup(group) {
13162
+ this.emitGroupEvent(EditorGroupEvent.BEFORE_CLOSE, group);
13104
13163
  this.openedGroupList.remove(group);
13105
13164
  group.hitChildren = false;
13106
13165
  this.emitGroupEvent(EditorGroupEvent.CLOSE, group);
@@ -13129,7 +13188,8 @@ class Editor extends Group {
13129
13188
  emitGroupEvent(type, group) {
13130
13189
  const event = new EditorGroupEvent(type, { editTarget: group });
13131
13190
  this.emitEvent(event);
13132
- group.emitEvent(event);
13191
+ if (group)
13192
+ group.emitEvent(event);
13133
13193
  }
13134
13194
  openInnerEditor(target, select) {
13135
13195
  if (target && select)
@@ -13546,16 +13606,14 @@ function scaleResize(leaf, scaleX, scaleY) {
13546
13606
  leaf.height *= scaleY;
13547
13607
  }
13548
13608
  }
13549
- function scaleResizeFontSize(leaf, scaleX, scaleY) {
13550
- const { app } = leaf;
13551
- const editor = app && app.editor;
13609
+ function scaleResizeFontSize(leaf, scaleX, scaleY, direction) {
13552
13610
  let fontScale = scaleX;
13553
- if (editor.editing) {
13611
+ if (direction !== undefined) {
13554
13612
  const layout = leaf.__layout;
13555
13613
  let { width, height } = layout.boxBounds;
13556
13614
  width *= scaleY - scaleX;
13557
13615
  height *= scaleX - scaleY;
13558
- switch (editor.resizeDirection) {
13616
+ switch (direction) {
13559
13617
  case top:
13560
13618
  case bottom:
13561
13619
  fontScale = scaleY;
@@ -13623,8 +13681,9 @@ leaf.resizeHeight = function (height) {
13623
13681
  this.scaleOf(this.__layout.boxBounds, this.__.lockRatio ? scale : 1, scale, true);
13624
13682
  };
13625
13683
  Text.prototype.__scaleResize = function (scaleX, scaleY) {
13626
- if (this.__.resizeFontSize || (this.editConfig && this.editConfig.editSize === 'font-size')) {
13627
- scaleResizeFontSize(this, scaleX, scaleY);
13684
+ const { app, editConfig } = this, editor = app && app.editor, dragPoint = editor && editor.dragPoint;
13685
+ if (this.__.resizeFontSize || (editConfig && editConfig.editSize === 'font-size') || (dragPoint && editor.mergeConfig.editSize === 'font-size')) {
13686
+ scaleResizeFontSize(this, scaleX, scaleY, dragPoint && dragPoint.direction);
13628
13687
  }
13629
13688
  else {
13630
13689
  scaleResize(this, scaleX, scaleY);
@@ -13673,34 +13732,15 @@ Plugin.add('resize');
13673
13732
 
13674
13733
  Plugin.add('editor', 'resize');
13675
13734
  Creator.editor = function (options) { return new Editor(options); };
13676
- dataType(false)(Box.prototype, 'textBox');
13677
- defineKey(UI.prototype, 'editOuter', {
13678
- get() { return this.__.__isLinePath ? 'LineEditTool' : 'EditTool'; }
13679
- });
13680
- defineKey(UI.prototype, 'editInner', {
13681
- get() { return 'PathEditor'; }
13682
- });
13683
- defineKey(Group.prototype, 'editInner', {
13684
- get() { return ''; }
13685
- });
13686
- defineKey(Text.prototype, 'editInner', {
13687
- get() { return 'TextEditor'; }
13688
- });
13689
- UI.setEditConfig = function (config) {
13690
- defineKey(this.prototype, 'editConfig', {
13691
- get() { return typeof config === 'function' ? config(this) : config; }
13692
- });
13693
- };
13694
- UI.setEditOuter = function (toolName) {
13695
- defineKey(this.prototype, 'editOuter', {
13696
- get() { return typeof toolName === 'string' ? toolName : toolName(this); }
13697
- });
13698
- };
13699
- UI.setEditInner = function (editorName) {
13700
- defineKey(this.prototype, 'editInner', {
13701
- get() { return typeof editorName === 'string' ? editorName : editorName(this); }
13702
- });
13703
- };
13735
+ Box.addAttr('textBox', false, dataType);
13736
+ UI.addAttr('editConfig', undefined, dataType);
13737
+ UI.addAttr('editOuter', (ui) => ui.__.__isLinePath ? 'LineEditTool' : 'EditTool', dataType);
13738
+ UI.addAttr('editInner', 'PathEditor', dataType);
13739
+ Group.addAttr('editInner', '', dataType);
13740
+ Text.addAttr('editInner', 'TextEditor', dataType);
13741
+ UI.setEditConfig = function (config) { this.changeAttr('editConfig', config); };
13742
+ UI.setEditOuter = function (toolName) { this.changeAttr('editOuter', toolName); };
13743
+ UI.setEditInner = function (editorName) { this.changeAttr('editInner', editorName); };
13704
13744
 
13705
13745
  function addViewport(leafer, mergeConfig, custom) {
13706
13746
  addViewportConfig(leafer.parentApp ? leafer.parentApp : leafer, mergeConfig);
@@ -13711,10 +13751,8 @@ function addViewport(leafer, mergeConfig, custom) {
13711
13751
  }), leafer.on_(ZoomEvent.BEFORE_ZOOM, (e) => {
13712
13752
  const { zoomLayer } = leafer;
13713
13753
  const changeScale = leafer.getValidScale(e.scale);
13714
- if (changeScale !== 1) {
13715
- PointHelper.scaleOf(zoomLayer, e, changeScale);
13716
- zoomLayer.scale = zoomLayer.__.scaleX * changeScale;
13717
- }
13754
+ if (changeScale !== 1)
13755
+ zoomLayer.scaleOfWorld(e, changeScale);
13718
13756
  }));
13719
13757
  }
13720
13758
  function addViewportConfig(leafer, mergeConfig) {
@@ -13941,7 +13979,7 @@ leafer.getValidScale = function (changeScale) {
13941
13979
  changeScale = min / scaleX;
13942
13980
  else if (max && absScale > max)
13943
13981
  changeScale = max / scaleX;
13944
- return disabled ? 1 : MathHelper.float(changeScale);
13982
+ return disabled ? 1 : changeScale;
13945
13983
  };
13946
13984
 
13947
13985
  function getMoveEventData(move, event) {
@@ -14082,7 +14120,7 @@ Leafer.prototype.zoom = function (zoomType, padding, fixed, transition) {
14082
14120
  const limitBounds = this.canvas.bounds.clone().shrink(padding !== undefined ? padding : 30), bounds = new Bounds();
14083
14121
  const center = { x: limitBounds.x + limitBounds.width / 2, y: limitBounds.y + limitBounds.height / 2 };
14084
14122
  let changeScale;
14085
- const { scaleX } = this.__;
14123
+ const { x, y, scaleX, scaleY } = zoomLayer.__;
14086
14124
  if (typeof zoomType === 'string') {
14087
14125
  switch (zoomType) {
14088
14126
  case 'in':
@@ -14112,7 +14150,6 @@ Leafer.prototype.zoom = function (zoomType, padding, fixed, transition) {
14112
14150
  zoomLayer.scaleOfWorld(center, changeScale, changeScale, false, transition);
14113
14151
  }
14114
14152
  else if (typeof zoomType === 'object') {
14115
- const { x, y, scaleX, scaleY } = zoomLayer;
14116
14153
  const data = { x, y, scaleX, scaleY };
14117
14154
  const isArray = zoomType instanceof Array;
14118
14155
  if (isArray || zoomType.tag) {
@@ -14260,6 +14297,18 @@ Plugin.add('scroll');
14260
14297
  class ArrowData extends LineData {
14261
14298
  }
14262
14299
 
14300
+ function arrowType(defaultValue) {
14301
+ return decorateLeafAttr(defaultValue, (key) => attr({
14302
+ set(value) {
14303
+ if (this.__setAttr(key, value)) {
14304
+ const data = this.__;
14305
+ data.__useArrow = data.startArrow !== 'none' || data.endArrow !== 'none';
14306
+ doStrokeType(this);
14307
+ }
14308
+ }
14309
+ }));
14310
+ }
14311
+
14263
14312
  let Arrow = class Arrow extends Line {
14264
14313
  get __tag() { return 'Arrow'; }
14265
14314
  constructor(data) {
@@ -14271,7 +14320,7 @@ __decorate([
14271
14320
  dataProcessor(ArrowData)
14272
14321
  ], Arrow.prototype, "__", void 0);
14273
14322
  __decorate([
14274
- strokeType('angle')
14323
+ arrowType('angle')
14275
14324
  ], Arrow.prototype, "endArrow", void 0);
14276
14325
  Arrow = __decorate([
14277
14326
  registerUI()
@@ -14504,22 +14553,9 @@ function setPoint$1(data, point, startIndex) {
14504
14553
  data[startIndex + 1] = point.y;
14505
14554
  }
14506
14555
 
14507
- function arrowType(defaultValue) {
14508
- return decorateLeafAttr(defaultValue, (key) => attr({
14509
- set(value) {
14510
- if (this.__setAttr(key, value)) {
14511
- const data = this.__;
14512
- data.__useArrow = data.startArrow !== 'none' || data.endArrow !== 'none';
14513
- doStrokeType(this);
14514
- }
14515
- }
14516
- }));
14517
- }
14518
-
14519
14556
  Plugin.add('arrow');
14520
- const ui$1 = UI.prototype;
14521
- arrowType('none')(ui$1, 'startArrow');
14522
- arrowType('none')(ui$1, 'endArrow');
14557
+ UI.addAttr('startArrow', 'none', arrowType);
14558
+ UI.addAttr('endArrow', 'none', arrowType);
14523
14559
  Object.assign(PathArrow, PathArrowModule);
14524
14560
 
14525
14561
  const { Yes, NoAndSkip, YesAndSkip } = Answer;
@@ -14687,124 +14723,134 @@ function getTrimBounds(canvas) {
14687
14723
  }
14688
14724
 
14689
14725
  const ExportModule = {
14690
- export(leaf, filename, options) {
14726
+ syncExport(leaf, filename, options) {
14691
14727
  this.running = true;
14728
+ let result;
14692
14729
  const fileType = FileHelper.fileType(filename);
14693
14730
  const isDownload = filename.includes('.');
14694
14731
  options = FileHelper.getExportOptions(options);
14695
- return addTask((success) => new Promise((resolve) => {
14696
- const over = (result) => {
14697
- success(result);
14698
- resolve();
14699
- this.running = false;
14700
- };
14701
- const { toURL } = Platform;
14702
- const { download } = Platform.origin;
14703
- if (fileType === 'json') {
14704
- isDownload && download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
14705
- return over({ data: isDownload ? true : leaf.toJSON(options.json) });
14706
- }
14707
- if (fileType === 'svg') {
14708
- isDownload && download(toURL(leaf.toSVG(), 'svg'), filename);
14709
- return over({ data: isDownload ? true : leaf.toSVG() });
14732
+ const { toURL } = Platform;
14733
+ const { download } = Platform.origin;
14734
+ if (fileType === 'json') {
14735
+ isDownload && download(toURL(JSON.stringify(leaf.toJSON(options.json)), 'text'), filename);
14736
+ result = { data: isDownload ? true : leaf.toJSON(options.json) };
14737
+ }
14738
+ else if (fileType === 'svg') {
14739
+ isDownload && download(toURL(leaf.toSVG(), 'svg'), filename);
14740
+ result = { data: isDownload ? true : leaf.toSVG() };
14741
+ }
14742
+ else {
14743
+ let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
14744
+ const { worldTransform, isLeafer, leafer, isFrame } = leaf;
14745
+ const { slice, trim, padding, onCanvas } = options;
14746
+ const smooth = options.smooth === undefined ? (leafer ? leafer.config.smooth : true) : options.smooth;
14747
+ const contextSettings = options.contextSettings || (leafer ? leafer.config.contextSettings : undefined);
14748
+ const screenshot = options.screenshot || leaf.isApp;
14749
+ const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
14750
+ const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
14751
+ if (screenshot) {
14752
+ renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
14710
14753
  }
14711
- const { leafer } = leaf;
14712
- if (leafer) {
14713
- checkLazy(leaf);
14714
- leafer.waitViewCompleted(() => __awaiter(this, void 0, void 0, function* () {
14715
- let renderBounds, trimBounds, scaleX = 1, scaleY = 1;
14716
- const { worldTransform, isLeafer, isFrame } = leaf;
14717
- const { slice, trim, padding, onCanvas } = options;
14718
- const smooth = options.smooth === undefined ? leafer.config.smooth : options.smooth;
14719
- const contextSettings = options.contextSettings || leafer.config.contextSettings;
14720
- const screenshot = options.screenshot || leaf.isApp;
14721
- const fill = (isLeafer && screenshot) ? (options.fill === undefined ? leaf.fill : options.fill) : options.fill;
14722
- const needFill = FileHelper.isOpaqueImage(filename) || fill, matrix = new Matrix();
14723
- if (screenshot) {
14724
- renderBounds = screenshot === true ? (isLeafer ? leafer.canvas.bounds : leaf.worldRenderBounds) : screenshot;
14725
- }
14726
- else {
14727
- let relative = options.relative || (isLeafer ? 'inner' : 'local');
14728
- scaleX = worldTransform.scaleX;
14729
- scaleY = worldTransform.scaleY;
14730
- switch (relative) {
14731
- case 'inner':
14732
- matrix.set(worldTransform);
14733
- break;
14734
- case 'local':
14735
- matrix.set(worldTransform).divide(leaf.localTransform);
14736
- scaleX /= leaf.scaleX;
14737
- scaleY /= leaf.scaleY;
14738
- break;
14739
- case 'world':
14740
- scaleX = 1;
14741
- scaleY = 1;
14742
- break;
14743
- case 'page':
14744
- relative = leaf.leafer;
14745
- default:
14746
- matrix.set(worldTransform).divide(leaf.getTransform(relative));
14747
- const l = relative.worldTransform;
14748
- scaleX /= scaleX / l.scaleX;
14749
- scaleY /= scaleY / l.scaleY;
14750
- }
14751
- renderBounds = leaf.getBounds('render', relative);
14752
- }
14753
- const scaleData = { scaleX: 1, scaleY: 1 };
14754
- MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData);
14755
- let pixelRatio = options.pixelRatio || 1;
14756
- if (leaf.isApp) {
14757
- scaleData.scaleX *= pixelRatio;
14758
- scaleData.scaleY *= pixelRatio;
14759
- pixelRatio = leaf.app.pixelRatio;
14760
- }
14761
- const { x, y, width, height } = new Bounds(renderBounds).scale(scaleData.scaleX, scaleData.scaleY);
14762
- const renderOptions = { matrix: matrix.scale(1 / scaleData.scaleX, 1 / scaleData.scaleY).invert().translate(-x, -y).withScale(1 / scaleX * scaleData.scaleX, 1 / scaleY * scaleData.scaleY) };
14763
- let canvas = Creator.canvas({ width: Math.round(width), height: Math.round(height), pixelRatio, smooth, contextSettings });
14764
- let sliceLeaf;
14765
- if (slice) {
14766
- sliceLeaf = leaf;
14767
- sliceLeaf.__worldOpacity = 0;
14768
- leaf = leafer;
14769
- renderOptions.bounds = canvas.bounds;
14770
- }
14771
- canvas.save();
14772
- if (isFrame && fill !== undefined) {
14773
- const oldFill = leaf.get('fill');
14774
- leaf.fill = '';
14775
- leaf.__render(canvas, renderOptions);
14776
- leaf.fill = oldFill;
14777
- }
14778
- else {
14779
- leaf.__render(canvas, renderOptions);
14780
- }
14781
- canvas.restore();
14782
- if (sliceLeaf)
14783
- sliceLeaf.__updateWorldOpacity();
14784
- if (trim) {
14785
- trimBounds = getTrimBounds(canvas);
14786
- const old = canvas, { width, height } = trimBounds;
14787
- const config = { x: 0, y: 0, width, height, pixelRatio };
14788
- canvas = Creator.canvas(config);
14789
- canvas.copyWorld(old, trimBounds, config);
14790
- }
14791
- if (padding) {
14792
- const [top, right, bottom, left] = MathHelper.fourNumber(padding);
14793
- const old = canvas, { width, height } = old;
14794
- canvas = Creator.canvas({ width: width + left + right, height: height + top + bottom, pixelRatio });
14795
- canvas.copyWorld(old, old.bounds, { x: left, y: top, width, height });
14796
- }
14797
- if (needFill)
14798
- canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
14799
- if (onCanvas)
14800
- onCanvas(canvas);
14801
- const data = filename === 'canvas' ? canvas : yield canvas.export(filename, options);
14802
- over({ data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds });
14803
- }));
14754
+ else {
14755
+ let relative = options.relative || (isLeafer ? 'inner' : 'local');
14756
+ scaleX = worldTransform.scaleX;
14757
+ scaleY = worldTransform.scaleY;
14758
+ switch (relative) {
14759
+ case 'inner':
14760
+ matrix.set(worldTransform);
14761
+ break;
14762
+ case 'local':
14763
+ matrix.set(worldTransform).divide(leaf.localTransform);
14764
+ scaleX /= leaf.scaleX;
14765
+ scaleY /= leaf.scaleY;
14766
+ break;
14767
+ case 'world':
14768
+ scaleX = 1;
14769
+ scaleY = 1;
14770
+ break;
14771
+ case 'page':
14772
+ relative = leafer || leaf;
14773
+ default:
14774
+ matrix.set(worldTransform).divide(leaf.getTransform(relative));
14775
+ const l = relative.worldTransform;
14776
+ scaleX /= scaleX / l.scaleX;
14777
+ scaleY /= scaleY / l.scaleY;
14778
+ }
14779
+ renderBounds = leaf.getBounds('render', relative);
14780
+ }
14781
+ const scaleData = { scaleX: 1, scaleY: 1 };
14782
+ MathHelper.getScaleData(options.scale, options.size, renderBounds, scaleData);
14783
+ let pixelRatio = options.pixelRatio || 1;
14784
+ if (leaf.isApp) {
14785
+ scaleData.scaleX *= pixelRatio;
14786
+ scaleData.scaleY *= pixelRatio;
14787
+ pixelRatio = leaf.app.pixelRatio;
14788
+ }
14789
+ const { x, y, width, height } = new Bounds(renderBounds).scale(scaleData.scaleX, scaleData.scaleY);
14790
+ const renderOptions = { matrix: matrix.scale(1 / scaleData.scaleX, 1 / scaleData.scaleY).invert().translate(-x, -y).withScale(1 / scaleX * scaleData.scaleX, 1 / scaleY * scaleData.scaleY) };
14791
+ let canvas = Creator.canvas({ width: Math.floor(width), height: Math.floor(height), pixelRatio, smooth, contextSettings });
14792
+ let sliceLeaf;
14793
+ if (slice) {
14794
+ sliceLeaf = leaf;
14795
+ sliceLeaf.__worldOpacity = 0;
14796
+ leaf = leafer || leaf;
14797
+ renderOptions.bounds = canvas.bounds;
14798
+ }
14799
+ canvas.save();
14800
+ if (isFrame && fill !== undefined) {
14801
+ const oldFill = leaf.get('fill');
14802
+ leaf.fill = '';
14803
+ leaf.__render(canvas, renderOptions);
14804
+ leaf.fill = oldFill;
14804
14805
  }
14805
14806
  else {
14806
- over({ data: false });
14807
+ leaf.__render(canvas, renderOptions);
14808
+ }
14809
+ canvas.restore();
14810
+ if (sliceLeaf)
14811
+ sliceLeaf.__updateWorldOpacity();
14812
+ if (trim) {
14813
+ trimBounds = getTrimBounds(canvas);
14814
+ const old = canvas, { width, height } = trimBounds;
14815
+ const config = { x: 0, y: 0, width, height, pixelRatio };
14816
+ canvas = Creator.canvas(config);
14817
+ canvas.copyWorld(old, trimBounds, config);
14807
14818
  }
14819
+ if (padding) {
14820
+ const [top, right, bottom, left] = MathHelper.fourNumber(padding);
14821
+ const old = canvas, { width, height } = old;
14822
+ canvas = Creator.canvas({ width: width + left + right, height: height + top + bottom, pixelRatio });
14823
+ canvas.copyWorld(old, old.bounds, { x: left, y: top, width, height });
14824
+ }
14825
+ if (needFill)
14826
+ canvas.fillWorld(canvas.bounds, fill || '#FFFFFF', 'destination-over');
14827
+ if (onCanvas)
14828
+ onCanvas(canvas);
14829
+ const data = filename === 'canvas' ? canvas : canvas.export(filename, options);
14830
+ result = { data, width: canvas.pixelWidth, height: canvas.pixelHeight, renderBounds, trimBounds };
14831
+ }
14832
+ this.running = false;
14833
+ return result;
14834
+ },
14835
+ export(leaf, filename, options) {
14836
+ this.running = true;
14837
+ return addTask((success) => new Promise((resolve) => {
14838
+ const getResult = () => __awaiter(this, void 0, void 0, function* () {
14839
+ if (!Resource.isComplete)
14840
+ return Platform.requestRender(getResult);
14841
+ const result = ExportModule.syncExport(leaf, filename, options);
14842
+ if (result.data instanceof Promise)
14843
+ result.data = yield result.data;
14844
+ success(result);
14845
+ resolve();
14846
+ });
14847
+ leaf.updateLayout();
14848
+ checkLazy(leaf);
14849
+ const { leafer } = leaf;
14850
+ if (leafer)
14851
+ leafer.waitViewCompleted(getResult);
14852
+ else
14853
+ getResult();
14808
14854
  }));
14809
14855
  }
14810
14856
  };
@@ -14863,6 +14909,9 @@ Object.assign(Export, ExportModule);
14863
14909
  UI.prototype.export = function (filename, options) {
14864
14910
  return Export.export(this, filename, options);
14865
14911
  };
14912
+ UI.prototype.syncExport = function (filename, options) {
14913
+ return Export.syncExport(this, filename, options);
14914
+ };
14866
14915
 
14867
14916
  const textCaseMap = {
14868
14917
  'none': 'none',
@@ -14971,10 +15020,10 @@ let TextEditor = class TextEditor extends InnerEditor {
14971
15020
  this.onFocus = this.onFocus.bind(this);
14972
15021
  this.onInput = this.onInput.bind(this);
14973
15022
  this.onUpdate = this.onUpdate.bind(this);
14974
- this.onEscape = this.onEscape.bind(this);
15023
+ this.onKeydown = this.onKeydown.bind(this);
14975
15024
  div.addEventListener("focus", this.onFocus);
14976
15025
  div.addEventListener("input", this.onInput);
14977
- window.addEventListener('keydown', this.onEscape);
15026
+ window.addEventListener('keydown', this.onKeydown);
14978
15027
  window.addEventListener('scroll', this.onUpdate);
14979
15028
  const selection = window.getSelection();
14980
15029
  const range = document.createRange();
@@ -14992,14 +15041,25 @@ let TextEditor = class TextEditor extends InnerEditor {
14992
15041
  }
14993
15042
  onInput() {
14994
15043
  const { editDom } = this;
14995
- this.editTarget.text = this.isHTMLText ? editDom.innerHTML : editDom.innerText.replace(/\n\n/, '\n');
15044
+ this.editTarget.text = this.isHTMLText ? editDom.innerHTML : editDom.innerText;
14996
15045
  }
14997
15046
  onFocus() {
14998
15047
  this.editDom.style.outline = 'none';
14999
15048
  }
15000
- onEscape(e) {
15049
+ onKeydown(e) {
15001
15050
  if (e.code === 'Escape')
15002
15051
  this.editor.closeInnerEditor();
15052
+ if (e.key === 'Enter') {
15053
+ e.preventDefault();
15054
+ const br = document.createElement('br');
15055
+ const selection = window.getSelection();
15056
+ const range = selection.getRangeAt(0);
15057
+ range.deleteContents();
15058
+ range.insertNode(br);
15059
+ range.setStartAfter(br);
15060
+ range.setEndAfter(br);
15061
+ this.onInput();
15062
+ }
15003
15063
  }
15004
15064
  onUpdate() {
15005
15065
  const { editTarget: text } = this;
@@ -15055,7 +15115,7 @@ let TextEditor = class TextEditor extends InnerEditor {
15055
15115
  editor.off_(this.eventIds);
15056
15116
  dom.removeEventListener("focus", this.onFocus);
15057
15117
  dom.removeEventListener("input", this.onInput);
15058
- window.removeEventListener('keydown', this.onEscape);
15118
+ window.removeEventListener('keydown', this.onKeydown);
15059
15119
  window.removeEventListener('scroll', this.onUpdate);
15060
15120
  dom.remove();
15061
15121
  this.editDom = this.eventIds = undefined;
@@ -15077,7 +15137,6 @@ class HTMLTextData extends ImageData {
15077
15137
 
15078
15138
  let HTMLText = class HTMLText extends Image {
15079
15139
  get __tag() { return 'HTMLText'; }
15080
- get editInner() { return 'TextEditor'; }
15081
15140
  constructor(data) {
15082
15141
  super(data);
15083
15142
  }
@@ -15122,6 +15181,9 @@ __decorate([
15122
15181
  __decorate([
15123
15182
  boundsType('')
15124
15183
  ], HTMLText.prototype, "text", void 0);
15184
+ __decorate([
15185
+ dataType('TextEditor')
15186
+ ], HTMLText.prototype, "editInner", void 0);
15125
15187
  HTMLText = __decorate([
15126
15188
  registerUI()
15127
15189
  ], HTMLText);