mce 0.15.3 → 0.15.5

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.
@@ -38,7 +38,6 @@ export declare class Doc extends Model {
38
38
  reset(): this;
39
39
  protected _addNode(data: Element, options?: AddNodeOptions): Node;
40
40
  addNode(data: Element, options?: AddNodeOptions): Node;
41
- addNodes(dataItems: Element[], options?: AddNodeOptions): Node[];
42
41
  set(source: Document): this;
43
42
  protected _proxyProps(obj: CoreObject, yMap: Y.Map<any>, isMeta?: boolean): void;
44
43
  protected _proxyChildren(node: Node, childrenIds: Y.Array<string>): void;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Node as Node$1, Element2D, Timeline, Engine, Camera2D, DrawboardEffect, Aabb2D, IN_BROWSER, clamp, assets, TimelineNode, Transform2D, Obb2D, 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";
2
+ import { reactive, computed, watch, markRaw, isReactive, 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
4
  import { getObjectValueByPath, setObjectValueByPath, Observable, Reactivable, idGenerator, property, normalizeTextContent, normalizeCRLF, isEqualObject } from "modern-idoc";
5
5
  import { saveAs } from "file-saver";
@@ -536,11 +536,6 @@ class Doc extends Model {
536
536
  async load(initFn) {
537
537
  return super.load(async () => {
538
538
  await initFn?.();
539
- this._proxyNode(
540
- this.root,
541
- this._yProps,
542
- this._yChildrenIds
543
- );
544
539
  this._yChildren.observe(this._yChildrenChange.bind(this));
545
540
  });
546
541
  }
@@ -611,9 +606,6 @@ class Doc extends Model {
611
606
  addNode(data, options) {
612
607
  return this.transact(() => this._addNode(data, options));
613
608
  }
614
- addNodes(dataItems, options) {
615
- return this.transact(() => dataItems.map((data) => this._addNode(data, options)));
616
- }
617
609
  set(source) {
618
610
  const { children = [], meta = {}, ..._props } = source;
619
611
  const props = {
@@ -628,7 +620,12 @@ class Doc extends Model {
628
620
  }
629
621
  this._yProps.set("meta", new Y.Map(Object.entries(meta)));
630
622
  this._transacting = true;
631
- this.addNodes(children);
623
+ this._proxyNode(
624
+ this.root,
625
+ this._yProps,
626
+ this._yChildrenIds
627
+ );
628
+ this.root.append(children);
632
629
  return this;
633
630
  }
634
631
  _proxyProps(obj, yMap, isMeta = false) {
@@ -695,8 +692,9 @@ class Doc extends Model {
695
692
  return;
696
693
  }
697
694
  this.transact(() => {
698
- childrenIds.insert(newIndex, [child.id]);
699
695
  this._debug(`addChild ${child.id}`, child.name, newIndex);
696
+ this._proxyNode(child);
697
+ childrenIds.insert(newIndex, [child.id]);
700
698
  });
701
699
  });
702
700
  node.on("removeChild", (child, oldIndex) => {
@@ -704,11 +702,11 @@ class Doc extends Model {
704
702
  return;
705
703
  }
706
704
  this.transact(() => {
705
+ this._debug(`removeChild ${child.id}`, child.name, oldIndex);
707
706
  const index = childrenIds.toJSON().indexOf(child.id);
708
707
  if (index > -1) {
709
708
  childrenIds.delete(index, 1);
710
709
  }
711
- this._debug(`removeChild ${child.id}`, child.name, oldIndex);
712
710
  });
713
711
  });
714
712
  node.children.forEach((child) => {
@@ -786,6 +784,12 @@ class Doc extends Model {
786
784
  this.undoManager.addToScope(yNode);
787
785
  }
788
786
  if (!this._nodeMap.has(id)) {
787
+ if (!isReactive(node)) {
788
+ node = reactive(node);
789
+ if (node.parent) {
790
+ node.parent.children[node.getIndex()] = node;
791
+ }
792
+ }
789
793
  this._nodeMap.set(id, node);
790
794
  yNode.set("parentId", node.parent?.id);
791
795
  node.on("parented", () => {
@@ -793,6 +797,7 @@ class Doc extends Model {
793
797
  });
794
798
  node.on("destroy", () => {
795
799
  this._nodeMap.delete(node.id);
800
+ this._yChildren.delete(node.id);
796
801
  this._debug("destroy", node.id);
797
802
  });
798
803
  this._proxyProps(node, yNode);
@@ -934,7 +939,7 @@ const _0_context = defineMixin((editor) => {
934
939
  function isFrame(value) {
935
940
  return isElement(value) && value.meta.inEditorIs === "Frame";
936
941
  }
937
- function isRootFrame(value) {
942
+ function isTopLevelFrame(value) {
938
943
  return isFrame(value) && Boolean(value.parent?.equal(root.value));
939
944
  }
940
945
  function isVisible(node) {
@@ -977,7 +982,7 @@ const _0_context = defineMixin((editor) => {
977
982
  isRoot,
978
983
  isElement,
979
984
  isFrame,
980
- isRootFrame,
985
+ isTopLevelFrame,
981
986
  isVisible,
982
987
  setVisible,
983
988
  isLock,
@@ -2080,6 +2085,7 @@ const _2_load = defineMixin((editor) => {
2080
2085
  const load = async (source) => {
2081
2086
  state.value = "loading";
2082
2087
  const items = [];
2088
+ let hasLoader = false;
2083
2089
  try {
2084
2090
  for (const loader of loaders.values()) {
2085
2091
  if (await loader.test(source)) {
@@ -2089,13 +2095,14 @@ const _2_load = defineMixin((editor) => {
2089
2095
  } else {
2090
2096
  items.push(res);
2091
2097
  }
2098
+ hasLoader = true;
2092
2099
  break;
2093
2100
  }
2094
2101
  }
2095
2102
  } finally {
2096
2103
  state.value = void 0;
2097
2104
  }
2098
- if (!items.length) {
2105
+ if (!hasLoader) {
2099
2106
  throw new Error(`Failed to load source "${source}"`);
2100
2107
  }
2101
2108
  return items;
@@ -2534,7 +2541,8 @@ const _4_2_frame = defineMixin((editor) => {
2534
2541
  emit,
2535
2542
  selection,
2536
2543
  frames,
2537
- config
2544
+ config,
2545
+ isTopLevelFrame
2538
2546
  } = editor;
2539
2547
  function setCurrentFrame(index = currentFrameIndex.value) {
2540
2548
  index = Math.max(0, Math.min(frames.value.length - 1, index));
@@ -2548,31 +2556,32 @@ const _4_2_frame = defineMixin((editor) => {
2548
2556
  emit("setCurrentFrame", index, oldIndex);
2549
2557
  }
2550
2558
  function handleElementInsideFrame(element) {
2551
- const source = element.getGlobalAabb();
2552
- const aArea = source.getArea();
2559
+ const frame1 = element.findAncestor((node) => isTopLevelFrame(node));
2560
+ const aabb1 = element.getGlobalAabb();
2561
+ const area1 = aabb1.getArea();
2553
2562
  let flag = true;
2554
2563
  for (let i = 0, len = frames.value.length; i < len; i++) {
2555
- const frame = frames.value[i];
2556
- if (element.equal(frame)) {
2564
+ const frame2 = frames.value[i];
2565
+ if (frame2.equal(element)) {
2557
2566
  continue;
2558
2567
  }
2559
- const target = frame.getGlobalAabb();
2560
- if (source && target) {
2561
- if (source.getIntersectionRect(target).getArea() > aArea * 0.5) {
2562
- if (!element.findAncestor((ancestor) => ancestor.equal(frame))) {
2563
- frame.appendChild(element);
2564
- element.style.left = source.x - target.x;
2565
- element.style.top = source.y - target.y;
2568
+ const aabb2 = frame2.getGlobalAabb();
2569
+ if (aabb1 && aabb2) {
2570
+ if (aabb1.getIntersectionRect(aabb2).getArea() > area1 * 0.5) {
2571
+ if (!frame2.equal(frame1)) {
2572
+ frame2.appendChild(element);
2573
+ element.style.left = aabb1.x - aabb2.x;
2574
+ element.style.top = aabb1.y - aabb2.y;
2566
2575
  }
2567
2576
  flag = false;
2568
2577
  break;
2569
2578
  }
2570
2579
  }
2571
2580
  }
2572
- if (flag && element.parent && !element.parent.equal(root.value)) {
2581
+ if (flag && frame1) {
2573
2582
  root.value.moveChild(element, 0);
2574
- element.style.left = source.x;
2575
- element.style.top = source.y;
2583
+ element.style.left = aabb1.x;
2584
+ element.style.top = aabb1.y;
2576
2585
  }
2577
2586
  }
2578
2587
  Object.assign(editor, {
@@ -3295,36 +3304,74 @@ const _clipboard = definePlugin((editor, options) => {
3295
3304
  } = editor;
3296
3305
  const copiedData = ref();
3297
3306
  const useClipboard = options.clipboard !== false && SUPPORTS_CLIPBOARD;
3298
- function toClipboardItem(source) {
3307
+ const copy = async (source) => {
3299
3308
  if (typeof source === "string") {
3300
- const type = "text/plain";
3301
- return new ClipboardItem({ [type]: new Blob([source], { type }) });
3309
+ if (useClipboard) {
3310
+ await navigator.clipboard.write([
3311
+ new ClipboardItem({
3312
+ "text/plain": new Blob([source], { type: "text/plain" })
3313
+ })
3314
+ ]);
3315
+ }
3302
3316
  } else if (source instanceof Blob) {
3303
- return new ClipboardItem({ [source.type]: source });
3304
- } else {
3305
- const type = "text/html";
3306
- const content = `<mce-clipboard>${JSON.stringify(source)}</mce-clipboard>`;
3307
- return new ClipboardItem({
3308
- [type]: new Blob([content], { type })
3309
- });
3310
- }
3311
- }
3312
- const copy = async (source) => {
3313
- if (source === void 0) {
3314
- source = selection.value.map((v) => {
3315
- const json = v.toJSON();
3316
- delete json.style.left;
3317
- delete json.style.top;
3318
- return json;
3319
- });
3320
- }
3321
- if (useClipboard) {
3322
- await navigator.clipboard.write([
3323
- toClipboardItem(source)
3324
- ]);
3317
+ if (useClipboard) {
3318
+ await navigator.clipboard.write([
3319
+ new ClipboardItem({
3320
+ [source.type]: source
3321
+ })
3322
+ ]);
3323
+ }
3325
3324
  } else {
3326
- if (Array.isArray(source)) {
3327
- copiedData.value = source;
3325
+ if (useClipboard) {
3326
+ const textItems = [];
3327
+ let html = "";
3328
+ if (!source) {
3329
+ const selected = selection.value;
3330
+ html += `<mce-clipboard>${JSON.stringify(selected.map((v) => {
3331
+ const json = v.toJSON();
3332
+ if (json.style) {
3333
+ delete json.style.left;
3334
+ delete json.style.top;
3335
+ }
3336
+ return json;
3337
+ }))}</mce-clipboard>`;
3338
+ const cb = (child) => {
3339
+ if (child instanceof Element2D) {
3340
+ const _text2 = child.text.base.toString();
3341
+ textItems.push(_text2);
3342
+ html += `<span>${_text2}</span>`;
3343
+ }
3344
+ return false;
3345
+ };
3346
+ selected.forEach((node) => {
3347
+ cb(node);
3348
+ node.findOne(cb);
3349
+ });
3350
+ } else {
3351
+ html += `<mce-clipboard>${JSON.stringify(source)}</mce-clipboard>`;
3352
+ }
3353
+ const items = {};
3354
+ if (textItems.length) {
3355
+ items["text/plain"] = new Blob([textItems.join("\n")], { type: "text/plain" });
3356
+ }
3357
+ if (html) {
3358
+ items["text/html"] = new Blob([html], { type: "text/html" });
3359
+ }
3360
+ await navigator.clipboard.write([
3361
+ new ClipboardItem(items)
3362
+ ]);
3363
+ } else {
3364
+ if (source === void 0) {
3365
+ source = selection.value.map((v) => {
3366
+ const json = v.toJSON();
3367
+ delete json.style.left;
3368
+ delete json.style.top;
3369
+ return json;
3370
+ });
3371
+ }
3372
+ if (Array.isArray(source)) {
3373
+ copiedData.value = source;
3374
+ }
3328
3375
  }
3329
3376
  }
3330
3377
  };
@@ -3343,10 +3390,17 @@ const _clipboard = definePlugin((editor, options) => {
3343
3390
  async function _paste(items) {
3344
3391
  const elements = [];
3345
3392
  for (const item of items) {
3346
- for (const type of item.types) {
3393
+ const types = [...item.types];
3394
+ const index = types.indexOf("text/html");
3395
+ if (index > -1) {
3396
+ types.splice(index, 1);
3397
+ types.unshift("text/html");
3398
+ }
3399
+ for (const type of types) {
3347
3400
  const blob = await item.getType(type);
3348
3401
  if (await canLoad(blob)) {
3349
3402
  elements.push(...await load(blob));
3403
+ break;
3350
3404
  } else {
3351
3405
  console.warn(`Unhandled clipboard ${blob.type}`, await blob.text());
3352
3406
  }
@@ -4351,7 +4405,8 @@ const _frame = definePlugin((editor) => {
4351
4405
  name: t("frame"),
4352
4406
  meta: {
4353
4407
  inPptIs: "GroupShape",
4354
- inEditorIs: "Frame"
4408
+ inEditorIs: "Frame",
4409
+ inCanvasIs: "Element2D"
4355
4410
  }
4356
4411
  }, {
4357
4412
  position: start,
@@ -15084,7 +15139,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15084
15139
  const {
15085
15140
  pluginsComponents,
15086
15141
  isElement,
15087
- isRootFrame,
15142
+ isTopLevelFrame,
15088
15143
  config,
15089
15144
  drawboardDom,
15090
15145
  renderEngine,
@@ -15163,7 +15218,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15163
15218
  hovered = result;
15164
15219
  }
15165
15220
  }
15166
- if (!(isElement(hovered) && !isRootFrame(hovered))) {
15221
+ if (!(isElement(hovered) && !isTopLevelFrame(hovered))) {
15167
15222
  hovered = void 0;
15168
15223
  cursor = void 0;
15169
15224
  }
@@ -15178,7 +15233,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
15178
15233
  allowRootFrame = false
15179
15234
  } = options;
15180
15235
  function isIncluded(node) {
15181
- return isElement(node) && (allowRootFrame || !isRootFrame(node));
15236
+ return isElement(node) && (allowRootFrame || !isTopLevelFrame(node));
15182
15237
  }
15183
15238
  const drawing = state.value === "drawing";
15184
15239
  const hand = state.value === "hand";
@@ -45,7 +45,7 @@ declare global {
45
45
  isRoot: (value: any) => value is Node;
46
46
  isElement: (value: any) => value is Element2D;
47
47
  isFrame: (value: any) => value is Element2D;
48
- isRootFrame: (value: any) => value is Element2D;
48
+ isTopLevelFrame: (value: any) => value is Element2D;
49
49
  isVisible: (node: Node) => boolean;
50
50
  setVisible: (node: Node, visible: boolean) => void;
51
51
  isLock: (node: Node) => boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mce",
3
3
  "type": "module",
4
- "version": "0.15.3",
4
+ "version": "0.15.5",
5
5
  "description": "The headless canvas editor framework. only the ESM.",
6
6
  "author": "wxm",
7
7
  "license": "MIT",