mce 0.16.3 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +111 -58
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Element2D, Node as Node$1, Camera2D, Timeline, DrawboardEffect, Engine, Aabb2D, assets, IN_BROWSER, clamp, TimelineNode, Video2D, Transform2D, Obb2D, render, Vector2 as Vector2$1, Lottie2D, customNodes, Animation, IN_MAC_OS } from "modern-canvas";
1
+ import { Element2D, Node as Node$1, Camera2D, Timeline, DrawboardEffect, Engine, Aabb2D, assets, IN_BROWSER, clamp, TimelineNode, Video2D, Transform2D, Obb2D, render, Vector2 as Vector2$1, Lottie2D, customNodes, Animation, IN_MAC_OS, DEG_TO_RAD } from "modern-canvas";
2
2
  import { reactive, computed, watch, markRaw, isReactive, ref, onBeforeMount, onScopeDispose, warn, shallowRef, defineComponent, unref, openBlock, createElementBlock, normalizeStyle as normalizeStyle$1, toDisplayString, createCommentVNode, onMounted, createVNode, useAttrs, createBlock, resolveDynamicComponent, normalizeClass, mergeProps, createElementVNode, inject, toValue, getCurrentInstance, provide, useId, onBeforeUnmount, readonly, toRef, onDeactivated, onActivated, useModel, useTemplateRef, withDirectives, withModifiers, vModelText, vShow, nextTick, Fragment, renderList, renderSlot, resolveComponent, withCtx, mergeModels, Teleport, createTextVNode, createSlots, normalizeProps, guardReactiveProps, h, isRef, effectScope, useSlots } from "vue";
3
3
  import { useFileDialog, useEventListener, isClient, onClickOutside, useDebounceFn, useImage, useResizeObserver as useResizeObserver$1, useLocalStorage } from "@vueuse/core";
4
4
  import { getObjectValueByPath, setObjectValueByPath, Observable, idGenerator, normalizeTextContent, property, isCRLF, textContentToString, normalizeCRLF, isEqualObject } from "modern-idoc";
@@ -787,7 +787,7 @@ class Doc extends Node$1 {
787
787
  });
788
788
  this._localDb = _localDb;
789
789
  let id;
790
- let _source = source;
790
+ let _source;
791
791
  if (typeof source === "string") {
792
792
  id = source;
793
793
  } else if (source) {
@@ -869,8 +869,13 @@ class Doc extends Node$1 {
869
869
  this._yDoc.destroy();
870
870
  };
871
871
  }
872
- const _0_context = defineMixin((editor) => {
873
- const root = ref(new Doc());
872
+ const _0_context = defineMixin((editor, options) => {
873
+ const root = ref(
874
+ new Doc(
875
+ options.localDb ? "doc" : void 0,
876
+ options.localDb
877
+ )
878
+ );
874
879
  const docLoading = ref(false);
875
880
  const fonts = markRaw(new Fonts());
876
881
  const camera = ref(new Camera2D({ internalMode: "front" }));
@@ -1027,6 +1032,7 @@ const _0_context = defineMixin((editor) => {
1027
1032
  onBeforeMount(() => {
1028
1033
  on("setDoc", onSetDoc);
1029
1034
  renderEngine.value.start();
1035
+ root2.value.load();
1030
1036
  });
1031
1037
  onScopeDispose(() => {
1032
1038
  off("setDoc", onSetDoc);
@@ -2006,7 +2012,7 @@ const _2_box = defineMixin((editor) => {
2006
2012
  let flag = false;
2007
2013
  element.children.forEach((child) => {
2008
2014
  if (isElement(child)) {
2009
- const { min: _min, max: _max } = child.aabb.toMinmax();
2015
+ const { min: _min, max: _max } = child.aabb;
2010
2016
  min.x = Math.min(min.x, _min.x);
2011
2017
  min.y = Math.min(min.y, _min.y);
2012
2018
  max.x = Math.max(max.x, _max.x);
@@ -12561,17 +12567,20 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
12561
12567
  height: props.initialSize && !height ? void 0 : `${height}px`
12562
12568
  };
12563
12569
  });
12570
+ const DEG_TO_RAD2 = Math.PI / 180;
12564
12571
  const style = computed(() => {
12565
12572
  const { left = 0, top = 0, rotate = 0 } = model.value;
12566
- const radian = rotate * Math.PI / 180;
12567
- const cos = Math.cos(radian);
12568
- const sin = Math.sin(radian);
12573
+ const rad = rotate * DEG_TO_RAD2;
12574
+ const cos = Math.cos(rad);
12575
+ const sin = Math.sin(rad);
12569
12576
  return {
12570
12577
  ...sizeStyle.value,
12571
12578
  transform: `matrix(${cos}, ${sin}, ${-sin}, ${cos}, ${left}, ${top})`
12572
12579
  };
12573
12580
  });
12574
- const tip = computed(() => typeof props.tip === "string" ? props.tip : props.tip?.("size"));
12581
+ const tip = computed(() => {
12582
+ return typeof props.tip === "string" ? props.tip : props.tip?.("size");
12583
+ });
12575
12584
  function start(event, index) {
12576
12585
  if (event && event.button !== void 0 && event.button !== 0) {
12577
12586
  return false;
@@ -12617,7 +12626,7 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
12617
12626
  const startAngle = Math.atan2(
12618
12627
  rotatedStartPoint.y - centerPoint.y,
12619
12628
  rotatedStartPoint.x - centerPoint.x
12620
- ) / (Math.PI / 180);
12629
+ ) / DEG_TO_RAD2;
12621
12630
  let startClientPoint = event ? { x: event.clientX, y: event.clientY } : void 0;
12622
12631
  function startTransform() {
12623
12632
  transforming.value = true;
@@ -12655,7 +12664,7 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
12655
12664
  const endAngle = Math.atan2(
12656
12665
  rotatedCurrentPoint.y - centerPoint.y,
12657
12666
  rotatedCurrentPoint.x - centerPoint.x
12658
- ) / (Math.PI / 180);
12667
+ ) / DEG_TO_RAD2;
12659
12668
  updated.rotate = rotate + endAngle - startAngle;
12660
12669
  }
12661
12670
  } else if (isRound) {
@@ -12768,10 +12777,10 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
12768
12777
  }
12769
12778
  return `url("data:image/svg+xml,${create(model.value.rotate ?? 0)}") 16 16, pointer`;
12770
12779
  }
12771
- function rotatePoint2(point, origin, angle) {
12772
- const radian = angle * Math.PI / 180;
12773
- const cos = Math.cos(radian);
12774
- const sin = Math.sin(radian);
12780
+ function rotatePoint2(point, origin, deg) {
12781
+ const rad = deg * DEG_TO_RAD2;
12782
+ const cos = Math.cos(rad);
12783
+ const sin = Math.sin(rad);
12775
12784
  return {
12776
12785
  x: (point.x - origin.x) * cos - (point.y - origin.y) * sin + origin.x,
12777
12786
  y: (point.x - origin.x) * sin + (point.y - origin.y) * cos + origin.y
@@ -16409,19 +16418,23 @@ const _transform = definePlugin((editor) => {
16409
16418
  elementSelection,
16410
16419
  exec,
16411
16420
  inEditorIs,
16412
- resizeElement
16421
+ resizeElement,
16422
+ state
16413
16423
  } = editor;
16414
16424
  async function enter() {
16415
- if (elementSelection.value.length === 1) {
16416
- const element = elementSelection.value[0];
16417
- if (element.text.isValid()) {
16425
+ const els = elementSelection.value;
16426
+ if (els.length === 1) {
16427
+ const el = els[0];
16428
+ if (el.text.isValid()) {
16418
16429
  await exec("startTyping");
16430
+ } else if (el.foreground.isValid()) {
16431
+ state.value = "cropping";
16419
16432
  }
16420
16433
  }
16421
16434
  }
16422
- const startState = {
16435
+ const transformCtx = {
16423
16436
  rotate: 0,
16424
- minMaxMap: {}
16437
+ resize: {}
16425
16438
  };
16426
16439
  const transformValue = computed(() => {
16427
16440
  const { left, top, width, height, rotationDegrees } = selectionObb.value;
@@ -16434,32 +16447,54 @@ const _transform = definePlugin((editor) => {
16434
16447
  borderRadius: elementSelection.value[0]?.style.borderRadius ?? 0
16435
16448
  };
16436
16449
  });
16437
- function transform(handle, partialValue) {
16438
- const oldValue = transformValue.value;
16439
- const value = {
16440
- ...oldValue,
16441
- ...partialValue
16450
+ function onSelectionTransformStart() {
16451
+ const aabb = selectionAabb.value;
16452
+ elementSelection.value.forEach((el) => {
16453
+ const elAabb = el.globalAabb;
16454
+ transformCtx.resize[el.instanceId] = {
16455
+ minX: (elAabb.min.x - aabb.min.x) / aabb.width,
16456
+ minY: (elAabb.min.y - aabb.min.y) / aabb.height,
16457
+ maxX: (elAabb.max.x - aabb.min.x) / aabb.width,
16458
+ maxY: (elAabb.max.y - aabb.min.y) / aabb.height,
16459
+ scaleX: el.style.width / elAabb.width,
16460
+ scaleY: el.style.height / elAabb.height
16461
+ };
16462
+ });
16463
+ }
16464
+ function onSelectionTransformEnd() {
16465
+ transformCtx.rotate = 0;
16466
+ transformCtx.resize = {};
16467
+ }
16468
+ function transform(handle, partialTransform) {
16469
+ const oldTransform = transformValue.value;
16470
+ const transform2 = {
16471
+ ...oldTransform,
16472
+ ...partialTransform
16442
16473
  };
16443
16474
  const [type, direction = ""] = handle.split("-");
16444
16475
  const isCorner = direction.length > 1;
16445
16476
  const els = elementSelection.value;
16446
16477
  const isMultiple = els.length > 1;
16447
16478
  if (type === "move") {
16448
- value.left = exec("snap", "x", Math.round(value.left));
16449
- value.top = exec("snap", "y", Math.round(value.top));
16479
+ transform2.left = Math.round(transform2.left);
16480
+ transform2.top = Math.round(transform2.top);
16481
+ if (!transform2.rotate) {
16482
+ transform2.left = exec("snap", "x", transform2.left);
16483
+ transform2.top = exec("snap", "y", transform2.top);
16484
+ }
16450
16485
  }
16451
16486
  const offsetStyle = {
16452
- left: value.left - oldValue.left,
16453
- top: value.top - oldValue.top,
16454
- width: value.width - oldValue.width,
16455
- height: value.height - oldValue.height,
16456
- rotate: value.rotate - oldValue.rotate,
16457
- borderRadius: value.borderRadius - oldValue.borderRadius
16487
+ left: transform2.left - oldTransform.left,
16488
+ top: transform2.top - oldTransform.top,
16489
+ width: transform2.width - oldTransform.width,
16490
+ height: transform2.height - oldTransform.height,
16491
+ rotate: transform2.rotate - oldTransform.rotate,
16492
+ borderRadius: transform2.borderRadius - oldTransform.borderRadius
16458
16493
  };
16459
16494
  if (isMultiple) {
16460
16495
  if (type === "rotate") {
16461
- offsetStyle.rotate = value.rotate - startState.rotate;
16462
- startState.rotate += offsetStyle.rotate;
16496
+ offsetStyle.rotate = transform2.rotate - transformCtx.rotate;
16497
+ transformCtx.rotate += offsetStyle.rotate;
16463
16498
  }
16464
16499
  }
16465
16500
  els.forEach((el) => {
@@ -16473,15 +16508,47 @@ const _transform = definePlugin((editor) => {
16473
16508
  borderRadius: Math.round(style.borderRadius + offsetStyle.borderRadius)
16474
16509
  };
16475
16510
  if (type === "rotate") {
16511
+ if (isMultiple) {
16512
+ const center = el.globalAabb.getCenter().rotate(
16513
+ offsetStyle.rotate * DEG_TO_RAD,
16514
+ {
16515
+ x: transform2.left + transform2.width / 2,
16516
+ y: transform2.top + transform2.height / 2
16517
+ }
16518
+ );
16519
+ const parentAabb = el.getParent()?.globalAabb;
16520
+ if (parentAabb) {
16521
+ center.x -= parentAabb.left;
16522
+ center.y -= parentAabb.top;
16523
+ }
16524
+ newStyle.left = center.x - newStyle.width / 2;
16525
+ newStyle.top = center.y - newStyle.height / 2;
16526
+ }
16476
16527
  newStyle.rotate = Math.round(newStyle.rotate * 100) / 100;
16477
16528
  } else if (type === "resize") {
16478
16529
  if (isMultiple) {
16479
- const parentAabb = el.getParent()?.globalAabb ?? new Aabb2D();
16480
- const minMax = startState.minMaxMap[el.instanceId];
16481
- newStyle.left = value.left - parentAabb.left + value.width * minMax.minX;
16482
- newStyle.top = value.top - parentAabb.left + value.height * minMax.minY;
16483
- newStyle.width = value.width * (minMax.maxX - minMax.minX);
16484
- newStyle.height = value.height * (minMax.maxY - minMax.minY);
16530
+ const ctx = transformCtx.resize[el.instanceId];
16531
+ if (ctx) {
16532
+ const min = {
16533
+ x: transform2.left + transform2.width * ctx.minX,
16534
+ y: transform2.top + transform2.height * ctx.minY
16535
+ };
16536
+ const max = {
16537
+ x: transform2.left + transform2.width * ctx.maxX,
16538
+ y: transform2.top + transform2.height * ctx.maxY
16539
+ };
16540
+ const size = { x: max.x - min.x, y: max.y - min.y };
16541
+ const center = { x: min.x + size.x / 2, y: min.y + size.y / 2 };
16542
+ const parentAabb = el.getParent()?.globalAabb;
16543
+ if (parentAabb) {
16544
+ center.x -= parentAabb.left;
16545
+ center.y -= parentAabb.top;
16546
+ }
16547
+ newStyle.width = size.x * ctx.scaleX;
16548
+ newStyle.height = size.y * ctx.scaleY;
16549
+ newStyle.left = center.x - newStyle.width / 2;
16550
+ newStyle.top = center.y - newStyle.height / 2;
16551
+ }
16485
16552
  }
16486
16553
  const scale = newStyle.rotate ? 100 : 1;
16487
16554
  resizeElement(
@@ -16527,23 +16594,9 @@ const _transform = definePlugin((editor) => {
16527
16594
  { command: "flipVertical", key: "Shift+V" }
16528
16595
  ],
16529
16596
  events: {
16530
- selectionTransformStart: () => {
16531
- const aabb = selectionAabb.value;
16532
- elementSelection.value.forEach((el) => {
16533
- const elAabb = el.globalAabb;
16534
- startState.minMaxMap[el.instanceId] = {
16535
- minX: (elAabb.min.x - aabb.min.x) / aabb.width,
16536
- minY: (elAabb.min.y - aabb.min.y) / aabb.height,
16537
- maxX: (elAabb.max.x - aabb.min.x) / aabb.width,
16538
- maxY: (elAabb.max.y - aabb.min.y) / aabb.height
16539
- };
16540
- });
16541
- },
16597
+ selectionTransformStart: onSelectionTransformStart,
16542
16598
  selectionTransform: (ctx) => transform(ctx.handle, ctx.value),
16543
- selectionTransformEnd: () => {
16544
- startState.rotate = 0;
16545
- startState.minMaxMap = {};
16546
- }
16599
+ selectionTransformEnd: onSelectionTransformEnd
16547
16600
  }
16548
16601
  };
16549
16602
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mce",
3
3
  "type": "module",
4
- "version": "0.16.3",
4
+ "version": "0.16.4",
5
5
  "description": "A headless infinite canvas editor framework built on WebGL rendering, supports exporting to image, video, and PPT. Only the ESM.",
6
6
  "author": "wxm",
7
7
  "license": "MIT",
@@ -61,7 +61,7 @@
61
61
  "diff": "^8.0.3",
62
62
  "file-saver": "^2.0.5",
63
63
  "lodash-es": "^4.17.23",
64
- "modern-canvas": "^0.15.1",
64
+ "modern-canvas": "^0.15.3",
65
65
  "modern-font": "^0.4.4",
66
66
  "modern-idoc": "^0.10.21",
67
67
  "modern-text": "^1.10.15",