mce 0.11.2 → 0.11.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.
- package/README.md +2 -1
- package/dist/index.js +230 -187
- package/dist/mixins/0.config/base.d.ts +0 -2
- package/dist/mixins/2.load.d.ts +1 -1
- package/dist/mixins/4.4.doc.d.ts +2 -2
- package/dist/plugins/clipboard.d.ts +2 -1
- package/dist/{mixins/2.export → plugins}/json.d.ts +1 -1
- package/dist/typed-plugins.d.ts +1 -2
- package/dist/utils/helper.d.ts +1 -0
- package/package.json +1 -1
- package/dist/mixins/2.loader/json.d.ts +0 -2
package/README.md
CHANGED
|
@@ -45,8 +45,8 @@ npm i mce
|
|
|
45
45
|
svg(),
|
|
46
46
|
],
|
|
47
47
|
theme: 'system',
|
|
48
|
-
language: 'en',
|
|
49
48
|
viewMode: 'edgeless',
|
|
49
|
+
clipboard: true,
|
|
50
50
|
checkerboard: true,
|
|
51
51
|
pixelGrid: true,
|
|
52
52
|
camera: true,
|
|
@@ -60,6 +60,7 @@ npm i mce
|
|
|
60
60
|
zoomToFitOffset: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
61
61
|
localDb: false,
|
|
62
62
|
customUpload: async (blob) => URL.createObjectURL(blob),
|
|
63
|
+
customContextMenu: (menu) => menu,
|
|
63
64
|
defaultFont: { family: 'SourceHanSansCN-Normal', src: '/SourceHanSansCN-Normal.woff' },
|
|
64
65
|
doc: {
|
|
65
66
|
children: [
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref, computed, watch, markRaw, reactive, warn, shallowRef, inject, provide, defineComponent, createVNode, mergeProps, createElementVNode, toValue, getCurrentInstance, onScopeDispose, createElementBlock, openBlock, Fragment, renderList, unref, normalizeStyle, normalizeClass,
|
|
1
|
+
import { ref, computed, watch, markRaw, reactive, warn, shallowRef, onBeforeUnmount, onMounted, inject, provide, defineComponent, createVNode, mergeProps, createElementVNode, toValue, getCurrentInstance, onScopeDispose, createElementBlock, openBlock, Fragment, renderList, unref, normalizeStyle, normalizeClass, readonly, toRef, useId, onDeactivated, onActivated, useAttrs, createBlock, resolveDynamicComponent, useTemplateRef, renderSlot, Teleport, createCommentVNode, mergeModels, useModel, resolveComponent, withCtx, createTextVNode, toDisplayString, createSlots, normalizeProps, guardReactiveProps, withDirectives, vShow, vModelText, nextTick, withModifiers, onBeforeMount, isRef } from "vue";
|
|
2
2
|
import { useFileDialog, useEventListener, isClient, useResizeObserver as useResizeObserver$1, useLocalStorage, onClickOutside, useMouse, useDebounceFn } from "@vueuse/core";
|
|
3
3
|
import { Node as Node$1, Element2D, Timeline, Engine, Camera2D, DrawboardEffect, IN_BROWSER, clamp, assets, TimelineNode, Transform2D, DEG_TO_RAD, render, Animation } from "modern-canvas";
|
|
4
4
|
import { getObjectValueByPath, setObjectValueByPath, Observable, Reactivable, idGenerator, property, normalizeElement, normalizeTextContent } from "modern-idoc";
|
|
@@ -110,7 +110,6 @@ const _0_config_base = defineMixin((editor, options) => {
|
|
|
110
110
|
config
|
|
111
111
|
} = editor;
|
|
112
112
|
registerConfig("theme", "system");
|
|
113
|
-
registerConfig("language", "en");
|
|
114
113
|
registerConfig("viewMode", "edgeless");
|
|
115
114
|
registerConfig("checkerboard", false);
|
|
116
115
|
registerConfig("pixelGrid", false);
|
|
@@ -1362,6 +1361,18 @@ function findChildrenWithProvide(key, vnode) {
|
|
|
1362
1361
|
}
|
|
1363
1362
|
return [];
|
|
1364
1363
|
}
|
|
1364
|
+
function isInputEvent(event) {
|
|
1365
|
+
if (!event)
|
|
1366
|
+
return false;
|
|
1367
|
+
let path = event.path;
|
|
1368
|
+
if (!path && event.composedPath)
|
|
1369
|
+
path = event.composedPath();
|
|
1370
|
+
if (!path)
|
|
1371
|
+
return false;
|
|
1372
|
+
return path?.some(
|
|
1373
|
+
(el) => ["INPUT", "TEXTAREA", "SELECT"].includes(el?.tagName) || el?.contentEditable === "true"
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1365
1376
|
function propsFactory(props, source) {
|
|
1366
1377
|
return (defaults) => {
|
|
1367
1378
|
return Object.keys(props).reduce((obj, prop) => {
|
|
@@ -1391,18 +1402,6 @@ function uuidv4() {
|
|
|
1391
1402
|
const defaultHotkeys = [
|
|
1392
1403
|
{ command: "cancel", key: "Esc", editable: false }
|
|
1393
1404
|
];
|
|
1394
|
-
function isInputEvent(event) {
|
|
1395
|
-
if (!event)
|
|
1396
|
-
return false;
|
|
1397
|
-
let path = event.path;
|
|
1398
|
-
if (!path && event.composedPath)
|
|
1399
|
-
path = event.composedPath();
|
|
1400
|
-
if (!path)
|
|
1401
|
-
return false;
|
|
1402
|
-
return path?.some(
|
|
1403
|
-
(el) => ["INPUT", "TEXTAREA", "SELECT"].includes(el?.tagName) || el?.contentEditable === "true"
|
|
1404
|
-
);
|
|
1405
|
-
}
|
|
1406
1405
|
const _1_hotkey = defineMixin((editor) => {
|
|
1407
1406
|
const {
|
|
1408
1407
|
registerConfig
|
|
@@ -1874,69 +1873,6 @@ const _2_export = defineMixin((editor) => {
|
|
|
1874
1873
|
to
|
|
1875
1874
|
});
|
|
1876
1875
|
});
|
|
1877
|
-
const _2_export_json = defineMixin((editor) => {
|
|
1878
|
-
const {
|
|
1879
|
-
registerExporter,
|
|
1880
|
-
getAabb,
|
|
1881
|
-
selection,
|
|
1882
|
-
root,
|
|
1883
|
-
getTimeRange
|
|
1884
|
-
} = editor;
|
|
1885
|
-
registerExporter({
|
|
1886
|
-
name: "json",
|
|
1887
|
-
copyAs: (exported) => JSON.stringify(exported),
|
|
1888
|
-
saveAs: (exported) => new Blob([JSON.stringify(exported)], { type: "application/json" }),
|
|
1889
|
-
handle: (options) => {
|
|
1890
|
-
const {
|
|
1891
|
-
selected = false,
|
|
1892
|
-
scale = 1
|
|
1893
|
-
} = options;
|
|
1894
|
-
let id = idGenerator();
|
|
1895
|
-
let elements = [];
|
|
1896
|
-
if (Array.isArray(selected)) {
|
|
1897
|
-
elements = selected;
|
|
1898
|
-
} else {
|
|
1899
|
-
if (selected === true) {
|
|
1900
|
-
elements = selection.value;
|
|
1901
|
-
}
|
|
1902
|
-
if (elements.length === 0 && root.value) {
|
|
1903
|
-
if (root.value.meta.id) {
|
|
1904
|
-
id = root.value.meta.id;
|
|
1905
|
-
}
|
|
1906
|
-
elements = root.value.children;
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
const box = getAabb(elements, "parent");
|
|
1910
|
-
console.log(box);
|
|
1911
|
-
return {
|
|
1912
|
-
id,
|
|
1913
|
-
style: {
|
|
1914
|
-
width: box.width * scale,
|
|
1915
|
-
height: box.height * scale,
|
|
1916
|
-
transformOrigin: "left top",
|
|
1917
|
-
transform: `scale(${scale})`
|
|
1918
|
-
},
|
|
1919
|
-
children: elements.map((el) => {
|
|
1920
|
-
const json = el.toJSON();
|
|
1921
|
-
if (box.left) {
|
|
1922
|
-
json.style.left = (json.style.left ?? 0) - box.left;
|
|
1923
|
-
}
|
|
1924
|
-
if (box.top) {
|
|
1925
|
-
json.style.top = (json.style.top ?? 0) - box.top;
|
|
1926
|
-
}
|
|
1927
|
-
json.meta ??= {};
|
|
1928
|
-
json.meta.inPptIs = "Slide";
|
|
1929
|
-
return json;
|
|
1930
|
-
}),
|
|
1931
|
-
meta: {
|
|
1932
|
-
inPptIs: "Pptx",
|
|
1933
|
-
inCanvasIs: "Element2D",
|
|
1934
|
-
...getTimeRange(elements)
|
|
1935
|
-
}
|
|
1936
|
-
};
|
|
1937
|
-
}
|
|
1938
|
-
});
|
|
1939
|
-
});
|
|
1940
1876
|
const _2_load = defineMixin((editor) => {
|
|
1941
1877
|
const {
|
|
1942
1878
|
state
|
|
@@ -1962,15 +1898,15 @@ const _2_load = defineMixin((editor) => {
|
|
|
1962
1898
|
};
|
|
1963
1899
|
const load = async (source) => {
|
|
1964
1900
|
state.value = "loading";
|
|
1965
|
-
|
|
1901
|
+
const items = [];
|
|
1966
1902
|
try {
|
|
1967
1903
|
for (const loader of loaders.value.values()) {
|
|
1968
1904
|
if (await loader.test(source)) {
|
|
1969
1905
|
const res = await loader.load(source);
|
|
1970
1906
|
if (Array.isArray(res)) {
|
|
1971
|
-
|
|
1907
|
+
items.push(...res);
|
|
1972
1908
|
} else {
|
|
1973
|
-
|
|
1909
|
+
items.push(res);
|
|
1974
1910
|
}
|
|
1975
1911
|
break;
|
|
1976
1912
|
}
|
|
@@ -1978,10 +1914,10 @@ const _2_load = defineMixin((editor) => {
|
|
|
1978
1914
|
} finally {
|
|
1979
1915
|
state.value = void 0;
|
|
1980
1916
|
}
|
|
1981
|
-
if (!
|
|
1917
|
+
if (!items.length) {
|
|
1982
1918
|
throw new Error(`Failed to load source "${source}"`);
|
|
1983
1919
|
}
|
|
1984
|
-
return
|
|
1920
|
+
return items;
|
|
1985
1921
|
};
|
|
1986
1922
|
const openFileDialog = (options = {}) => {
|
|
1987
1923
|
const {
|
|
@@ -2013,36 +1949,6 @@ const _2_load = defineMixin((editor) => {
|
|
|
2013
1949
|
openFileDialog
|
|
2014
1950
|
});
|
|
2015
1951
|
});
|
|
2016
|
-
const _2_loader_json = defineMixin((editor) => {
|
|
2017
|
-
const {
|
|
2018
|
-
registerLoader
|
|
2019
|
-
} = editor;
|
|
2020
|
-
const RE = /\.json$/i;
|
|
2021
|
-
registerLoader({
|
|
2022
|
-
name: "json",
|
|
2023
|
-
accept: ".json",
|
|
2024
|
-
test: (source) => {
|
|
2025
|
-
if (source instanceof Blob) {
|
|
2026
|
-
if (source.type.startsWith("application/json")) {
|
|
2027
|
-
return true;
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
if (source instanceof File) {
|
|
2031
|
-
if (RE.test(source.name)) {
|
|
2032
|
-
return true;
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
return false;
|
|
2036
|
-
},
|
|
2037
|
-
load: async (source) => {
|
|
2038
|
-
const json = JSON.parse(await source.text());
|
|
2039
|
-
if ("version" in json && "elements" in json) {
|
|
2040
|
-
console.log(json);
|
|
2041
|
-
}
|
|
2042
|
-
return json;
|
|
2043
|
-
}
|
|
2044
|
-
});
|
|
2045
|
-
});
|
|
2046
1952
|
const _3_view = defineMixin((editor) => {
|
|
2047
1953
|
const {
|
|
2048
1954
|
renderEngine,
|
|
@@ -2549,7 +2455,11 @@ const _4_4_doc = defineMixin((editor, options) => {
|
|
|
2549
2455
|
}
|
|
2550
2456
|
}
|
|
2551
2457
|
if (source && typeof source !== "string") {
|
|
2552
|
-
|
|
2458
|
+
if (Array.isArray(source)) {
|
|
2459
|
+
doc2.set({ children: source });
|
|
2460
|
+
} else {
|
|
2461
|
+
doc2.set(source);
|
|
2462
|
+
}
|
|
2553
2463
|
}
|
|
2554
2464
|
});
|
|
2555
2465
|
doc2.on("update", throttle((update, origin) => emit("updateDoc", update, origin), 200));
|
|
@@ -2559,8 +2469,17 @@ const _4_4_doc = defineMixin((editor, options) => {
|
|
|
2559
2469
|
let id;
|
|
2560
2470
|
if (typeof source === "string") {
|
|
2561
2471
|
id = source;
|
|
2562
|
-
} else {
|
|
2563
|
-
|
|
2472
|
+
} else if (source) {
|
|
2473
|
+
if (Array.isArray(source) && source.length === 1) {
|
|
2474
|
+
source = source[0];
|
|
2475
|
+
}
|
|
2476
|
+
if (!Array.isArray(source)) {
|
|
2477
|
+
if (source.meta?.inEditorIs === "Doc") {
|
|
2478
|
+
id = source.id;
|
|
2479
|
+
} else {
|
|
2480
|
+
source = [source];
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2564
2483
|
}
|
|
2565
2484
|
const _doc = new Doc(id);
|
|
2566
2485
|
state.value = "loading";
|
|
@@ -2576,11 +2495,7 @@ const _4_4_doc = defineMixin((editor, options) => {
|
|
|
2576
2495
|
return _doc;
|
|
2577
2496
|
};
|
|
2578
2497
|
const loadDoc = async (source) => {
|
|
2579
|
-
|
|
2580
|
-
if (loaded.meta?.inEditorIs !== "Doc") {
|
|
2581
|
-
loaded = { id: idGenerator(), children: [loaded] };
|
|
2582
|
-
}
|
|
2583
|
-
const _doc = await setDoc(loaded);
|
|
2498
|
+
const _doc = await setDoc(await load(source));
|
|
2584
2499
|
emit("loadDoc", _doc, source);
|
|
2585
2500
|
return _doc;
|
|
2586
2501
|
};
|
|
@@ -2726,9 +2641,7 @@ const mixins = [
|
|
|
2726
2641
|
_1_upload,
|
|
2727
2642
|
_2_box,
|
|
2728
2643
|
_2_export,
|
|
2729
|
-
_2_export_json,
|
|
2730
2644
|
_2_load,
|
|
2731
|
-
_2_loader_json,
|
|
2732
2645
|
_3_view,
|
|
2733
2646
|
_4_0_text,
|
|
2734
2647
|
_4_1_lock,
|
|
@@ -4054,7 +3967,12 @@ const _clipboard = definePlugin((editor, options) => {
|
|
|
4054
3967
|
const useClipboard = options.clipboard !== false && SUPPORTS_CLIPBOARD;
|
|
4055
3968
|
const copy = async (data) => {
|
|
4056
3969
|
if (data === void 0) {
|
|
4057
|
-
data = selection.value.
|
|
3970
|
+
data = selection.value.map((v) => {
|
|
3971
|
+
const json = v.toJSON();
|
|
3972
|
+
delete json.style.left;
|
|
3973
|
+
delete json.style.top;
|
|
3974
|
+
return json;
|
|
3975
|
+
});
|
|
4058
3976
|
}
|
|
4059
3977
|
if (useClipboard) {
|
|
4060
3978
|
if (Array.isArray(data)) {
|
|
@@ -4077,46 +3995,69 @@ const _clipboard = definePlugin((editor, options) => {
|
|
|
4077
3995
|
}
|
|
4078
3996
|
}
|
|
4079
3997
|
};
|
|
4080
|
-
async
|
|
3998
|
+
const cut = async () => {
|
|
4081
3999
|
await copy();
|
|
4082
4000
|
exec("delete");
|
|
4083
|
-
}
|
|
4084
|
-
let
|
|
4085
|
-
function
|
|
4086
|
-
if (!lock) {
|
|
4087
|
-
lock = true;
|
|
4088
|
-
}
|
|
4001
|
+
};
|
|
4002
|
+
let locked = false;
|
|
4003
|
+
function getPasteLock() {
|
|
4089
4004
|
return {
|
|
4090
|
-
|
|
4091
|
-
|
|
4005
|
+
locked,
|
|
4006
|
+
lock: () => locked = true,
|
|
4007
|
+
unlock: () => locked = false
|
|
4092
4008
|
};
|
|
4093
4009
|
}
|
|
4094
|
-
async function
|
|
4095
|
-
const items = source ?? await navigator.clipboard.read();
|
|
4010
|
+
async function _paste(items) {
|
|
4096
4011
|
const elements = [];
|
|
4097
4012
|
for (const item of items) {
|
|
4098
4013
|
for (const type of item.types) {
|
|
4099
4014
|
const blob = await item.getType(type);
|
|
4100
4015
|
if (await canLoad(blob)) {
|
|
4101
|
-
elements.push(await load(blob));
|
|
4016
|
+
elements.push(...await load(blob));
|
|
4102
4017
|
} else {
|
|
4103
4018
|
console.warn(`Unhandled clipboard ${blob.type}`, await blob.text());
|
|
4104
4019
|
}
|
|
4105
4020
|
}
|
|
4106
4021
|
}
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4022
|
+
if (elements.length) {
|
|
4023
|
+
addElement(elements, {
|
|
4024
|
+
inPointerPosition: true,
|
|
4025
|
+
active: true,
|
|
4026
|
+
regenId: true
|
|
4027
|
+
});
|
|
4028
|
+
}
|
|
4112
4029
|
}
|
|
4113
|
-
async
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4030
|
+
const paste = async (source) => {
|
|
4031
|
+
if (source) {
|
|
4032
|
+
const { unlock, lock } = getPasteLock();
|
|
4033
|
+
lock();
|
|
4034
|
+
let items = [];
|
|
4035
|
+
if (source instanceof DataTransfer) {
|
|
4036
|
+
for (const item of source.items) {
|
|
4037
|
+
switch (item.kind) {
|
|
4038
|
+
case "file": {
|
|
4039
|
+
const file = item.getAsFile();
|
|
4040
|
+
if (file) {
|
|
4041
|
+
items.push(new ClipboardItem({ [file.type]: file }));
|
|
4042
|
+
}
|
|
4043
|
+
break;
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
} else {
|
|
4048
|
+
items = source;
|
|
4049
|
+
}
|
|
4050
|
+
if (items.length) {
|
|
4051
|
+
await _paste(items);
|
|
4052
|
+
} else {
|
|
4053
|
+
unlock();
|
|
4054
|
+
}
|
|
4055
|
+
} else {
|
|
4056
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
4057
|
+
const { locked: locked2, unlock } = getPasteLock();
|
|
4058
|
+
if (!locked2) {
|
|
4118
4059
|
if (useClipboard) {
|
|
4119
|
-
await
|
|
4060
|
+
await _paste(await navigator.clipboard.read());
|
|
4120
4061
|
} else if (copiedData.value) {
|
|
4121
4062
|
if (Array.isArray(copiedData.value)) {
|
|
4122
4063
|
addElement(copiedData.value?.map((el) => cloneDeep(el)) ?? [], {
|
|
@@ -4126,13 +4067,11 @@ const _clipboard = definePlugin((editor, options) => {
|
|
|
4126
4067
|
});
|
|
4127
4068
|
}
|
|
4128
4069
|
}
|
|
4129
|
-
}
|
|
4070
|
+
} else {
|
|
4130
4071
|
unlock();
|
|
4131
4072
|
}
|
|
4132
|
-
} else {
|
|
4133
|
-
unlock();
|
|
4134
4073
|
}
|
|
4135
|
-
}
|
|
4074
|
+
};
|
|
4136
4075
|
async function duplicate() {
|
|
4137
4076
|
await copy();
|
|
4138
4077
|
await paste();
|
|
@@ -4156,31 +4095,16 @@ const _clipboard = definePlugin((editor, options) => {
|
|
|
4156
4095
|
],
|
|
4157
4096
|
setup: () => {
|
|
4158
4097
|
if (useClipboard) {
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
pasteLock();
|
|
4163
|
-
const clipboardItems = [];
|
|
4164
|
-
for (const item of items) {
|
|
4165
|
-
switch (item.kind) {
|
|
4166
|
-
case "file": {
|
|
4167
|
-
const file = item.getAsFile();
|
|
4168
|
-
if (file) {
|
|
4169
|
-
clipboardItems.push(
|
|
4170
|
-
new ClipboardItem({
|
|
4171
|
-
[file.type]: file
|
|
4172
|
-
})
|
|
4173
|
-
);
|
|
4174
|
-
}
|
|
4175
|
-
break;
|
|
4176
|
-
}
|
|
4177
|
-
}
|
|
4178
|
-
}
|
|
4179
|
-
await onPaste(
|
|
4180
|
-
clipboardItems.length ? clipboardItems : void 0
|
|
4181
|
-
);
|
|
4098
|
+
async function onPaste(e) {
|
|
4099
|
+
if (isInputEvent(e)) {
|
|
4100
|
+
return;
|
|
4182
4101
|
}
|
|
4183
|
-
|
|
4102
|
+
if (e.clipboardData) {
|
|
4103
|
+
await paste(e.clipboardData);
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
window.addEventListener("paste", onPaste);
|
|
4107
|
+
onBeforeUnmount(() => window.removeEventListener("paste", onPaste));
|
|
4184
4108
|
}
|
|
4185
4109
|
}
|
|
4186
4110
|
};
|
|
@@ -4609,7 +4533,7 @@ const _import = definePlugin((editor) => {
|
|
|
4609
4533
|
} = editor;
|
|
4610
4534
|
const _import2 = async (options = {}) => {
|
|
4611
4535
|
const files = await openFileDialog({ multiple: true });
|
|
4612
|
-
return addElement(await Promise.all(files.map((file) => load(file))), {
|
|
4536
|
+
return addElement((await Promise.all(files.map((file) => load(file)))).flat(), {
|
|
4613
4537
|
...options,
|
|
4614
4538
|
sizeToFit: true,
|
|
4615
4539
|
positionToFit: true
|
|
@@ -4622,6 +4546,125 @@ const _import = definePlugin((editor) => {
|
|
|
4622
4546
|
],
|
|
4623
4547
|
hotkeys: [
|
|
4624
4548
|
{ command: "import", key: "CmdOrCtrl+i" }
|
|
4549
|
+
],
|
|
4550
|
+
setup: () => {
|
|
4551
|
+
const {
|
|
4552
|
+
drawboardPointer,
|
|
4553
|
+
drawboardDom,
|
|
4554
|
+
exec
|
|
4555
|
+
} = editor;
|
|
4556
|
+
function onDragover(e) {
|
|
4557
|
+
e.preventDefault();
|
|
4558
|
+
drawboardPointer.value = { x: e.clientX, y: e.clientY };
|
|
4559
|
+
if (e.dataTransfer) {
|
|
4560
|
+
e.dataTransfer.dropEffect = "copy";
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
async function onDrop(e) {
|
|
4564
|
+
e.preventDefault();
|
|
4565
|
+
if (e.dataTransfer) {
|
|
4566
|
+
await exec("paste", e.dataTransfer);
|
|
4567
|
+
}
|
|
4568
|
+
}
|
|
4569
|
+
onMounted(() => {
|
|
4570
|
+
drawboardDom.value?.addEventListener("dragover", onDragover);
|
|
4571
|
+
drawboardDom.value?.addEventListener("drop", onDrop);
|
|
4572
|
+
});
|
|
4573
|
+
onBeforeUnmount(() => {
|
|
4574
|
+
drawboardDom.value?.removeEventListener("dragover", onDragover);
|
|
4575
|
+
drawboardDom.value?.removeEventListener("drop", onDrop);
|
|
4576
|
+
});
|
|
4577
|
+
}
|
|
4578
|
+
};
|
|
4579
|
+
});
|
|
4580
|
+
const _json = definePlugin((editor) => {
|
|
4581
|
+
const {
|
|
4582
|
+
getAabb,
|
|
4583
|
+
selection,
|
|
4584
|
+
root,
|
|
4585
|
+
getTimeRange
|
|
4586
|
+
} = editor;
|
|
4587
|
+
const RE = /\.json$/i;
|
|
4588
|
+
return {
|
|
4589
|
+
name: "mce:json",
|
|
4590
|
+
loaders: [
|
|
4591
|
+
{
|
|
4592
|
+
name: "json",
|
|
4593
|
+
accept: ".json",
|
|
4594
|
+
test: (source) => {
|
|
4595
|
+
if (source instanceof Blob) {
|
|
4596
|
+
if (source.type.startsWith("application/json")) {
|
|
4597
|
+
return true;
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
if (source instanceof File) {
|
|
4601
|
+
if (RE.test(source.name)) {
|
|
4602
|
+
return true;
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
return false;
|
|
4606
|
+
},
|
|
4607
|
+
load: async (source) => {
|
|
4608
|
+
const json = JSON.parse(await source.text());
|
|
4609
|
+
if ("version" in json && "elements" in json) {
|
|
4610
|
+
console.log(json);
|
|
4611
|
+
}
|
|
4612
|
+
return json;
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
],
|
|
4616
|
+
exporters: [
|
|
4617
|
+
{
|
|
4618
|
+
name: "json",
|
|
4619
|
+
handle: (options) => {
|
|
4620
|
+
const {
|
|
4621
|
+
selected = false,
|
|
4622
|
+
scale = 1
|
|
4623
|
+
} = options;
|
|
4624
|
+
let id = idGenerator();
|
|
4625
|
+
let elements = [];
|
|
4626
|
+
if (Array.isArray(selected)) {
|
|
4627
|
+
elements = selected;
|
|
4628
|
+
} else {
|
|
4629
|
+
if (selected === true) {
|
|
4630
|
+
elements = selection.value;
|
|
4631
|
+
}
|
|
4632
|
+
if (elements.length === 0 && root.value) {
|
|
4633
|
+
if (root.value.meta.id) {
|
|
4634
|
+
id = root.value.meta.id;
|
|
4635
|
+
}
|
|
4636
|
+
elements = root.value.children;
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
const box = getAabb(elements, "parent");
|
|
4640
|
+
return {
|
|
4641
|
+
id,
|
|
4642
|
+
style: {
|
|
4643
|
+
width: box.width * scale,
|
|
4644
|
+
height: box.height * scale,
|
|
4645
|
+
transformOrigin: "left top",
|
|
4646
|
+
transform: `scale(${scale})`
|
|
4647
|
+
},
|
|
4648
|
+
children: elements.map((el) => {
|
|
4649
|
+
const json = el.toJSON();
|
|
4650
|
+
if (box.left) {
|
|
4651
|
+
json.style.left = (json.style.left ?? 0) - box.left;
|
|
4652
|
+
}
|
|
4653
|
+
if (box.top) {
|
|
4654
|
+
json.style.top = (json.style.top ?? 0) - box.top;
|
|
4655
|
+
}
|
|
4656
|
+
json.meta ??= {};
|
|
4657
|
+
json.meta.inPptIs = "Slide";
|
|
4658
|
+
return json;
|
|
4659
|
+
}),
|
|
4660
|
+
meta: {
|
|
4661
|
+
inPptIs: "Pptx",
|
|
4662
|
+
inCanvasIs: "Element2D",
|
|
4663
|
+
...getTimeRange(elements)
|
|
4664
|
+
}
|
|
4665
|
+
};
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4625
4668
|
]
|
|
4626
4669
|
};
|
|
4627
4670
|
});
|
|
@@ -4778,25 +4821,26 @@ const _menu = definePlugin((editor, options) => {
|
|
|
4778
4821
|
{ key: "open" },
|
|
4779
4822
|
{ type: "divider" },
|
|
4780
4823
|
{ key: "import" },
|
|
4781
|
-
exportMenu.value
|
|
4782
|
-
]
|
|
4824
|
+
exportMenu.value.children.length && exportMenu.value
|
|
4825
|
+
].filter(Boolean)
|
|
4783
4826
|
}));
|
|
4784
4827
|
const historyMenus = computed(() => [
|
|
4785
4828
|
{ key: "undo", disabled: !canUndo.value },
|
|
4786
4829
|
{ key: "redo", disabled: !canRedo.value }
|
|
4787
4830
|
]);
|
|
4831
|
+
const copyAsMenu = computed(() => ({
|
|
4832
|
+
key: "copyAs",
|
|
4833
|
+
disabled: !hasSelected.value,
|
|
4834
|
+
children: [...exporters.value.values()].filter((v) => Boolean(v.copyAs)).map((v) => ({ key: `copyAs:${v.name}` }))
|
|
4835
|
+
}));
|
|
4788
4836
|
const editMenus1 = computed(() => [
|
|
4789
4837
|
{ key: "copy", disabled: !hasSelected.value },
|
|
4790
|
-
|
|
4791
|
-
key: "copyAs",
|
|
4792
|
-
disabled: !hasSelected.value,
|
|
4793
|
-
children: [...exporters.value.values()].filter((v) => Boolean(v.copyAs)).map((v) => ({ key: `copyAs:${v.name}` }))
|
|
4794
|
-
},
|
|
4838
|
+
copyAsMenu.value.children.length && copyAsMenu.value,
|
|
4795
4839
|
{ key: "cut", disabled: !hasSelected.value },
|
|
4796
4840
|
{ key: "paste" },
|
|
4797
4841
|
{ key: "duplicate", disabled: !hasSelected.value },
|
|
4798
4842
|
{ key: "delete", disabled: !hasSelected.value }
|
|
4799
|
-
]);
|
|
4843
|
+
].filter(Boolean));
|
|
4800
4844
|
const selectMenu = computed(() => ({
|
|
4801
4845
|
key: "select",
|
|
4802
4846
|
children: [
|
|
@@ -4988,10 +5032,7 @@ const _new = definePlugin((editor) => {
|
|
|
4988
5032
|
setDoc
|
|
4989
5033
|
} = editor;
|
|
4990
5034
|
function _new2() {
|
|
4991
|
-
setDoc(
|
|
4992
|
-
id: idGenerator(),
|
|
4993
|
-
children: []
|
|
4994
|
-
});
|
|
5035
|
+
setDoc([]);
|
|
4995
5036
|
}
|
|
4996
5037
|
return {
|
|
4997
5038
|
name: "mce:new",
|
|
@@ -5379,6 +5420,7 @@ const plugins = [
|
|
|
5379
5420
|
_html,
|
|
5380
5421
|
_image,
|
|
5381
5422
|
_import,
|
|
5423
|
+
_json,
|
|
5382
5424
|
_layerOrder,
|
|
5383
5425
|
_layerPosition,
|
|
5384
5426
|
_lock,
|
|
@@ -8872,6 +8914,7 @@ export {
|
|
|
8872
8914
|
imageExts,
|
|
8873
8915
|
imageMimeTypeExtMap,
|
|
8874
8916
|
isClickInsideElement,
|
|
8917
|
+
isInputEvent,
|
|
8875
8918
|
isMac,
|
|
8876
8919
|
isOverlappingAabb,
|
|
8877
8920
|
isOverlappingObb,
|
|
@@ -3,13 +3,11 @@ declare global {
|
|
|
3
3
|
interface Options extends Partial<Config> {
|
|
4
4
|
}
|
|
5
5
|
type Theme = 'system' | 'light' | 'dark';
|
|
6
|
-
type Language = string;
|
|
7
6
|
type ViewMode = 'frame' | 'edgeless';
|
|
8
7
|
type TypographyStrategy = 'autoHeight' | 'autoWidth' | 'fixedWidthHeight' | 'autoFontSize';
|
|
9
8
|
type HandleShape = 'rect' | 'circle';
|
|
10
9
|
interface Config {
|
|
11
10
|
theme: Theme;
|
|
12
|
-
language: Language;
|
|
13
11
|
viewMode: ViewMode;
|
|
14
12
|
checkerboard: boolean;
|
|
15
13
|
pixelGrid: boolean;
|
package/dist/mixins/2.load.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ declare global {
|
|
|
13
13
|
registerLoader: (value: Loader | Loader[]) => void;
|
|
14
14
|
unregisterLoader: (name: string) => void;
|
|
15
15
|
canLoad: (source: any) => Promise<boolean>;
|
|
16
|
-
load: <T = NormalizedElement>(source: any) => Promise<T>;
|
|
16
|
+
load: <T = NormalizedElement>(source: any) => Promise<T[]>;
|
|
17
17
|
openFileDialog: (options?: {
|
|
18
18
|
multiple?: boolean;
|
|
19
19
|
}) => Promise<File[]>;
|
package/dist/mixins/4.4.doc.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Document } from 'modern-idoc';
|
|
1
|
+
import type { Document, Element } from 'modern-idoc';
|
|
2
2
|
import { Doc } from '../models';
|
|
3
3
|
declare global {
|
|
4
4
|
namespace Mce {
|
|
5
5
|
interface Editor {
|
|
6
6
|
getDoc: () => JsonData;
|
|
7
|
-
setDoc: (doc: Document | string) => Promise<Doc>;
|
|
7
|
+
setDoc: (doc: Document | Element[] | string) => Promise<Doc>;
|
|
8
8
|
loadDoc: (source: any) => Promise<Doc>;
|
|
9
9
|
clearDoc: () => void;
|
|
10
10
|
}
|
|
@@ -7,10 +7,11 @@ declare global {
|
|
|
7
7
|
paste: [event: KeyboardEvent];
|
|
8
8
|
duplicate: [event: KeyboardEvent];
|
|
9
9
|
}
|
|
10
|
+
type PasteSource = DataTransfer | ClipboardItem[];
|
|
10
11
|
interface Commands {
|
|
11
12
|
copy: (data?: any) => Promise<void>;
|
|
12
13
|
cut: () => Promise<void>;
|
|
13
|
-
paste: () => Promise<void>;
|
|
14
|
+
paste: (source?: PasteSource) => Promise<void>;
|
|
14
15
|
duplicate: () => Promise<void>;
|
|
15
16
|
}
|
|
16
17
|
interface Editor {
|
package/dist/typed-plugins.d.ts
CHANGED
|
@@ -15,9 +15,7 @@ import './mixins/1.timeline'
|
|
|
15
15
|
import './mixins/1.upload'
|
|
16
16
|
import './mixins/2.box'
|
|
17
17
|
import './mixins/2.export'
|
|
18
|
-
import './mixins/2.export/json'
|
|
19
18
|
import './mixins/2.load'
|
|
20
|
-
import './mixins/2.loader/json'
|
|
21
19
|
import './mixins/3.view'
|
|
22
20
|
import './mixins/4.0.text'
|
|
23
21
|
import './mixins/4.1.lock'
|
|
@@ -37,6 +35,7 @@ import './plugins/history'
|
|
|
37
35
|
import './plugins/html'
|
|
38
36
|
import './plugins/image'
|
|
39
37
|
import './plugins/import'
|
|
38
|
+
import './plugins/json'
|
|
40
39
|
import './plugins/layerOrder'
|
|
41
40
|
import './plugins/layerPosition'
|
|
42
41
|
import './plugins/lock'
|
package/dist/utils/helper.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export declare function convertToUnit(str: number, unit?: string): string;
|
|
|
10
10
|
export declare function convertToUnit(str: string | number | null | undefined, unit?: string): string | undefined;
|
|
11
11
|
export declare function templateRef(): TemplateRef;
|
|
12
12
|
export declare function findChildrenWithProvide(key: InjectionKey<any> | symbol, vnode?: VNodeChild): ComponentInternalInstance[];
|
|
13
|
+
export declare function isInputEvent(event?: Event): boolean;
|
package/package.json
CHANGED