mce 0.14.4 → 0.15.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { Node as Node$1, Element2D, Timeline, Engine, Camera2D, DrawboardEffect, IN_BROWSER, clamp, assets, TimelineNode, Transform2D, DEG_TO_RAD, render, customNodes, Animation, IN_MAC_OS } from "modern-canvas";
2
- import { reactive, computed, watch, markRaw, ref, warn, shallowRef, onBeforeUnmount, defineComponent, createElementBlock, createCommentVNode, unref, openBlock, normalizeStyle, toDisplayString, createVNode, useAttrs, createBlock, resolveDynamicComponent, normalizeClass, mergeProps, createElementVNode, inject, toValue, getCurrentInstance, provide, readonly, toRef, onMounted, useId, onDeactivated, onActivated, onScopeDispose, useModel, useTemplateRef, withDirectives, vShow, vModelText, nextTick, Fragment, renderList, renderSlot, mergeModels, resolveComponent, withCtx, withModifiers, Teleport, createTextVNode, createSlots, normalizeProps, guardReactiveProps, onBeforeMount, h, isRef, useSlots } from "vue";
1
+ import { Node as Node$1, Element2D, Timeline, Engine, Camera2D, DrawboardEffect, IN_BROWSER, clamp, assets, TimelineNode, Transform2D, Obb2D, Aabb2D, render, Vector2 as Vector2$1, customNodes, Animation, IN_MAC_OS } from "modern-canvas";
2
+ import { reactive, computed, watch, markRaw, ref, warn, shallowRef, onBeforeUnmount, defineComponent, createElementBlock, createCommentVNode, unref, openBlock, normalizeStyle, toDisplayString, createVNode, useAttrs, createBlock, resolveDynamicComponent, normalizeClass, mergeProps, createElementVNode, inject, toValue, getCurrentInstance, provide, useId, readonly, toRef, onMounted, onDeactivated, onActivated, onScopeDispose, useModel, useTemplateRef, withDirectives, vShow, vModelText, nextTick, Fragment, renderList, renderSlot, mergeModels, resolveComponent, withModifiers, withCtx, Teleport, createTextVNode, createSlots, normalizeProps, guardReactiveProps, onBeforeMount, h, isRef, useSlots } from "vue";
3
3
  import { useFileDialog, useEventListener, isClient, onClickOutside, useDebounceFn, useResizeObserver as useResizeObserver$1, useLocalStorage, useImage } from "@vueuse/core";
4
- import { getObjectValueByPath, setObjectValueByPath, Observable, Reactivable, idGenerator, property, normalizeElement, normalizeTextContent, normalizeCRLF, isEqualObject } from "modern-idoc";
4
+ import { getObjectValueByPath, setObjectValueByPath, Observable, Reactivable, idGenerator, property, normalizeTextContent, normalizeCRLF, isEqualObject } from "modern-idoc";
5
5
  import { saveAs } from "file-saver";
6
6
  import { Fonts } from "modern-font";
7
7
  import * as Y from "yjs";
@@ -495,58 +495,13 @@ var __decorateClass = (decorators, target, key, kind) => {
495
495
  if (result) __defProp(target, key, result);
496
496
  return result;
497
497
  };
498
- function initYElement(yMap, element = {}, parentId, regenId = false) {
499
- const normalized = normalizeElement({
500
- ...element,
501
- id: regenId ? void 0 : element.id,
502
- meta: {
503
- inCanvasIs: "Element2D",
504
- ...element?.meta ?? {}
505
- }
506
- });
507
- const id = normalized.id;
508
- const yChildrenIds = new Y.Array();
509
- for (const key in normalized) {
510
- yMap.set(key, normalized[key]);
511
- }
512
- yMap.set("id", id);
513
- yMap.set("parentId", parentId);
514
- yMap.set("name", normalized.name ?? id);
515
- yMap.set("childrenIds", yChildrenIds);
516
- yMap.set("meta", new Y.Map(Object.entries(normalized.meta ?? {})));
517
- const inCanvasIs = normalized?.meta?.inCanvasIs;
518
- if (inCanvasIs === "Element2D" || inCanvasIs === "Lottie2D") {
519
- yMap.set("style", new Y.Map(Object.entries(normalized.style ?? {})));
520
- yMap.set("background", new Y.Map(Object.entries(normalized.background ?? {})));
521
- yMap.set("shape", new Y.Map(Object.entries(normalized.shape ?? {})));
522
- yMap.set("fill", new Y.Map(Object.entries(normalized.fill ?? {})));
523
- yMap.set("outline", new Y.Map(Object.entries(normalized.outline ?? {})));
524
- yMap.set("text", new Y.Map(Object.entries(normalized.text ?? {})));
525
- yMap.set("foreground", new Y.Map(Object.entries(normalized.foreground ?? {})));
526
- yMap.set("shadow", new Y.Map(Object.entries(normalized.shadow ?? {})));
527
- }
528
- return {
529
- normalized,
530
- yChildrenIds
531
- };
532
- }
533
- function iElementToYNodes(element, parentId, regenId = false) {
534
- const results = [];
535
- const yNode = new Y.Map();
536
- const { normalized, yChildrenIds } = initYElement(yNode, element, parentId, regenId);
537
- const id = normalized.id;
538
- results.push({ id, node: yNode });
539
- normalized.children?.forEach((iChild) => {
540
- const result = iElementToYNodes(iChild, id, regenId);
541
- yChildrenIds.push([result[0].id]);
542
- results.push(...result);
543
- });
544
- return results;
545
- }
546
498
  class Doc extends Model {
547
499
  _yChildren;
548
500
  _yChildrenIds;
549
- root = reactive(new Node$1());
501
+ root = reactive(new Node$1({
502
+ id: "root",
503
+ name: "Doc"
504
+ }));
550
505
  _nodeMap = /* @__PURE__ */ new Map();
551
506
  get meta() {
552
507
  return this.root.meta;
@@ -562,6 +517,8 @@ class Doc extends Model {
562
517
  this._yChildren,
563
518
  this._yChildrenIds
564
519
  ]);
520
+ this._yProps.set("id", this.root.id);
521
+ this._yProps.set("name", this.root.name);
565
522
  }
566
523
  setProperties(properties) {
567
524
  if (properties) {
@@ -578,20 +535,13 @@ class Doc extends Model {
578
535
  }
579
536
  async load(initFn) {
580
537
  return super.load(async () => {
538
+ this._proxyNode(
539
+ this.root,
540
+ this._yProps,
541
+ this._yChildrenIds
542
+ );
543
+ this._yChildren.observe(this._yChildrenChange.bind(this));
581
544
  await initFn?.();
582
- this._proxyProps(this.root, this._yProps);
583
- const meta = this._yProps.get("meta");
584
- if (meta) {
585
- this._proxyProps(this.root.meta, meta, true);
586
- }
587
- this._proxyChildren(this.root, this._yChildrenIds);
588
- this._yChildrenIds.forEach((id) => {
589
- const yNode = this._yChildren.get(id);
590
- if (yNode) {
591
- this._getOrCreateNode(yNode);
592
- }
593
- });
594
- this._yChildren.observe(this._onChildrenChange.bind(this));
595
545
  });
596
546
  }
597
547
  _isSelfTransaction(transaction) {
@@ -599,11 +549,11 @@ class Doc extends Model {
599
549
  }
600
550
  _debug(..._args) {
601
551
  }
602
- _onChildrenChange(event, transaction) {
552
+ _yChildrenChange(event, transaction) {
603
553
  if (this._isSelfTransaction(transaction)) {
604
554
  return;
605
555
  }
606
- this._debug("_onChildrenChange", event);
556
+ this._debug("yChildrenChange", event);
607
557
  const { keysChanged, changes } = event;
608
558
  keysChanged.forEach((key) => {
609
559
  const change = changes.keys.get(key);
@@ -611,7 +561,7 @@ class Doc extends Model {
611
561
  switch (change?.action) {
612
562
  case "add":
613
563
  if (yNode) {
614
- this._getOrCreateNode(yNode);
564
+ this._initYNode(yNode);
615
565
  }
616
566
  break;
617
567
  case "delete":
@@ -623,6 +573,7 @@ class Doc extends Model {
623
573
  }
624
574
  reset() {
625
575
  super.reset();
576
+ this.root.resetProperties();
626
577
  this._yChildren.clear();
627
578
  this._yChildrenIds.delete(0, this._yChildrenIds.length);
628
579
  this._nodeMap.clear();
@@ -630,92 +581,57 @@ class Doc extends Model {
630
581
  this.indexeddb?.clearData();
631
582
  return this;
632
583
  }
633
- _addNode(node, options = {}) {
584
+ _addNode(data, options = {}) {
634
585
  const { parentId, index, regenId } = options;
635
- const yNodes = iElementToYNodes(node, parentId, regenId);
636
- yNodes.forEach((result) => this._yChildren.set(result.id, result.node));
637
- const _nodeMap = yNodes.map((result) => this._getOrCreateNode(result.node));
638
- const first = _nodeMap[0];
639
586
  let parent;
640
- let childrenIds;
641
587
  if (parentId && parentId !== this.root.id) {
642
- parent = this._nodeMap.get(parentId);
643
- childrenIds = this._yChildren.get(parentId)?.get("childrenIds");
588
+ parent = this._nodeMap.get(parentId) ?? this.root;
644
589
  } else {
645
590
  parent = this.root;
646
- childrenIds = this._yChildrenIds;
647
591
  }
648
- if (parent && childrenIds) {
649
- if (index === void 0) {
650
- childrenIds.push([first.id]);
651
- parent.appendChild(first);
652
- } else {
653
- childrenIds.insert(index, [first.id]);
654
- parent.moveChild(first, index);
592
+ const value = {
593
+ ...data,
594
+ meta: {
595
+ inCanvasIs: "Element2D",
596
+ ...data?.meta ?? {}
655
597
  }
598
+ };
599
+ if (regenId) {
600
+ delete value.id;
601
+ }
602
+ const node = reactive(Node$1.parse(value));
603
+ if (index === void 0) {
604
+ parent.appendChild(node);
605
+ } else {
606
+ parent.moveChild(node, index);
656
607
  }
657
- return first;
608
+ this._proxyNode(node);
609
+ return node;
658
610
  }
659
- addNode(node, options) {
660
- return this.transact(() => this._addNode(node, options));
611
+ addNode(data, options) {
612
+ return this.transact(() => this._addNode(data, options));
661
613
  }
662
- addNodes(nodes, options) {
663
- return this.transact(() => nodes.map((element) => this._addNode(element, options)));
614
+ addNodes(dataItems, options) {
615
+ return this.transact(() => dataItems.map((data) => this._addNode(data, options)));
664
616
  }
665
617
  set(source) {
666
- const { children = [], meta = {}, ...props } = source;
618
+ const { children = [], meta = {}, ..._props } = source;
619
+ const props = {
620
+ id: this.root.id,
621
+ name: this.root.name,
622
+ ..._props
623
+ };
667
624
  this.reset();
668
- this.addNodes(children);
669
625
  this.setProperties(props);
670
626
  this._yProps.clear();
671
627
  for (const key in props) {
672
628
  this._yProps.set(key, props[key]);
673
629
  }
674
630
  this._yProps.set("meta", new Y.Map(Object.entries(meta)));
631
+ this._transacting = true;
632
+ this.addNodes(children);
675
633
  return this;
676
634
  }
677
- _deleteNode(id) {
678
- const node = this._nodeMap.get(id);
679
- const yNode = this._yChildren.get(id);
680
- if (!yNode || !node) {
681
- return;
682
- }
683
- const parentId = yNode.get("parentId");
684
- const parentChildrenIds = parentId ? this._yChildren.get(parentId)?.get("childrenIds") : this._yChildrenIds;
685
- if (parentChildrenIds) {
686
- const index = parentChildrenIds.toJSON().indexOf(id);
687
- if (index > -1) {
688
- parentChildrenIds.delete(index);
689
- }
690
- }
691
- yNode.get("childrenIds").forEach((id2) => this._deleteNode(id2));
692
- node.remove();
693
- }
694
- deleteNode(id) {
695
- this.transact(() => this._deleteNode(id));
696
- }
697
- getNode(id) {
698
- return this._nodeMap.get(id);
699
- }
700
- moveNode(id, toIndex) {
701
- const node = this._nodeMap.get(id);
702
- if (!node) {
703
- return;
704
- }
705
- const parent = node.parent;
706
- const childrenIds = parent?.id ? this._yChildren.get(parent.id)?.get("childrenIds") : this._yChildrenIds;
707
- if (!childrenIds) {
708
- return;
709
- }
710
- const fromIndex = childrenIds.toJSON().indexOf(id);
711
- childrenIds.delete(fromIndex, 1);
712
- childrenIds.insert(toIndex, [id]);
713
- if (parent && !parent.equal(this.root)) {
714
- parent.moveChild(node, toIndex);
715
- } else {
716
- this.root.moveChild(node, toIndex);
717
- }
718
- }
719
635
  _proxyProps(obj, yMap, isMeta = false) {
720
636
  const accessor = {
721
637
  getProperty: (key) => yMap.doc ? yMap.get(key) : void 0,
@@ -775,45 +691,80 @@ class Doc extends Model {
775
691
  yMap.observe(observeFn);
776
692
  }
777
693
  _proxyChildren(node, childrenIds) {
778
- childrenIds.forEach((id) => {
779
- const child = this._yChildren.get(id);
780
- if (child) {
781
- node.appendChild(this._getOrCreateNode(child));
694
+ node.on("addChild", (child, newIndex) => {
695
+ if (this._transacting === false) {
696
+ return;
782
697
  }
698
+ this.transact(() => {
699
+ childrenIds.insert(newIndex, [child.id]);
700
+ this._debug(`addChild ${child.id}`, child.name, newIndex);
701
+ });
783
702
  });
784
- const observeFn = (event, transaction) => {
785
- if (this._isSelfTransaction(transaction)) {
703
+ node.on("removeChild", (child, oldIndex) => {
704
+ if (this._transacting === false) {
786
705
  return;
787
706
  }
788
- this._debug("_proxyChildren", event, node);
789
- const children = node.children;
707
+ this.transact(() => {
708
+ const index = childrenIds.toJSON().indexOf(child.id);
709
+ if (index > -1) {
710
+ childrenIds.delete(index, 1);
711
+ }
712
+ this._debug(`removeChild ${child.id}`, child.name, oldIndex);
713
+ });
714
+ });
715
+ node.children.forEach((child) => {
716
+ this._proxyNode(child);
717
+ });
718
+ const cachedChildrenIds = childrenIds.toArray();
719
+ const observeFn = (event, transaction) => {
720
+ const skip = this._isSelfTransaction(transaction);
721
+ this._debug(`yChildren ${node.id} changes`, event.changes.delta);
790
722
  let retain = 0;
791
723
  event.changes.delta.forEach((action) => {
792
724
  if (action.retain !== void 0) {
793
725
  retain += action.retain;
794
726
  }
795
727
  if (action.delete) {
796
- for (let i = retain; i < retain + action.delete; i++) {
797
- children[i]?.remove();
728
+ if (!skip) {
729
+ for (let i = retain; i < retain + action.delete; i++) {
730
+ const id = cachedChildrenIds[i];
731
+ if (!id) {
732
+ continue;
733
+ }
734
+ const child = this._nodeMap.get(id);
735
+ if (child && child.parent?.equal(node) && child.getIndex() === i) {
736
+ this.transact(() => {
737
+ child.remove();
738
+ this._debug(`yChildren remove ${child.id}`, child.name, i);
739
+ }, false);
740
+ }
741
+ }
798
742
  }
743
+ cachedChildrenIds.splice(retain, action.delete);
799
744
  }
800
745
  if (action.insert) {
801
- const ids = Array.isArray(action.insert) ? action.insert : [action.insert];
802
- ids.forEach((id, index) => {
803
- let child = this._nodeMap.get(id);
804
- const cb = (child2) => {
805
- node.moveChild(child2, retain + index);
806
- };
807
- if (child) {
808
- cb(child);
809
- } else {
810
- setTimeout(() => {
811
- child = this._nodeMap.get(id);
812
- child && cb(child);
813
- }, 0);
814
- }
815
- });
816
- retain += ids.length;
746
+ const insert = Array.isArray(action.insert) ? action.insert : [action.insert];
747
+ if (!skip) {
748
+ insert.forEach((id, index) => {
749
+ let child = this._nodeMap.get(id);
750
+ const cb = (child2) => {
751
+ this.transact(() => {
752
+ node.moveChild(child2, retain + index);
753
+ this._debug(`yChildren insert ${child2.id}`, child2.name, retain + index);
754
+ }, false);
755
+ };
756
+ if (child) {
757
+ cb(child);
758
+ } else {
759
+ setTimeout(() => {
760
+ child = this._nodeMap.get(id);
761
+ child && cb(child);
762
+ }, 0);
763
+ }
764
+ });
765
+ }
766
+ cachedChildrenIds.splice(retain, 0, ...insert);
767
+ retain += insert.length;
817
768
  }
818
769
  });
819
770
  };
@@ -822,35 +773,71 @@ class Doc extends Model {
822
773
  node._childrenIdsObserveFn = markRaw(observeFn);
823
774
  childrenIds.observe(observeFn);
824
775
  }
825
- _proxyNode(node, yEle) {
826
- this._proxyProps(node, yEle);
827
- const meta = yEle.get("meta");
828
- if (meta) {
829
- this._proxyProps(node.meta, meta, true);
776
+ _proxyNode(node, yNode, yChildrenIds) {
777
+ const id = node.id;
778
+ if (!yNode) {
779
+ yNode = this._yChildren.get(id);
830
780
  }
831
- if (node instanceof Element2D) {
832
- [
833
- "style",
834
- "background",
835
- "shape",
836
- "fill",
837
- "outline",
838
- "text",
839
- "foreground",
840
- "shadow"
841
- ].forEach((key) => {
842
- const yMap = yEle.get(key);
843
- if (yMap) {
844
- this._proxyProps(node[key], yMap);
845
- }
781
+ if (!yNode) {
782
+ yNode = new Y.Map(Object.entries({
783
+ ...node.getProperties(),
784
+ id
785
+ }));
786
+ this._yChildren.set(id, yNode);
787
+ this.undoManager.addToScope(yNode);
788
+ }
789
+ if (!this._nodeMap.has(id)) {
790
+ this._nodeMap.set(id, node);
791
+ yNode.set("parentId", node.parent?.id);
792
+ node.on("parented", () => {
793
+ yNode.set("parentId", node.parent?.id);
846
794
  });
847
- node._text = markRaw(node._text);
848
- node.text.update();
849
- node.requestRender();
795
+ node.on("destroy", () => {
796
+ this._nodeMap.delete(node.id);
797
+ this._debug("destroy", node.id);
798
+ });
799
+ this._proxyProps(node, yNode);
800
+ let meta = yNode.get("meta");
801
+ if (!meta || !(meta instanceof Y.Map)) {
802
+ meta = new Y.Map(Object.entries(node.meta.getProperties()));
803
+ yNode.set("meta", meta);
804
+ }
805
+ this._proxyProps(node.meta, meta, true);
806
+ if (node instanceof Element2D) {
807
+ [
808
+ "style",
809
+ "background",
810
+ "shape",
811
+ "fill",
812
+ "outline",
813
+ "text",
814
+ "foreground",
815
+ "shadow"
816
+ ].forEach((key) => {
817
+ let yMap = yNode.get(key);
818
+ if (!yMap || !(yMap instanceof Y.Map)) {
819
+ yMap = new Y.Map(Object.entries(node[key].getProperties()));
820
+ yNode.set(key, yMap);
821
+ }
822
+ this._proxyProps(node[key], yMap);
823
+ });
824
+ node._text = markRaw(node._text);
825
+ node.text.update();
826
+ node.requestRender();
827
+ }
828
+ if (!yChildrenIds) {
829
+ yChildrenIds = yNode.get("childrenIds");
830
+ }
831
+ if (!yChildrenIds) {
832
+ yChildrenIds = new Y.Array();
833
+ yChildrenIds.push(node.children.map((c) => c.id));
834
+ yNode.set("childrenIds", yChildrenIds);
835
+ }
836
+ this._proxyChildren(node, yChildrenIds);
850
837
  }
851
- this._proxyChildren(node, yEle.get("childrenIds"));
838
+ return yNode;
852
839
  }
853
- _getOrCreateNode(yNode) {
840
+ _initYNode(yNode) {
854
841
  const id = yNode.get("id");
855
842
  let node = this._nodeMap.get(id);
856
843
  if (!node) {
@@ -875,7 +862,7 @@ class Doc extends Model {
875
862
  }
876
863
  }
877
864
  __decorateClass([
878
- property({ default: "doc" })
865
+ property()
879
866
  ], Doc.prototype, "name");
880
867
  const _0_context = defineMixin((editor) => {
881
868
  const fonts = markRaw(new Fonts());
@@ -1357,76 +1344,6 @@ function boundingBoxToStyle(box) {
1357
1344
  }
1358
1345
  return style;
1359
1346
  }
1360
- function isPointInsideAabb(point, box) {
1361
- const right = box.left + box.width;
1362
- const bottom = box.top + box.height;
1363
- return point.x >= box.left && point.x <= right && point.y >= box.top && point.y <= bottom;
1364
- }
1365
- function isOverlappingAabb(aabb1, aabb2, axis) {
1366
- switch (axis) {
1367
- case "horizontal":
1368
- return aabb1.left + aabb1.width >= aabb2.left && aabb2.left + aabb2.width >= aabb1.left;
1369
- case "vertical":
1370
- return aabb1.top + aabb1.height >= aabb2.top && aabb2.top + aabb2.height >= aabb1.top;
1371
- default:
1372
- return isOverlappingAabb(aabb1, aabb2, "horizontal") && isOverlappingAabb(aabb1, aabb2, "vertical");
1373
- }
1374
- }
1375
- function isOverlappingObb(box1, box2) {
1376
- if (!box1.rotate && !box2.rotate) {
1377
- return isOverlappingAabb(box1, box2);
1378
- } else {
1379
- const dotProduct = ([ax, ay], [bx, by]) => Math.abs(ax * bx + ay * by);
1380
- const createSAT = ({ width, height, rotate = 0 }) => {
1381
- rotate = -rotate % 180;
1382
- const deg = rotate / 180 * Math.PI;
1383
- const axisX = [Math.cos(deg), -Math.sin(deg)];
1384
- const axisY = [Math.sin(deg), Math.cos(deg)];
1385
- return {
1386
- axis: [axisX, axisY],
1387
- projectionRadius: (axis) => width / 2 * dotProduct(axis, axisX) + height / 2 * dotProduct(axis, axisY)
1388
- };
1389
- };
1390
- const data1 = createSAT(box1);
1391
- const data2 = createSAT(box2);
1392
- const center = [
1393
- box1.left + box1.width / 2 - (box2.left + box2.width / 2),
1394
- box1.top + box1.height / 2 - (box2.top + box2.height / 2)
1395
- ];
1396
- for (const axis of [...data1.axis, ...data2.axis]) {
1397
- if (data1.projectionRadius(axis) + data2.projectionRadius(axis) < dotProduct(axis, center)) {
1398
- return false;
1399
- }
1400
- }
1401
- return true;
1402
- }
1403
- }
1404
- function minBoundingBox(rects) {
1405
- if (rects.length < 2) {
1406
- return {
1407
- left: rects[0]?.left ?? 0,
1408
- top: rects[0]?.top ?? 0,
1409
- width: rects[0]?.width ?? 0,
1410
- height: rects[0]?.height ?? 0
1411
- };
1412
- }
1413
- const res = rects.slice(1).reduce(
1414
- (acc, rect) => {
1415
- acc.x1 = Math.min(acc.x1, rect.left);
1416
- acc.y1 = Math.min(acc.y1, rect.top);
1417
- acc.x2 = Math.max(acc.x2, rect.left + rect.width);
1418
- acc.y2 = Math.max(acc.y2, rect.top + rect.height);
1419
- return acc;
1420
- },
1421
- {
1422
- x1: rects[0].left,
1423
- y1: rects[0].top,
1424
- x2: rects[0].left + rects[0].width,
1425
- y2: rects[0].top + rects[0].height
1426
- }
1427
- );
1428
- return { left: res.x1, top: res.y1, width: res.x2 - res.x1, height: res.y2 - res.y1 };
1429
- }
1430
1347
  function consoleWarn(message) {
1431
1348
  warn(`mce: ${message}`);
1432
1349
  }
@@ -1896,29 +1813,31 @@ const _2_box = defineMixin((editor) => {
1896
1813
  getAncestorFrame
1897
1814
  } = editor;
1898
1815
  function obbToFit(element) {
1899
- const minmax = {
1900
- minX: Number.MAX_SAFE_INTEGER,
1901
- minY: Number.MAX_SAFE_INTEGER,
1902
- maxX: Number.MIN_SAFE_INTEGER,
1903
- maxY: Number.MIN_SAFE_INTEGER
1816
+ const min = {
1817
+ x: Number.MAX_SAFE_INTEGER,
1818
+ y: Number.MAX_SAFE_INTEGER
1819
+ };
1820
+ const max = {
1821
+ x: Number.MIN_SAFE_INTEGER,
1822
+ y: Number.MIN_SAFE_INTEGER
1904
1823
  };
1905
1824
  let flag = false;
1906
1825
  element.children.forEach((child) => {
1907
1826
  if (isElement(child)) {
1908
- const _minmax = child.getAabb().toMinmax();
1909
- minmax.minX = Math.min(minmax.minX, _minmax.minX);
1910
- minmax.minY = Math.min(minmax.minY, _minmax.minY);
1911
- minmax.maxX = Math.max(minmax.maxX, _minmax.maxX);
1912
- minmax.maxY = Math.max(minmax.maxY, _minmax.maxY);
1827
+ const { min: _min, max: _max } = child.getAabb().toMinmax();
1828
+ min.x = Math.min(min.x, _min.x);
1829
+ min.y = Math.min(min.y, _min.y);
1830
+ max.x = Math.max(max.x, _max.x);
1831
+ max.y = Math.max(max.y, _max.y);
1913
1832
  flag = true;
1914
1833
  }
1915
1834
  });
1916
1835
  if (flag) {
1917
1836
  const box = {
1918
- left: minmax.minX,
1919
- top: minmax.minY,
1920
- width: minmax.maxX - minmax.minX,
1921
- height: minmax.maxY - minmax.minY
1837
+ left: min.x,
1838
+ top: min.y,
1839
+ width: max.x - min.x,
1840
+ height: max.y - min.y
1922
1841
  };
1923
1842
  const aabbs = {};
1924
1843
  element.children.forEach((child, index) => {
@@ -1960,21 +1879,14 @@ const _2_box = defineMixin((editor) => {
1960
1879
  if (node.length === 1) {
1961
1880
  obb = getObb(node[0]);
1962
1881
  } else {
1963
- obb = { ...getAabb(node), rotate: 0 };
1882
+ obb = new Obb2D(getAabb(node));
1964
1883
  }
1965
1884
  } else if (isElement(node)) {
1966
1885
  const style = node.style;
1967
1886
  noop([style.left, style.top, style.width, style.height, style.rotate]);
1968
- const { rect, rotation } = node.getGlobalObb();
1969
- obb = {
1970
- left: rect.left,
1971
- top: rect.top,
1972
- width: rect.width,
1973
- height: rect.height,
1974
- rotate: rotation / DEG_TO_RAD
1975
- };
1887
+ obb = node.getGlobalObb();
1976
1888
  } else {
1977
- obb = { left: 0, top: 0, width: 0, height: 0, rotate: 0 };
1889
+ obb = new Obb2D();
1978
1890
  }
1979
1891
  if (inTarget === "drawboard") {
1980
1892
  const zoom = camera.value.zoom;
@@ -2013,40 +1925,36 @@ const _2_box = defineMixin((editor) => {
2013
1925
  if (node.length === 1) {
2014
1926
  aabb = getAabb(node[0]);
2015
1927
  } else {
2016
- const minmax = {
2017
- minX: Number.MAX_SAFE_INTEGER,
2018
- minY: Number.MAX_SAFE_INTEGER,
2019
- maxX: Number.MIN_SAFE_INTEGER,
2020
- maxY: Number.MIN_SAFE_INTEGER
1928
+ const min = {
1929
+ x: Number.MAX_SAFE_INTEGER,
1930
+ y: Number.MAX_SAFE_INTEGER
1931
+ };
1932
+ const max = {
1933
+ x: Number.MIN_SAFE_INTEGER,
1934
+ y: Number.MIN_SAFE_INTEGER
2021
1935
  };
2022
1936
  node.forEach((child) => {
2023
1937
  if (isElement(child)) {
2024
1938
  const aabb2 = getAabb(child);
2025
- minmax.minX = Math.min(minmax.minX, aabb2.left);
2026
- minmax.minY = Math.min(minmax.minY, aabb2.top);
2027
- minmax.maxX = Math.max(minmax.maxX, aabb2.left + aabb2.width);
2028
- minmax.maxY = Math.max(minmax.maxY, aabb2.top + aabb2.height);
1939
+ min.x = Math.min(min.x, aabb2.left);
1940
+ min.y = Math.min(min.y, aabb2.top);
1941
+ max.x = Math.max(max.x, aabb2.left + aabb2.width);
1942
+ max.y = Math.max(max.y, aabb2.top + aabb2.height);
2029
1943
  }
2030
1944
  });
2031
- aabb = {
2032
- left: minmax.minX,
2033
- top: minmax.minY,
2034
- width: minmax.maxX - minmax.minX,
2035
- height: minmax.maxY - minmax.minY
2036
- };
1945
+ aabb = new Aabb2D(
1946
+ min.x,
1947
+ min.y,
1948
+ max.x - min.x,
1949
+ max.y - min.y
1950
+ );
2037
1951
  }
2038
1952
  } else if (isElement(node)) {
2039
1953
  const style = node.style;
2040
1954
  noop([style.left, style.top, style.width, style.height, style.rotate]);
2041
- const rect = node.getGlobalAabb();
2042
- aabb = {
2043
- left: rect.left,
2044
- top: rect.top,
2045
- width: rect.width,
2046
- height: rect.height
2047
- };
1955
+ aabb = node.getGlobalAabb();
2048
1956
  } else {
2049
- aabb = { left: 0, top: 0, width: 0, height: 0 };
1957
+ aabb = new Aabb2D();
2050
1958
  }
2051
1959
  if (inTarget === "drawboard") {
2052
1960
  aabb = aabbToDrawboardAabb(aabb);
@@ -2073,7 +1981,7 @@ const _2_box = defineMixin((editor) => {
2073
1981
  return aabb;
2074
1982
  }
2075
1983
  function aabbToDrawboardAabb(aabb) {
2076
- const _aabb = { ...aabb };
1984
+ const _aabb = new Aabb2D(aabb);
2077
1985
  const zoom = camera.value.zoom;
2078
1986
  const position = camera.value.position;
2079
1987
  _aabb.left *= zoom.x;
@@ -2616,11 +2524,63 @@ const _4_1_text = defineMixin((editor) => {
2616
2524
  TextEditor.register();
2617
2525
  };
2618
2526
  });
2619
- const _4_2_element = defineMixin((editor) => {
2527
+ const _4_2_frame = defineMixin((editor) => {
2528
+ const {
2529
+ root,
2530
+ currentFrameIndex,
2531
+ emit,
2532
+ selection,
2533
+ frames,
2534
+ config
2535
+ } = editor;
2536
+ function setCurrentFrame(index = currentFrameIndex.value) {
2537
+ index = Math.max(0, Math.min(frames.value.length - 1, index));
2538
+ const oldIndex = currentFrameIndex.value;
2539
+ currentFrameIndex.value = index;
2540
+ if (config.value.viewMode === "edgeless") {
2541
+ selection.value = [frames.value[index]];
2542
+ } else {
2543
+ selection.value = [];
2544
+ }
2545
+ emit("setCurrentFrame", index, oldIndex);
2546
+ }
2547
+ function handleElementInsideFrame(element) {
2548
+ const source = element.getGlobalAabb();
2549
+ const aArea = source.getArea();
2550
+ let flag = true;
2551
+ for (let i = 0, len = frames.value.length; i < len; i++) {
2552
+ const frame = frames.value[i];
2553
+ if (element.equal(frame)) {
2554
+ continue;
2555
+ }
2556
+ const target = frame.getGlobalAabb();
2557
+ if (source && target) {
2558
+ if (source.getIntersectionRect(target).getArea() > aArea * 0.5) {
2559
+ if (!element.findAncestor((ancestor) => ancestor.equal(frame))) {
2560
+ frame.appendChild(element);
2561
+ element.style.left = source.x - target.x;
2562
+ element.style.top = source.y - target.y;
2563
+ }
2564
+ flag = false;
2565
+ break;
2566
+ }
2567
+ }
2568
+ }
2569
+ if (flag && element.parent && !element.parent.equal(root.value)) {
2570
+ root.value.moveChild(element, 0);
2571
+ element.style.left = source.x;
2572
+ element.style.top = source.y;
2573
+ }
2574
+ }
2575
+ Object.assign(editor, {
2576
+ setCurrentFrame,
2577
+ handleElementInsideFrame
2578
+ });
2579
+ });
2580
+ const _4_3_element = defineMixin((editor) => {
2620
2581
  const {
2621
2582
  doc,
2622
2583
  rootAabb,
2623
- emit,
2624
2584
  textFontSizeToFit,
2625
2585
  textToFit,
2626
2586
  log,
@@ -2634,7 +2594,8 @@ const _4_2_element = defineMixin((editor) => {
2634
2594
  screenCenter,
2635
2595
  selection,
2636
2596
  camera,
2637
- parseAnchor
2597
+ parseAnchor,
2598
+ handleElementInsideFrame
2638
2599
  } = editor;
2639
2600
  function addElement(value, options = {}) {
2640
2601
  log("addElement", value, options);
@@ -2792,20 +2753,10 @@ const _4_2_element = defineMixin((editor) => {
2792
2753
  if (active) {
2793
2754
  selection.value = elements;
2794
2755
  }
2795
- emit("addElement", elements);
2796
- return isArray ? elements : elements[0];
2797
- }
2798
- function deleteElement(id) {
2799
- if (id === selection.value[0]?.id) {
2800
- selection.value = [];
2756
+ if (!isArray && !parent) {
2757
+ handleElementInsideFrame(elements[0]);
2801
2758
  }
2802
- doc.value.deleteNode(id);
2803
- }
2804
- function updateElement(id, properties) {
2805
- getElement(id)?.setProperties(properties);
2806
- }
2807
- function getElement(id) {
2808
- return doc.value.getNode(id);
2759
+ return isArray ? elements : elements[0];
2809
2760
  }
2810
2761
  function resizeElement(element, scaleX, scaleY, options = {}) {
2811
2762
  scaleX = Math.abs(scaleX);
@@ -2829,111 +2780,25 @@ const _4_2_element = defineMixin((editor) => {
2829
2780
  options.textFontSizeToFit && textFontSizeToFit(element, scaleX);
2830
2781
  }
2831
2782
  function selectArea(areaInDrawboard) {
2783
+ const area2 = new Obb2D(areaInDrawboard);
2832
2784
  const selected = root.value?.children.flatMap((node) => {
2833
2785
  if (isFrame(node)) {
2834
2786
  return node.children;
2835
2787
  }
2836
2788
  return [node];
2837
2789
  }).filter((node) => {
2838
- return "isVisibleInTree" in node && node.isVisibleInTree() && isOverlappingObb(areaInDrawboard, getObb(node, "drawboard")) && !isLock(node);
2790
+ return "isVisibleInTree" in node && node.isVisibleInTree() && getObb(node, "drawboard").overlapsOnAxis(area2) && !isLock(node);
2839
2791
  }) ?? [];
2840
2792
  selection.value = selected;
2841
2793
  return selected;
2842
2794
  }
2843
2795
  Object.assign(editor, {
2844
2796
  addElement,
2845
- deleteElement,
2846
- updateElement,
2847
- getElement,
2797
+ addElements: addElement,
2848
2798
  resizeElement,
2849
2799
  selectArea
2850
2800
  });
2851
2801
  });
2852
- const _4_3_frame = defineMixin((editor) => {
2853
- const {
2854
- doc,
2855
- root,
2856
- rootAabb,
2857
- currentFrameIndex,
2858
- frameThumbs,
2859
- emit,
2860
- selection,
2861
- frames,
2862
- config
2863
- } = editor;
2864
- function addFrame(value = {}, toIndex) {
2865
- const element = normalizeElement({
2866
- ...value,
2867
- id: void 0,
2868
- name: "Frame",
2869
- meta: {
2870
- ...value.meta,
2871
- inEditorIs: "Frame"
2872
- }
2873
- });
2874
- element.style ??= {};
2875
- element.style.left = rootAabb.value.left + rootAabb.value.width + config.value.frameGap;
2876
- element.style.width ||= rootAabb.value.width;
2877
- element.style.height ||= rootAabb.value.height;
2878
- const index = toIndex ?? (currentFrameIndex.value > -1 ? currentFrameIndex.value + 1 : frames.value.length - 1);
2879
- doc.value.addNode(element, { index });
2880
- setCurrentFrame(index);
2881
- emit("addFrame", index);
2882
- }
2883
- function duplicateFrame(index = currentFrameIndex.value) {
2884
- const page = root.value.children[index];
2885
- if (!page)
2886
- return;
2887
- doc.value.addNode(page.toJSON(), {
2888
- index: index + 1,
2889
- regenId: true
2890
- });
2891
- emit("duplicateFrame", index);
2892
- }
2893
- function moveFrame(fromIndex, toIndex) {
2894
- const id = root.value.children[fromIndex]?.id;
2895
- if (!id)
2896
- return;
2897
- doc.value.moveNode(id, toIndex);
2898
- frameThumbs.value.splice(
2899
- toIndex,
2900
- 0,
2901
- frameThumbs.value.splice(fromIndex, 1)[0]
2902
- );
2903
- setCurrentFrame(toIndex);
2904
- emit("moveFrame", fromIndex, toIndex);
2905
- }
2906
- function deleteFrame(index = currentFrameIndex.value) {
2907
- if (!root.value || root.value.children.length === 1) {
2908
- return;
2909
- }
2910
- const id = root.value.children[index]?.id;
2911
- if (!id)
2912
- return;
2913
- doc.value.deleteNode(id);
2914
- frameThumbs.value.splice(index, 1);
2915
- setCurrentFrame(index);
2916
- emit("deleteFrame", index);
2917
- }
2918
- function setCurrentFrame(index = currentFrameIndex.value) {
2919
- index = Math.max(0, Math.min(frames.value.length - 1, index));
2920
- const oldIndex = currentFrameIndex.value;
2921
- currentFrameIndex.value = index;
2922
- if (config.value.viewMode === "edgeless") {
2923
- selection.value = [frames.value[index]];
2924
- } else {
2925
- selection.value = [];
2926
- }
2927
- emit("setCurrentFrame", index, oldIndex);
2928
- }
2929
- Object.assign(editor, {
2930
- addFrame,
2931
- duplicateFrame,
2932
- moveFrame,
2933
- deleteFrame,
2934
- setCurrentFrame
2935
- });
2936
- });
2937
2802
  const _4_4_doc = defineMixin((editor, options) => {
2938
2803
  const {
2939
2804
  doc,
@@ -3389,8 +3254,8 @@ const mixins = [
3389
3254
  _3_view,
3390
3255
  _4_0_node,
3391
3256
  _4_1_text,
3392
- _4_2_element,
3393
- _4_3_frame,
3257
+ _4_2_frame,
3258
+ _4_3_element,
3394
3259
  _4_4_doc,
3395
3260
  _drawingTool$1,
3396
3261
  _scroll$1,
@@ -3423,7 +3288,7 @@ const _clipboard = definePlugin((editor, options) => {
3423
3288
  exec,
3424
3289
  canLoad,
3425
3290
  load,
3426
- addElement
3291
+ addElements
3427
3292
  } = editor;
3428
3293
  const copiedData = ref();
3429
3294
  const useClipboard = options.clipboard !== false && SUPPORTS_CLIPBOARD;
@@ -3485,7 +3350,7 @@ const _clipboard = definePlugin((editor, options) => {
3485
3350
  }
3486
3351
  }
3487
3352
  if (elements.length) {
3488
- addElement(elements, {
3353
+ addElements(elements, {
3489
3354
  position: "pointer",
3490
3355
  active: true,
3491
3356
  regenId: true
@@ -3536,7 +3401,7 @@ const _clipboard = definePlugin((editor, options) => {
3536
3401
  await _paste(await navigator.clipboard.read());
3537
3402
  } else if (copiedData.value) {
3538
3403
  if (Array.isArray(copiedData.value)) {
3539
- addElement(copiedData.value?.map((el) => cloneDeep(el)) ?? [], {
3404
+ addElements(copiedData.value?.map((el) => cloneDeep(el)) ?? [], {
3540
3405
  position: "pointer",
3541
3406
  active: true,
3542
3407
  regenId: true
@@ -3552,7 +3417,7 @@ const _clipboard = definePlugin((editor, options) => {
3552
3417
  if (!selection.value.length) {
3553
3418
  return;
3554
3419
  }
3555
- addElement(
3420
+ addElements(
3556
3421
  selection.value.map((v) => v.toJSON()),
3557
3422
  {
3558
3423
  parent: selection.value[0].parent,
@@ -3621,14 +3486,13 @@ const _copyAs = definePlugin((editor) => {
3621
3486
  });
3622
3487
  const _delete = definePlugin((editor) => {
3623
3488
  const {
3624
- deleteElement,
3625
3489
  selection,
3626
3490
  hoverElement
3627
3491
  } = editor;
3628
3492
  function _delete2() {
3629
3493
  if (selection.value.length) {
3630
- selection.value.forEach((element) => {
3631
- deleteElement(element.id);
3494
+ selection.value.forEach((node) => {
3495
+ node.remove();
3632
3496
  });
3633
3497
  selection.value = [];
3634
3498
  }
@@ -3879,23 +3743,36 @@ function useIcon(props) {
3879
3743
  const MceLayerKey = Symbol.for("mce:layer");
3880
3744
  const MceLayerItemKey = Symbol.for("mce:layer-item");
3881
3745
  function createLayer(options) {
3882
- const {
3883
- sortedSelection
3884
- } = options;
3885
3746
  const registered = ref([]);
3886
- const selecting = ref(false);
3747
+ const nodeItems = /* @__PURE__ */ new Map();
3887
3748
  const openedItems = reactive(/* @__PURE__ */ new Map());
3888
3749
  const domItems = reactive(/* @__PURE__ */ new Map());
3889
3750
  const rootVm = getCurrentInstance();
3751
+ const selecting = ref(false);
3752
+ const dragging = ref(false);
3753
+ const droppingItemId = ref();
3754
+ function getIdByNode(node) {
3755
+ let id;
3756
+ nodeItems.forEach((_node2, _id) => {
3757
+ if (node.equal(_node2.value)) {
3758
+ id = _id;
3759
+ }
3760
+ });
3761
+ return id;
3762
+ }
3890
3763
  provide(MceLayerKey, {
3764
+ ...options,
3891
3765
  selecting,
3892
- sortedSelection,
3893
- register: (vm, options2) => {
3766
+ dragging,
3767
+ droppingItemId,
3768
+ register: (vm, item) => {
3894
3769
  const {
3895
3770
  id,
3896
3771
  dom,
3897
- opened
3898
- } = options2;
3772
+ opened,
3773
+ node
3774
+ } = item;
3775
+ nodeItems.set(id, node);
3899
3776
  openedItems.set(id, opened);
3900
3777
  domItems.set(id, dom);
3901
3778
  registered.value.push(id);
@@ -3908,34 +3785,79 @@ function createLayer(options) {
3908
3785
  }
3909
3786
  },
3910
3787
  unregister: (id) => {
3788
+ nodeItems.delete(id);
3911
3789
  openedItems.delete(id);
3912
3790
  domItems.delete(id);
3913
3791
  registered.value = registered.value.filter((v) => v !== id);
3792
+ },
3793
+ onMousedown: (e, id) => {
3794
+ const start = { x: e.clientX, y: e.clientY };
3795
+ function onMove(e2) {
3796
+ const current = { x: e2.clientX, y: e2.clientY };
3797
+ if (!dragging.value && (Math.abs(current.x - start.x) >= 3 || Math.abs(current.y - start.y) >= 3)) {
3798
+ dragging.value = true;
3799
+ }
3800
+ if (dragging.value) {
3801
+ const targets = e2.composedPath();
3802
+ const layer = targets.find((target) => {
3803
+ return target instanceof HTMLElement && target.classList.contains("mce-layer");
3804
+ });
3805
+ const id2 = layer?.dataset?.id;
3806
+ if (id2) {
3807
+ droppingItemId.value = id2;
3808
+ }
3809
+ }
3810
+ }
3811
+ function onUp() {
3812
+ if (droppingItemId.value) {
3813
+ const from = nodeItems.get(id)?.value;
3814
+ const to = nodeItems.get(droppingItemId.value)?.value;
3815
+ if (to && from && !from.equal(to)) {
3816
+ let toIndex = to.getIndex() + 1;
3817
+ if (to.parent && from.parent && to.parent.equal(from.parent)) {
3818
+ toIndex--;
3819
+ }
3820
+ to.parent?.moveChild(
3821
+ from,
3822
+ toIndex
3823
+ );
3824
+ }
3825
+ }
3826
+ dragging.value = false;
3827
+ droppingItemId.value = void 0;
3828
+ document.removeEventListener("mousemove", onMove);
3829
+ document.removeEventListener("mouseup", onUp);
3830
+ }
3831
+ document.addEventListener("mousemove", onMove);
3832
+ document.addEventListener("mouseup", onUp);
3914
3833
  }
3915
3834
  });
3916
3835
  return {
3917
3836
  selecting,
3918
3837
  openedItems,
3919
- domItems
3838
+ domItems,
3839
+ getIdByNode
3920
3840
  };
3921
3841
  }
3922
3842
  function useLayerItem(options) {
3923
- const {
3843
+ const root = inject(MceLayerKey);
3844
+ if (!root)
3845
+ throw new Error("[mce] Could not find injected layer root");
3846
+ const id = `layer-item-${useId()}`;
3847
+ const item = {
3924
3848
  id,
3925
- opened,
3926
- dom
3927
- } = options;
3849
+ ...options
3850
+ };
3928
3851
  const vm = getCurrentInstance();
3929
3852
  provide(MceLayerItemKey, { id });
3930
- const rootLayer = inject(MceLayerKey);
3931
- const { register, unregister, ...props } = rootLayer;
3932
- register(vm, {
3853
+ root.register(vm, item);
3854
+ onBeforeUnmount(() => root.unregister(id));
3855
+ return {
3856
+ ...root,
3933
3857
  id,
3934
- dom,
3935
- opened
3936
- });
3937
- onBeforeUnmount(() => unregister(id));
3938
- return props;
3858
+ dropping: computed(() => root.droppingItemId.value === id),
3859
+ onMousedown: (e) => root.onMousedown?.(e, id)
3860
+ };
3939
3861
  }
3940
3862
  function useResizeObserver(callback, box = "content") {
3941
3863
  const resizeRef = templateRef();
@@ -4354,7 +4276,7 @@ const _sfc_main$B = /* @__PURE__ */ defineComponent({
4354
4276
  }
4355
4277
  return (_ctx, _cache) => {
4356
4278
  return withDirectives((openBlock(), createElementBlock("div", {
4357
- style: normalizeStyle(unref(boundingBoxToStyle)(unref(getObb)(frame.value, "drawboard"))),
4279
+ style: normalizeStyle(unref(getObb)(frame.value, "drawboard").toCssStyle()),
4358
4280
  class: normalizeClass(["mce-frame", [
4359
4281
  unref(config).frameOutline && "mce-frame--outline",
4360
4282
  unref(hoverElement)?.equal(frame.value) && "mce-frame--hover",
@@ -4495,7 +4417,7 @@ const _group = definePlugin((editor) => {
4495
4417
  getAabb,
4496
4418
  elementSelection,
4497
4419
  addElement,
4498
- deleteElement,
4420
+ addElements,
4499
4421
  doc
4500
4422
  } = editor;
4501
4423
  function group(inEditorIs) {
@@ -4515,7 +4437,12 @@ const _group = definePlugin((editor) => {
4515
4437
  doc.value.transact(() => {
4516
4438
  addElement({
4517
4439
  name: inEditorIs === "Frame" ? "Frame" : "Group",
4518
- style: { ...aabb },
4440
+ style: {
4441
+ left: aabb.left,
4442
+ top: aabb.top,
4443
+ width: aabb.width,
4444
+ height: aabb.height
4445
+ },
4519
4446
  children,
4520
4447
  meta: {
4521
4448
  inPptIs: "GroupShape",
@@ -4527,7 +4454,7 @@ const _group = definePlugin((editor) => {
4527
4454
  active: true,
4528
4455
  regenId: true
4529
4456
  });
4530
- elements.forEach((v) => deleteElement(v.id));
4457
+ elements.forEach((node) => node.remove());
4531
4458
  });
4532
4459
  }
4533
4460
  function ungroup() {
@@ -4543,13 +4470,13 @@ const _group = definePlugin((editor) => {
4543
4470
  return cloned;
4544
4471
  });
4545
4472
  doc.value.transact(() => {
4546
- addElement(items, {
4473
+ addElements(items, {
4547
4474
  parent: element.parent,
4548
4475
  index: element.getIndex(),
4549
4476
  active: true,
4550
4477
  regenId: true
4551
4478
  });
4552
- deleteElement(element.id);
4479
+ element.remove();
4553
4480
  });
4554
4481
  }
4555
4482
  return {
@@ -4622,7 +4549,7 @@ const _sfc_main$z = /* @__PURE__ */ defineComponent({
4622
4549
  style: normalizeStyle({
4623
4550
  borderColor: "currentcolor",
4624
4551
  borderRadius: `${(unref(hoverElement).style.borderRadius ?? 0) * unref(camera).zoom.x}px`,
4625
- ...unref(boundingBoxToStyle)(hoverElementObb.value)
4552
+ ...hoverElementObb.value.toCssStyle()
4626
4553
  })
4627
4554
  }, null, 12, _hoisted_1$m)) : createCommentVNode("", true);
4628
4555
  };
@@ -4762,11 +4689,11 @@ const _import = definePlugin((editor) => {
4762
4689
  const {
4763
4690
  load,
4764
4691
  openFileDialog,
4765
- addElement
4692
+ addElements
4766
4693
  } = editor;
4767
4694
  const _import2 = async (options = {}) => {
4768
4695
  const files = await openFileDialog({ multiple: true });
4769
- return addElement((await Promise.all(files.map((file) => load(file)))).flat(), {
4696
+ return addElements((await Promise.all(files.map((file) => load(file)))).flat(), {
4770
4697
  sizeToFit: true,
4771
4698
  ...options
4772
4699
  });
@@ -4788,10 +4715,10 @@ const _import = definePlugin((editor) => {
4788
4715
  } = editor;
4789
4716
  function onDragover(e) {
4790
4717
  e.preventDefault();
4791
- drawboardPointer.value = {
4792
- x: e.clientX - drawboardAabb.value.left,
4793
- y: e.clientY - drawboardAabb.value.top
4794
- };
4718
+ drawboardPointer.value = new Vector2$1(
4719
+ e.clientX - drawboardAabb.value.left,
4720
+ e.clientY - drawboardAabb.value.top
4721
+ );
4795
4722
  if (e.dataTransfer) {
4796
4723
  e.dataTransfer.dropEffect = "copy";
4797
4724
  }
@@ -5056,8 +4983,10 @@ const _sfc_main$y = /* @__PURE__ */ defineComponent({
5056
4983
  };
5057
4984
  }
5058
4985
  });
5059
- const _hoisted_1$l = { class: "mce-layer__name" };
5060
- const _hoisted_2$c = { class: "mce-layer__action" };
4986
+ const _hoisted_1$l = ["data-id"];
4987
+ const _hoisted_2$c = { class: "mce-layer__content" };
4988
+ const _hoisted_3$b = { class: "mce-layer__prepend" };
4989
+ const _hoisted_4$5 = { class: "mce-layer__action" };
5061
4990
  const _sfc_main$x = /* @__PURE__ */ defineComponent({
5062
4991
  ...{
5063
4992
  name: "MceLayer",
@@ -5100,9 +5029,12 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5100
5029
  const dom = ref();
5101
5030
  const {
5102
5031
  selecting,
5103
- sortedSelection
5032
+ sortedSelection,
5033
+ dragging,
5034
+ dropping,
5035
+ onMousedown,
5036
+ id
5104
5037
  } = useLayerItem({
5105
- id: props.node.id,
5106
5038
  opened,
5107
5039
  node: computed(() => props.node),
5108
5040
  dom: computed(() => dom.value)
@@ -5140,12 +5072,10 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5140
5072
  }
5141
5073
  return "$shape";
5142
5074
  });
5143
- function onMousedown() {
5144
- }
5145
5075
  function onClickExpand() {
5146
5076
  opened.value = !opened.value;
5147
5077
  }
5148
- function onClickContent(e) {
5078
+ function onMousedownContent(e) {
5149
5079
  selecting.value = true;
5150
5080
  if (e.shiftKey) {
5151
5081
  const _nodes = [
@@ -5190,6 +5120,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5190
5120
  nextTick().then(() => {
5191
5121
  selecting.value = false;
5192
5122
  });
5123
+ onMousedown(e);
5193
5124
  }
5194
5125
  function onDblclickThumbnail(e) {
5195
5126
  e.stopPropagation();
@@ -5199,7 +5130,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5199
5130
  });
5200
5131
  }
5201
5132
  }
5202
- function onDblclickContent() {
5133
+ function onDblclickName() {
5203
5134
  editing.value = true;
5204
5135
  editValue.value = props.node.name;
5205
5136
  nextTick().then(() => {
@@ -5211,7 +5142,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5211
5142
  });
5212
5143
  }
5213
5144
  function onMouseenter() {
5214
- if (isElement(props.node)) {
5145
+ if (!dragging.value && isElement(props.node)) {
5215
5146
  hoverElement.value = props.node;
5216
5147
  hovering.value = true;
5217
5148
  }
@@ -5245,41 +5176,44 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5245
5176
  isFrist.value && "mce-layer--first",
5246
5177
  isLast.value && "mce-layer--last",
5247
5178
  opened.value && "mce-layer--open",
5248
- isHoverElement.value && "mce-layer--hover"
5179
+ isHoverElement.value && "mce-layer--hover",
5180
+ unref(dropping) && "mce-layer--dropping"
5249
5181
  ]]),
5250
5182
  style: normalizeStyle({
5251
5183
  "--indent-padding": `${props.indent * 16}px`
5252
5184
  }),
5253
- onMousedown,
5185
+ "data-id": unref(id),
5186
+ onMousedown: onMousedownContent,
5254
5187
  onMouseenter,
5255
5188
  onMouseleave,
5256
5189
  onContextmenu
5257
5190
  }, [
5258
- createElementVNode("div", {
5259
- class: "mce-layer__expand",
5260
- onClick: onClickExpand
5261
- }, [
5262
- props.node.children.length ? (openBlock(), createBlock(unref(_sfc_main$C), {
5263
- key: 0,
5264
- icon: "$arrowRight"
5265
- })) : createCommentVNode("", true)
5266
- ]),
5267
- createElementVNode("div", {
5268
- class: "mce-layer__content",
5269
- onClick: onClickContent,
5270
- onDblclick: onDblclickContent
5271
- }, [
5191
+ _cache[5] || (_cache[5] = createElementVNode("span", { class: "mce-layer__underlay" }, null, -1)),
5192
+ _cache[6] || (_cache[6] = createElementVNode("span", { class: "mce-layer__overlay" }, null, -1)),
5193
+ createElementVNode("div", _hoisted_2$c, [
5194
+ createElementVNode("div", _hoisted_3$b, [
5195
+ props.node.children.length ? (openBlock(), createBlock(unref(_sfc_main$C), {
5196
+ key: 0,
5197
+ icon: "$arrowRight",
5198
+ onClick: onClickExpand,
5199
+ onMousedown: _cache[0] || (_cache[0] = withModifiers(() => {
5200
+ }, ["stop"]))
5201
+ })) : createCommentVNode("", true)
5202
+ ]),
5272
5203
  createElementVNode("div", {
5273
5204
  class: "mce-layer__thumbnail",
5274
5205
  onDblclick: onDblclickThumbnail
5275
5206
  }, [
5276
5207
  createVNode(unref(_sfc_main$C), { icon: thumbnailIcon.value }, null, 8, ["icon"])
5277
5208
  ], 32),
5278
- createElementVNode("div", _hoisted_1$l, [
5209
+ createElementVNode("div", {
5210
+ class: "mce-layer__name",
5211
+ onDblclick: onDblclickName
5212
+ }, [
5279
5213
  withDirectives(createElementVNode("input", {
5280
5214
  ref_key: "inputDom",
5281
5215
  ref: inputDom,
5282
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => editValue.value = $event),
5216
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => editValue.value = $event),
5283
5217
  type: "text",
5284
5218
  class: "mce-layer__input",
5285
5219
  autofocus: "",
@@ -5291,15 +5225,15 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5291
5225
  createElementVNode("div", {
5292
5226
  style: normalizeStyle({ visibility: editing.value ? "hidden" : void 0 })
5293
5227
  }, toDisplayString(editValue.value || props.node.name || props.node.id), 5)
5294
- ]),
5295
- createElementVNode("div", _hoisted_2$c, [
5228
+ ], 32),
5229
+ createElementVNode("div", _hoisted_4$5, [
5296
5230
  props.root ? (openBlock(), createBlock(_sfc_main$y, {
5297
5231
  key: 0,
5298
5232
  icon: "",
5299
5233
  class: normalizeClass(["mce-layer__btn", {
5300
5234
  "mce-layer__btn--hide": !hovering.value && !unref(isLock)(props.node)
5301
5235
  }]),
5302
- onClick: _cache[1] || (_cache[1] = ($event) => unref(setLock)(props.node, !unref(isLock)(props.node)))
5236
+ onClick: _cache[2] || (_cache[2] = ($event) => unref(setLock)(props.node, !unref(isLock)(props.node)))
5303
5237
  }, {
5304
5238
  default: withCtx(() => [
5305
5239
  createVNode(unref(_sfc_main$C), {
@@ -5313,7 +5247,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5313
5247
  class: normalizeClass(["mce-layer__btn", {
5314
5248
  "mce-layer__btn--hide": !hovering.value && !unref(isLock)(props.node)
5315
5249
  }]),
5316
- onClick: _cache[2] || (_cache[2] = withModifiers(($event) => unref(setLock)(props.node, !unref(isLock)(props.node)), ["prevent", "stop"]))
5250
+ onClick: _cache[3] || (_cache[3] = withModifiers(($event) => unref(setLock)(props.node, !unref(isLock)(props.node)), ["prevent", "stop"]))
5317
5251
  }, {
5318
5252
  default: withCtx(() => [
5319
5253
  createVNode(unref(_sfc_main$C), {
@@ -5327,7 +5261,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5327
5261
  class: normalizeClass(["mce-layer__btn", {
5328
5262
  "mce-layer__btn--hide": !hovering.value && unref(isVisible)(props.node)
5329
5263
  }]),
5330
- onClick: _cache[3] || (_cache[3] = withModifiers(($event) => unref(setVisible)(props.node, !unref(isVisible)(props.node)), ["prevent", "stop"]))
5264
+ onClick: _cache[4] || (_cache[4] = withModifiers(($event) => unref(setVisible)(props.node, !unref(isVisible)(props.node)), ["prevent", "stop"]))
5331
5265
  }, {
5332
5266
  default: withCtx(() => [
5333
5267
  createVNode(unref(_sfc_main$C), {
@@ -5338,8 +5272,8 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
5338
5272
  }, 8, ["class"])
5339
5273
  ], 64))
5340
5274
  ])
5341
- ], 32)
5342
- ], 38),
5275
+ ])
5276
+ ], 46, _hoisted_1$l),
5343
5277
  opened.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(props.node.children, (child, key) => {
5344
5278
  return openBlock(), createBlock(_component_MceLayer, {
5345
5279
  key,
@@ -5374,7 +5308,8 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
5374
5308
  const {
5375
5309
  selecting,
5376
5310
  openedItems,
5377
- domItems
5311
+ domItems,
5312
+ getIdByNode
5378
5313
  } = createLayer({
5379
5314
  sortedSelection
5380
5315
  });
@@ -5385,7 +5320,7 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
5385
5320
  let last;
5386
5321
  selection2.forEach((node) => {
5387
5322
  node.findAncestor((ancestor) => {
5388
- const opened = openedItems.get(ancestor.id);
5323
+ const opened = openedItems.get(getIdByNode(ancestor) ?? "");
5389
5324
  if (opened) {
5390
5325
  opened.value = true;
5391
5326
  }
@@ -5395,7 +5330,7 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
5395
5330
  });
5396
5331
  if (last) {
5397
5332
  nextTick().then(() => {
5398
- domItems.get(last.id)?.value?.scrollIntoView({
5333
+ domItems.get(getIdByNode(last) ?? "")?.value?.scrollIntoView({
5399
5334
  block: "center"
5400
5335
  });
5401
5336
  });
@@ -5863,10 +5798,10 @@ const _sfc_main$s = /* @__PURE__ */ defineComponent({
5863
5798
  x: event.clientX,
5864
5799
  y: event.clientY
5865
5800
  };
5866
- drawboardContextMenuPointer.value = {
5867
- x: event.clientX - drawboardAabb.value.left,
5868
- y: event.clientY - drawboardAabb.value.top
5869
- };
5801
+ drawboardContextMenuPointer.value = new Vector2$1(
5802
+ event.clientX - drawboardAabb.value.left,
5803
+ event.clientY - drawboardAabb.value.top
5804
+ );
5870
5805
  updateLocation();
5871
5806
  }
5872
5807
  watch(drawboardDom, (el, old) => {
@@ -10352,8 +10287,8 @@ const _pen = definePlugin((editor) => {
10352
10287
  const box = currentPath.getBoundingBox();
10353
10288
  el.style.left = box.left;
10354
10289
  el.style.top = box.top;
10355
- el.style.width = box.width;
10356
- el.style.height = box.height;
10290
+ el.style.width = box.width || 1;
10291
+ el.style.height = box.height || 1;
10357
10292
  }
10358
10293
  };
10359
10294
  return {
@@ -10374,6 +10309,10 @@ const _pen = definePlugin((editor) => {
10374
10309
  } else {
10375
10310
  el = addElement({
10376
10311
  name: "pen",
10312
+ style: {
10313
+ width: 1,
10314
+ height: 1
10315
+ },
10377
10316
  outline: {
10378
10317
  color: "#d9d9d9",
10379
10318
  width: 5,
@@ -10392,6 +10331,7 @@ const _pen = definePlugin((editor) => {
10392
10331
  new Vector2(start.x, start.y)
10393
10332
  );
10394
10333
  currentPath.currentCurve.addCurve(currentLine);
10334
+ update();
10395
10335
  const onMove = () => {
10396
10336
  const move = getGlobalPointer();
10397
10337
  if (currentLine && move) {
@@ -10416,6 +10356,10 @@ const _pen = definePlugin((editor) => {
10416
10356
  handle: (start) => {
10417
10357
  const el2 = addElement({
10418
10358
  name: "pencil",
10359
+ style: {
10360
+ width: 1,
10361
+ height: 1
10362
+ },
10419
10363
  outline: {
10420
10364
  color: "#d9d9d9",
10421
10365
  width: 5,
@@ -10428,20 +10372,25 @@ const _pen = definePlugin((editor) => {
10428
10372
  }, {
10429
10373
  position: start
10430
10374
  });
10375
+ const parentAabb = el2.getParent()?.getGlobalAabb?.() ?? new Aabb2D();
10431
10376
  const path = new Path2D();
10432
- path.moveTo(start.x, start.y);
10377
+ path.moveTo(start.x - parentAabb.x, start.y - parentAabb.y);
10378
+ const update2 = () => {
10379
+ el2.shape.paths = [
10380
+ { data: path.toData() }
10381
+ ];
10382
+ const box = path.getBoundingBox();
10383
+ el2.style.left = box.left;
10384
+ el2.style.top = box.top;
10385
+ el2.style.width = box.width || 1;
10386
+ el2.style.height = box.height || 1;
10387
+ };
10388
+ update2();
10433
10389
  return {
10434
10390
  move: (move) => {
10435
- path.lineTo(move.x, move.y);
10436
- path.moveTo(move.x, move.y);
10437
- el2.shape.paths = [
10438
- { data: path.toData() }
10439
- ];
10440
- const box = path.getBoundingBox();
10441
- el2.style.left = box.left;
10442
- el2.style.top = box.top;
10443
- el2.style.width = box.width;
10444
- el2.style.height = box.height;
10391
+ path.lineTo(move.x - parentAabb.x, move.y - parentAabb.y);
10392
+ path.moveTo(move.x - parentAabb.x, move.y - parentAabb.y);
10393
+ update2();
10445
10394
  }
10446
10395
  };
10447
10396
  }
@@ -11089,8 +11038,7 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
11089
11038
  exec
11090
11039
  } = useEditor();
11091
11040
  const isActive = computed(() => {
11092
- return selectionAabb.value.width && selectionAabb.value.height && !isOverlappingAabb(
11093
- drawboardAabb.value,
11041
+ return selectionAabb.value.width && selectionAabb.value.height && !drawboardAabb.value.overlapsOnAxis(
11094
11042
  aabbToDrawboardAabb(selectionAabb.value)
11095
11043
  );
11096
11044
  });
@@ -12386,9 +12334,9 @@ const _smartGuides = definePlugin((editor) => {
12386
12334
  const isCanvas = isCanvasLine(target);
12387
12335
  if (type !== target.type && !isCanvas)
12388
12336
  return;
12389
- if (!isOverlappingAabb(toBoundingBox(source), toBoundingBox(target), flippedAxis))
12337
+ if (!toBoundingBox(source).overlapsOnAxis(toBoundingBox(target), flippedAxis))
12390
12338
  return;
12391
- if (!isCanvas && prev && prev.box.id !== target.box.id && isOverlappingAabb(toBoundingBox(prev), toBoundingBox(target), axis)) {
12339
+ if (!isCanvas && prev && prev.box.id !== target.box.id && toBoundingBox(prev).overlapsOnAxis(toBoundingBox(target), axis)) {
12392
12340
  return;
12393
12341
  }
12394
12342
  prev = target;
@@ -12646,12 +12594,12 @@ function createLine(pos, type, box) {
12646
12594
  }
12647
12595
  function toBoundingBox(value) {
12648
12596
  const box = "box" in value ? value.box : value;
12649
- return {
12650
- left: box.hl.pos,
12651
- top: box.vt.pos,
12597
+ return new Aabb2D({
12598
+ x: box.hl.pos,
12599
+ y: box.vt.pos,
12652
12600
  width: box.hr.pos - box.hl.pos,
12653
12601
  height: box.vb.pos - box.vt.pos
12654
- };
12602
+ });
12655
12603
  }
12656
12604
  function flipType(type) {
12657
12605
  if (type === "vt")
@@ -13406,29 +13354,25 @@ const _ui = definePlugin((editor) => {
13406
13354
  }
13407
13355
  };
13408
13356
  });
13409
- const _url = definePlugin(() => {
13410
- async function isImage(url) {
13411
- try {
13412
- const response = await fetch(url, { method: "HEAD" });
13413
- const contentType = response.headers.get("Content-Type");
13414
- return contentType && contentType.startsWith("image/");
13415
- } catch (_error) {
13416
- return false;
13417
- }
13418
- }
13357
+ const _url = definePlugin((editor) => {
13358
+ const {
13359
+ load
13360
+ } = editor;
13419
13361
  return {
13420
13362
  name: "mce:url",
13421
13363
  loaders: [
13422
13364
  {
13423
13365
  name: "url",
13424
13366
  test: (source) => {
13425
- return typeof source === "string" && (source.startsWith("http") || imageExtRe.test(source));
13367
+ return typeof source === "string";
13426
13368
  },
13427
- load: async (source) => {
13428
- if (imageExtRe.test(source) || await isImage(source)) {
13429
- return await createImageElement(source);
13430
- } else {
13431
- throw new Error(`Failed to load url, ${source}`);
13369
+ load: async (url) => {
13370
+ const blob = await fetch(url).then((rep) => rep.blob());
13371
+ const file = new File([blob], url, { type: blob.type });
13372
+ try {
13373
+ return await load(file);
13374
+ } catch (error) {
13375
+ throw new Error(`Failed to load source "${url}", ${error}`);
13432
13376
  }
13433
13377
  }
13434
13378
  }
@@ -13527,7 +13471,7 @@ const _zoom = definePlugin((editor) => {
13527
13471
  useResizeObserver$1(drawboardDom, (entries) => {
13528
13472
  const { left: _left, top: _top, width, height } = entries[0].contentRect;
13529
13473
  const { left = _left, top = _top } = drawboardDom.value?.getBoundingClientRect() ?? {};
13530
- drawboardAabb.value = { left, top, width, height };
13474
+ drawboardAabb.value = new Aabb2D(left, top, width, height);
13531
13475
  exec("zoomToFit");
13532
13476
  });
13533
13477
  }
@@ -14578,7 +14522,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14578
14522
  __name: "Selector",
14579
14523
  props: {
14580
14524
  resizeStrategy: {},
14581
- selectedArea: { default: () => ({ left: 0, top: 0, width: 0, height: 0 }) }
14525
+ selectedArea: { default: () => new Aabb2D() }
14582
14526
  },
14583
14527
  setup(__props, { expose: __expose }) {
14584
14528
  const props = __props;
@@ -14599,7 +14543,8 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14599
14543
  isLock,
14600
14544
  config,
14601
14545
  snapThreshold,
14602
- getSnapPoints
14546
+ getSnapPoints,
14547
+ handleElementInsideFrame
14603
14548
  } = useEditor();
14604
14549
  const transformable = useTemplateRef("transformableTpl");
14605
14550
  onBeforeMount(() => {
@@ -14608,7 +14553,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14608
14553
  onBeforeUnmount(() => {
14609
14554
  unregisterCommand("startTransform");
14610
14555
  });
14611
- const parentObbs = computed(() => {
14556
+ const parentObbStyles = computed(() => {
14612
14557
  if (selection.value.length !== 1) {
14613
14558
  return [];
14614
14559
  }
@@ -14619,58 +14564,87 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14619
14564
  }
14620
14565
  return false;
14621
14566
  });
14622
- return obbs;
14567
+ return obbs.map((obb) => obb.toCssStyle());
14623
14568
  });
14624
- const selectionObbs = computed(() => {
14569
+ const selectionObbStyles = computed(() => {
14625
14570
  if (state.value !== "selecting" && elementSelection.value.length === 1) {
14626
14571
  return [];
14627
14572
  }
14628
14573
  return elementSelection.value.map((el) => {
14574
+ const box = getObb(el, "drawboard");
14629
14575
  return {
14630
- element: el,
14631
- box: getObb(el, "drawboard")
14576
+ ...box.toCssStyle(),
14577
+ borderRadius: `${(el.style.borderRadius ?? 0) * camera.value.zoom.x}px`
14632
14578
  };
14633
14579
  });
14634
14580
  });
14635
- const _selectionTransform = computed(() => {
14581
+ const _transform = computed(() => {
14636
14582
  const zoom = camera.value.zoom;
14583
+ const { left, top, width, height, rotationDegrees } = selectionObbInDrawboard.value;
14637
14584
  return {
14638
- ...selectionObbInDrawboard.value,
14585
+ left,
14586
+ top,
14587
+ width,
14588
+ height,
14589
+ rotate: rotationDegrees,
14639
14590
  borderRadius: (elementSelection.value[0]?.style.borderRadius ?? 0) * zoom.x
14640
14591
  };
14641
14592
  });
14642
- const selectionTransform = computed({
14643
- get: () => _selectionTransform.value,
14593
+ function snap(currentPos, type) {
14594
+ const points = getSnapPoints();
14595
+ const zoom = camera.value.zoom;
14596
+ const position = camera.value.position;
14597
+ let closest;
14598
+ let minDist = Infinity;
14599
+ if (type === "x") {
14600
+ currentPos += position.x / zoom.x;
14601
+ } else {
14602
+ currentPos += position.y / zoom.y;
14603
+ }
14604
+ for (const pt of points[type]) {
14605
+ const dist = pt - currentPos;
14606
+ const absDist = Math.abs(dist);
14607
+ if (absDist < minDist) {
14608
+ minDist = absDist;
14609
+ closest = pt;
14610
+ }
14611
+ }
14612
+ if (minDist <= snapThreshold.value) {
14613
+ currentPos = closest ?? currentPos;
14614
+ }
14615
+ if (type === "x") {
14616
+ currentPos -= position.x / zoom.x;
14617
+ } else {
14618
+ currentPos -= position.y / zoom.y;
14619
+ }
14620
+ return currentPos;
14621
+ }
14622
+ const transform = computed({
14623
+ get: () => _transform.value,
14644
14624
  set: (val) => {
14625
+ const handle = transformable.value?.activeHandle ?? "move";
14645
14626
  const zoom = camera.value.zoom;
14646
- const oldTransform = _selectionTransform.value;
14647
- const offsetStyle = {
14648
- left: (val.left - oldTransform.left) / zoom.x,
14649
- top: (val.top - oldTransform.top) / zoom.y,
14650
- width: Math.max(1, val.width / zoom.x) - oldTransform.width / zoom.x,
14651
- height: Math.max(1, val.height / zoom.y) - oldTransform.height / zoom.y,
14652
- rotate: (val.rotate ?? 0) - (oldTransform.rotate ?? 0),
14653
- borderRadius: ((val.borderRadius ?? 0) - (oldTransform.borderRadius ?? 0)) / zoom.y
14627
+ const oldTransform = _transform.value;
14628
+ const transform2 = {
14629
+ left: val.left / zoom.x,
14630
+ top: val.top / zoom.y,
14631
+ width: Math.max(1, val.width / zoom.x),
14632
+ height: Math.max(1, val.height / zoom.y),
14633
+ rotate: val.rotate ?? 0,
14634
+ borderRadius: (val.borderRadius ?? 0) / zoom.y
14654
14635
  };
14655
- const points = getSnapPoints();
14656
- const snap = (currentPos, type) => {
14657
- let closest;
14658
- let minDist = Infinity;
14659
- for (const pt of points[type]) {
14660
- const dist = pt - currentPos;
14661
- const absDist = Math.abs(dist);
14662
- if (absDist < minDist) {
14663
- minDist = absDist;
14664
- closest = pt;
14665
- }
14666
- }
14667
- if (minDist <= snapThreshold.value) {
14668
- return closest ?? currentPos;
14669
- } else {
14670
- return currentPos;
14671
- }
14636
+ if (handle === "move") {
14637
+ transform2.left = snap(Math.round(transform2.left), "x");
14638
+ transform2.top = snap(Math.round(transform2.top), "y");
14639
+ }
14640
+ const offsetStyle = {
14641
+ left: transform2.left - oldTransform.left / zoom.x,
14642
+ top: transform2.top - oldTransform.top / zoom.y,
14643
+ width: transform2.width - oldTransform.width / zoom.x,
14644
+ height: transform2.height - oldTransform.height / zoom.y,
14645
+ rotate: transform2.rotate - (oldTransform.rotate ?? 0),
14646
+ borderRadius: transform2.borderRadius - (oldTransform.borderRadius ?? 0) / zoom.y
14672
14647
  };
14673
- const handle = transformable.value?.activeHandle ?? "move";
14674
14648
  elementSelection.value.forEach((element) => {
14675
14649
  const style = element.style;
14676
14650
  const newStyle = {
@@ -14681,20 +14655,18 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14681
14655
  rotate: style.rotate + offsetStyle.rotate,
14682
14656
  borderRadius: Math.round(style.borderRadius + offsetStyle.borderRadius)
14683
14657
  };
14684
- if (handle === "move") {
14685
- newStyle.left = snap(Math.round(newStyle.left), "x");
14686
- newStyle.top = snap(Math.round(newStyle.top), "y");
14687
- } else if (handle.startsWith("rotate")) {
14658
+ if (handle.startsWith("rotate")) {
14688
14659
  newStyle.rotate = Math.round(newStyle.rotate * 100) / 100;
14689
14660
  } else if (handle.startsWith("resize")) {
14690
14661
  const scale = newStyle.rotate ? 100 : 1;
14691
14662
  newStyle.width = Math.round(newStyle.width * scale) / scale;
14692
14663
  newStyle.height = Math.round(newStyle.height * scale) / scale;
14664
+ const shape = element.shape;
14693
14665
  resizeElement(
14694
14666
  element,
14695
14667
  newStyle.width / element.style.width,
14696
14668
  newStyle.height / element.style.height,
14697
- isFrame(element) ? void 0 : handle.split("-").length > 2 ? { deep: true, textFontSizeToFit: true } : { deep: true, textToFit: true }
14669
+ isFrame(element) ? void 0 : !shape.enabled || !shape._path2DSet.paths.length ? handle.split("-").length > 2 ? { deep: true, textFontSizeToFit: true } : { deep: true, textToFit: true } : void 0
14698
14670
  );
14699
14671
  newStyle.width = element.style.width;
14700
14672
  newStyle.height = element.style.height;
@@ -14707,6 +14679,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14707
14679
  }
14708
14680
  return false;
14709
14681
  });
14682
+ handleElementInsideFrame(element);
14710
14683
  });
14711
14684
  }
14712
14685
  });
@@ -14738,13 +14711,13 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14738
14711
  });
14739
14712
  return (_ctx, _cache) => {
14740
14713
  return openBlock(), createElementBlock(Fragment, null, [
14741
- (openBlock(true), createElementBlock(Fragment, null, renderList(parentObbs.value, (obb, index) => {
14714
+ (openBlock(true), createElementBlock(Fragment, null, renderList(parentObbStyles.value, (style, index) => {
14742
14715
  return openBlock(), createElementBlock("div", {
14743
14716
  key: index,
14744
14717
  class: "mce-selector__parent-element",
14745
14718
  style: normalizeStyle({
14746
14719
  borderColor: "currentColor",
14747
- ...unref(boundingBoxToStyle)(obb)
14720
+ ...style
14748
14721
  })
14749
14722
  }, null, 4);
14750
14723
  }), 128)),
@@ -14753,25 +14726,24 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14753
14726
  class: "mce-selector__selected-area",
14754
14727
  style: normalizeStyle({
14755
14728
  borderColor: "currentcolor",
14756
- ...unref(boundingBoxToStyle)(props.selectedArea)
14729
+ ...props.selectedArea.toCssStyle()
14757
14730
  })
14758
14731
  }, null, 4)) : createCommentVNode("", true),
14759
- (openBlock(true), createElementBlock(Fragment, null, renderList(selectionObbs.value, (item, index) => {
14732
+ (openBlock(true), createElementBlock(Fragment, null, renderList(selectionObbStyles.value, (style, index) => {
14760
14733
  return openBlock(), createElementBlock("div", {
14761
14734
  key: index,
14762
14735
  class: "mce-selector__element",
14763
14736
  style: normalizeStyle({
14764
14737
  borderColor: "currentcolor",
14765
- borderRadius: `${(item.element.style.borderRadius ?? 0) * unref(camera).zoom.x}px`,
14766
- ...unref(boundingBoxToStyle)(item.box)
14738
+ ...style
14767
14739
  })
14768
14740
  }, null, 4);
14769
14741
  }), 128)),
14770
- selectionTransform.value.width && selectionTransform.value.height ? (openBlock(), createBlock(_sfc_main$a, {
14742
+ transform.value.width && transform.value.height ? (openBlock(), createBlock(_sfc_main$a, {
14771
14743
  key: 1,
14772
14744
  ref: "transformableTpl",
14773
- modelValue: selectionTransform.value,
14774
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectionTransform.value = $event),
14745
+ modelValue: transform.value,
14746
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => transform.value = $event),
14775
14747
  movable: movable.value,
14776
14748
  resizable: resizable.value,
14777
14749
  rotatable: rotatable.value,
@@ -14792,12 +14764,12 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
14792
14764
  key: "0"
14793
14765
  } : void 0
14794
14766
  ]), 1032, ["modelValue", "movable", "resizable", "rotatable", "adjustable-border-radius", "resize-strategy", "handle-shape", "border-style"])) : createCommentVNode("", true),
14795
- selectionTransform.value.width && selectionTransform.value.height && _ctx.$slots.default ? (openBlock(), createElementBlock("div", {
14767
+ transform.value.width && transform.value.height && _ctx.$slots.default ? (openBlock(), createElementBlock("div", {
14796
14768
  key: 2,
14797
14769
  class: "mce-selector__slot",
14798
- style: normalizeStyle(unref(boundingBoxToStyle)(selectionTransform.value))
14770
+ style: normalizeStyle(unref(boundingBoxToStyle)(transform.value))
14799
14771
  }, [
14800
- renderSlot(_ctx.$slots, "default", { box: selectionTransform.value })
14772
+ renderSlot(_ctx.$slots, "default", { box: transform.value })
14801
14773
  ], 4)) : createCommentVNode("", true)
14802
14774
  ], 64);
14803
14775
  };
@@ -15002,18 +14974,14 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
15002
14974
  obb.left += textBox.left;
15003
14975
  obb.top += textBox.top;
15004
14976
  }
15005
- const style = boundingBoxToStyle(obb);
15006
- return {
15007
- ...style
15008
- };
14977
+ return obb.toCssStyle();
15009
14978
  });
15010
14979
  function onUpdateTextSelection(e) {
15011
14980
  textSelection.value = e.detail;
15012
14981
  }
15013
14982
  function onUpdate() {
15014
14983
  const element = elementSelection.value[0];
15015
- const shape = element.shape;
15016
- if (!shape.enabled || !shape._path2DSet.paths.length) {
14984
+ if (!element.shape.enabled || !element.shape._path2DSet.paths.length) {
15017
14985
  textToFit(element);
15018
14986
  }
15019
14987
  }
@@ -15133,7 +15101,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15133
15101
  const selector = useTemplateRef("selectorTpl");
15134
15102
  const textEditor = useTemplateRef("textEditorTpl");
15135
15103
  const grabbing = ref(false);
15136
- const selectedArea = ref({ left: 0, top: 0, width: 0, height: 0 });
15104
+ const selectedArea = ref(new Aabb2D());
15137
15105
  const resizeStrategy = computed(() => {
15138
15106
  const first = elementSelection.value[0];
15139
15107
  if (first) {
@@ -15167,10 +15135,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15167
15135
  function onHover(event) {
15168
15136
  let cursor;
15169
15137
  let hovered;
15170
- if (elementSelection.value.length > 1 && isPointInsideAabb(
15171
- { x: event.clientX, y: event.clientY },
15172
- selectionAabbInDrawboard.value
15173
- )) {
15138
+ if (elementSelection.value.length > 1 && selectionAabbInDrawboard.value.containsPoint({
15139
+ x: event.clientX,
15140
+ y: event.clientY
15141
+ })) {
15174
15142
  cursor = "move";
15175
15143
  } else {
15176
15144
  const element = event.target;
@@ -15204,10 +15172,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15204
15172
  let isUp = false;
15205
15173
  let selected = [];
15206
15174
  let ctxState;
15207
- const inSelection = isPointInsideAabb({
15175
+ const inSelection = selectionAabbInDrawboard.value.containsPoint({
15208
15176
  x: start.x - drawboardAabb.value.left,
15209
15177
  y: start.y - drawboardAabb.value.top
15210
- }, selectionAabbInDrawboard.value);
15178
+ });
15211
15179
  if (downEvent.button === 2) {
15212
15180
  if (!inSelection) {
15213
15181
  const result = props.activeStrategy({
@@ -15253,12 +15221,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15253
15221
  if (state.value !== "selecting") {
15254
15222
  state.value = "selecting";
15255
15223
  }
15256
- selectedArea.value = {
15257
- left: Math.min(start.x, current.x) - drawboardAabb.value.left,
15258
- top: Math.min(start.y, current.y) - drawboardAabb.value.top,
15259
- width: Math.abs(start.x - current.x),
15260
- height: Math.abs(start.y - current.y)
15261
- };
15224
+ selectedArea.value.x = Math.min(start.x, current.x) - drawboardAabb.value.left;
15225
+ selectedArea.value.y = Math.min(start.y, current.y) - drawboardAabb.value.top;
15226
+ selectedArea.value.width = Math.abs(start.x - current.x);
15227
+ selectedArea.value.height = Math.abs(start.y - current.y);
15262
15228
  selected = selectArea(selectedArea.value);
15263
15229
  }
15264
15230
  function onActivate() {
@@ -15379,10 +15345,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15379
15345
  if (event.srcElement !== drawboardDom.value) {
15380
15346
  return;
15381
15347
  }
15382
- drawboardPointer.value = {
15383
- x: event.clientX - drawboardAabb.value.left,
15384
- y: event.clientY - drawboardAabb.value.top
15385
- };
15348
+ drawboardPointer.value = new Vector2$1(
15349
+ event.clientX - drawboardAabb.value.left,
15350
+ event.clientY - drawboardAabb.value.top
15351
+ );
15386
15352
  if (camera.value.grabbing || event.button === 1 || state.value && state.value !== "typing") {
15387
15353
  return;
15388
15354
  }
@@ -15624,22 +15590,17 @@ export {
15624
15590
  findChildrenWithProvide,
15625
15591
  getImageSizeFromUrl,
15626
15592
  getRandomValues,
15627
- iElementToYNodes,
15628
15593
  imageExtRe,
15629
15594
  imageExts,
15630
15595
  imageMimeTypeExtMap,
15631
15596
  isClickInsideElement,
15632
15597
  isInputEvent,
15633
15598
  isMac,
15634
- isOverlappingAabb,
15635
- isOverlappingObb,
15636
- isPointInsideAabb,
15637
15599
  isWindows,
15638
15600
  makeLayoutItemProps,
15639
15601
  makeLayoutProps,
15640
15602
  makeMceOverlayProps,
15641
15603
  makeMceStrategyProps,
15642
- minBoundingBox,
15643
15604
  mixins,
15644
15605
  plugins,
15645
15606
  propsFactory,