@tmagic/editor 1.0.0-beta.1 → 1.0.0-beta.12

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 (53) hide show
  1. package/LICENSE +5432 -0
  2. package/README.md +1 -0
  3. package/dist/style.css +53 -24
  4. package/dist/tmagic-editor.es.js +901 -412
  5. package/dist/tmagic-editor.es.js.map +1 -1
  6. package/dist/tmagic-editor.umd.js +918 -412
  7. package/dist/tmagic-editor.umd.js.map +1 -1
  8. package/dist/types/src/Editor.vue.d.ts +5 -5
  9. package/dist/types/src/components/ScrollViewer.vue.d.ts +23 -0
  10. package/dist/types/src/layouts/CodeEditor.vue.d.ts +5 -4
  11. package/dist/types/src/layouts/NavMenu.vue.d.ts +2 -1
  12. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
  13. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +10 -3
  14. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +8 -3
  15. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +77 -42
  16. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +4 -10
  17. package/dist/types/src/services/BaseService.d.ts +4 -1
  18. package/dist/types/src/services/editor.d.ts +11 -4
  19. package/dist/types/src/services/props.d.ts +1 -1
  20. package/dist/types/src/services/ui.d.ts +10 -3
  21. package/dist/types/src/type.d.ts +23 -7
  22. package/dist/types/src/utils/editor.d.ts +3 -3
  23. package/dist/types/src/utils/scroll-viewer.d.ts +35 -0
  24. package/package.json +25 -12
  25. package/src/Editor.vue +5 -5
  26. package/src/components/ScrollViewer.vue +66 -0
  27. package/src/components/ToolButton.vue +5 -3
  28. package/src/layouts/AddPageBox.vue +3 -1
  29. package/src/layouts/CodeEditor.vue +35 -59
  30. package/src/layouts/NavMenu.vue +7 -3
  31. package/src/layouts/PropsPanel.vue +6 -10
  32. package/src/layouts/sidebar/ComponentListPanel.vue +2 -2
  33. package/src/layouts/sidebar/LayerMenu.vue +15 -39
  34. package/src/layouts/sidebar/LayerPanel.vue +63 -16
  35. package/src/layouts/workspace/PageBar.vue +113 -14
  36. package/src/layouts/workspace/Stage.vue +67 -61
  37. package/src/layouts/workspace/ViewerMenu.vue +5 -3
  38. package/src/layouts/workspace/Workspace.vue +45 -34
  39. package/src/services/BaseService.ts +70 -22
  40. package/src/services/editor.ts +111 -55
  41. package/src/services/props.ts +2 -1
  42. package/src/services/ui.ts +42 -5
  43. package/src/theme/common/var.scss +2 -2
  44. package/src/theme/layer-panel.scss +9 -0
  45. package/src/theme/nav-menu.scss +3 -3
  46. package/src/theme/page-bar.scss +21 -2
  47. package/src/theme/props-panel.scss +8 -0
  48. package/src/theme/stage.scss +8 -7
  49. package/src/type.ts +26 -7
  50. package/src/utils/editor.ts +30 -27
  51. package/src/utils/props.ts +1 -1
  52. package/src/utils/scroll-viewer.ts +216 -0
  53. package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
@@ -1,12 +1,32 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue'), require('serialize-javascript'), require('@tmagic/utils'), require('@element-plus/icons'), require('lodash-es'), require('events'), require('@tmagic/core'), require('element-plus'), require('@tmagic/stage')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'vue', 'serialize-javascript', '@tmagic/utils', '@element-plus/icons', 'lodash-es', 'events', '@tmagic/core', 'element-plus', '@tmagic/stage'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicEditor = {}, global.vue, global.serialize, global.utils, global.icons, global.lodashEs, global.events, global.core, global.elementPlus, global.StageCore));
5
- })(this, (function (exports, vue, serialize, utils, icons, lodashEs, events, core, elementPlus, StageCore) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue'), require('serialize-javascript'), require('monaco-editor'), require('@element-plus/icons'), require('@tmagic/schema'), require('lodash-es'), require('@tmagic/utils'), require('events'), require('@tmagic/core'), require('element-plus'), require('keycon'), require('@tmagic/stage')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'vue', 'serialize-javascript', 'monaco-editor', '@element-plus/icons', '@tmagic/schema', 'lodash-es', '@tmagic/utils', 'events', '@tmagic/core', 'element-plus', 'keycon', '@tmagic/stage'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicEditor = {}, global.vue, global.serialize, global.monaco, global.icons, global.schema, global.lodashEs, global.utils, global.events, global.core, global.elementPlus, global.KeyController, global.StageCore));
5
+ })(this, (function (exports, vue, serialize, monaco, icons, schema, lodashEs, utils, events, core, elementPlus, KeyController, StageCore) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = {__proto__: null, [Symbol.toStringTag]: 'Module'};
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n["default"] = e;
24
+ return Object.freeze(n);
25
+ }
26
+
9
27
  var serialize__default = /*#__PURE__*/_interopDefaultLegacy(serialize);
28
+ var monaco__namespace = /*#__PURE__*/_interopNamespace(monaco);
29
+ var KeyController__default = /*#__PURE__*/_interopDefaultLegacy(KeyController);
10
30
  var StageCore__default = /*#__PURE__*/_interopDefaultLegacy(StageCore);
11
31
 
12
32
  var _export_sfc = (sfc, props) => {
@@ -17,7 +37,7 @@
17
37
  return target;
18
38
  };
19
39
 
20
- const _sfc_main$j = vue.defineComponent({
40
+ const _sfc_main$k = vue.defineComponent({
21
41
  name: "m-fields-vs-code",
22
42
  props: ["model", "name", "config", "prop"],
23
43
  emits: ["change"],
@@ -34,7 +54,7 @@
34
54
  };
35
55
  }
36
56
  });
37
- function _sfc_render$j(_ctx, _cache, $props, $setup, $data, $options) {
57
+ function _sfc_render$k(_ctx, _cache, $props, $setup, $data, $options) {
38
58
  const _component_magic_code_editor = vue.resolveComponent("magic-code-editor");
39
59
  return vue.openBlock(), vue.createBlock(_component_magic_code_editor, {
40
60
  style: vue.normalizeStyle(`height: ${_ctx.height}`),
@@ -43,9 +63,9 @@
43
63
  onSave: _ctx.save
44
64
  }, null, 8, ["style", "init-values", "language", "onSave"]);
45
65
  }
46
- var Code = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["render", _sfc_render$j]]);
66
+ var Code = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["render", _sfc_render$k]]);
47
67
 
48
- const _sfc_main$i = vue.defineComponent({
68
+ const _sfc_main$j = vue.defineComponent({
49
69
  name: "m-fields-code-link",
50
70
  props: {
51
71
  config: {
@@ -100,7 +120,7 @@
100
120
  };
101
121
  }
102
122
  });
103
- function _sfc_render$i(_ctx, _cache, $props, $setup, $data, $options) {
123
+ function _sfc_render$j(_ctx, _cache, $props, $setup, $data, $options) {
104
124
  const _component_m_fields_link = vue.resolveComponent("m-fields-link");
105
125
  return vue.openBlock(), vue.createBlock(_component_m_fields_link, {
106
126
  config: _ctx.formConfig,
@@ -109,11 +129,11 @@
109
129
  onChange: _ctx.changeHandler
110
130
  }, null, 8, ["config", "model", "onChange"]);
111
131
  }
112
- var CodeLink = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["render", _sfc_render$i]]);
132
+ var CodeLink = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["render", _sfc_render$j]]);
113
133
 
114
134
  var UISelect_vue_vue_type_style_index_0_lang = '';
115
135
 
116
- const _sfc_main$h = vue.defineComponent({
136
+ const _sfc_main$i = vue.defineComponent({
117
137
  name: "m-fields-ui-select",
118
138
  props: {
119
139
  labelWidth: String,
@@ -175,15 +195,15 @@
175
195
  };
176
196
  }
177
197
  });
178
- const _hoisted_1$d = /* @__PURE__ */ vue.createElementVNode("i", {
198
+ const _hoisted_1$e = /* @__PURE__ */ vue.createElementVNode("i", {
179
199
  class: "el-icon-delete",
180
200
  style: { "color": "rgb(221, 75, 57)" }
181
201
  }, "\u53D6\u6D88", -1);
182
202
  const _hoisted_2$7 = [
183
- _hoisted_1$d
203
+ _hoisted_1$e
184
204
  ];
185
205
  const _hoisted_3$5 = /* @__PURE__ */ vue.createElementVNode("i", { class: "el-icon-thumb" }, null, -1);
186
- function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
206
+ function _sfc_render$i(_ctx, _cache, $props, $setup, $data, $options) {
187
207
  return _ctx.uiSelectMode ? (vue.openBlock(), vue.createElementBlock("div", {
188
208
  key: 0,
189
209
  class: "m-fields-ui-select",
@@ -202,23 +222,8 @@
202
222
  })) : vue.createCommentVNode("", true)
203
223
  ]));
204
224
  }
205
- var uiSelect = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["render", _sfc_render$h]]);
225
+ var uiSelect = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["render", _sfc_render$i]]);
206
226
 
207
- const initEditor = () => {
208
- if (globalThis.monaco) {
209
- Promise.resolve(globalThis.monaco);
210
- }
211
- return utils.asyncLoadJs(`https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/loader.min.js`).then(() => {
212
- globalThis.require.config({
213
- paths: { vs: `https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs` }
214
- });
215
- return new Promise((resolve) => {
216
- globalThis.require(["vs/editor/editor.main"], () => {
217
- resolve(globalThis.monaco);
218
- });
219
- });
220
- });
221
- };
222
227
  const toString = (v, language) => {
223
228
  let value = "";
224
229
  if (typeof v !== "string") {
@@ -234,7 +239,7 @@
234
239
  }
235
240
  return value;
236
241
  };
237
- const _sfc_main$g = vue.defineComponent({
242
+ const _sfc_main$h = vue.defineComponent({
238
243
  name: "magic-code-editor",
239
244
  props: {
240
245
  initValues: {
@@ -252,32 +257,34 @@
252
257
  default: () => "javascript"
253
258
  }
254
259
  },
255
- emits: ["inited", "save"],
260
+ emits: ["initd", "save"],
256
261
  setup(props, { emit }) {
257
262
  let vsEditor = null;
263
+ let vsDiffEditor = null;
258
264
  const values = vue.ref("");
259
265
  const loading = vue.ref(false);
260
266
  const codeEditor = vue.ref();
261
267
  const setEditorValue = (v, m) => {
262
268
  values.value = toString(v, props.language);
263
269
  if (props.type === "diff") {
264
- const originalModel = globalThis.monaco.editor.createModel(values.value, "text/javascript");
265
- const modifiedModel = globalThis.monaco.editor.createModel(toString(m, props.language), "text/javascript");
266
- return vsEditor.setModel({
270
+ const originalModel = monaco__namespace.editor.createModel(values.value, "text/javascript");
271
+ const modifiedModel = monaco__namespace.editor.createModel(toString(m, props.language), "text/javascript");
272
+ return vsDiffEditor?.setModel({
267
273
  original: originalModel,
268
274
  modified: modifiedModel
269
275
  });
270
276
  }
271
- return vsEditor.setValue?.(values.value);
277
+ return vsEditor?.setValue(values.value);
272
278
  };
273
279
  const resizeHandler = () => {
274
280
  vsEditor?.layout();
281
+ vsDiffEditor?.layout();
275
282
  };
276
- const getEditorValue = () => vsEditor.getValue?.() || "";
283
+ const getEditorValue = () => props.type === "diff" ? vsDiffEditor?.getModifiedEditor().getValue() : vsEditor?.getValue();
277
284
  const init = async () => {
278
285
  if (!codeEditor.value)
279
286
  return;
280
- vsEditor = globalThis.monaco.editor[props.type === "diff" ? "createDiffEditor" : "create"](codeEditor.value, {
287
+ const options = {
281
288
  value: values.value,
282
289
  language: props.language,
283
290
  tabSize: 2,
@@ -285,10 +292,15 @@
285
292
  fontFamily: 'dm, Menlo, Monaco, "Courier New", monospace',
286
293
  fontSize: 15,
287
294
  formatOnPaste: true
288
- });
295
+ };
296
+ if (props.type === "diff") {
297
+ vsDiffEditor = monaco__namespace.editor.createDiffEditor(codeEditor.value, options);
298
+ } else {
299
+ vsEditor = monaco__namespace.editor.create(codeEditor.value, options);
300
+ }
289
301
  setEditorValue(props.initValues, props.modifiedValues);
290
302
  loading.value = false;
291
- emit("inited", vsEditor);
303
+ emit("initd", vsEditor);
292
304
  codeEditor.value.addEventListener("keydown", (e) => {
293
305
  if (e.keyCode === 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) {
294
306
  e.preventDefault();
@@ -296,14 +308,14 @@
296
308
  }
297
309
  });
298
310
  if (props.type !== "diff") {
299
- vsEditor.onDidBlurEditorWidget(() => {
311
+ vsEditor?.onDidBlurEditorWidget(() => {
300
312
  emit("save", getEditorValue());
301
313
  });
302
314
  }
303
315
  globalThis.addEventListener("resize", resizeHandler);
304
316
  };
305
317
  vue.watch(() => props.initValues, (v, preV) => {
306
- if (vsEditor && v !== preV) {
318
+ if (v !== preV) {
307
319
  setEditorValue(props.initValues, props.modifiedValues);
308
320
  }
309
321
  }, {
@@ -312,17 +324,7 @@
312
324
  });
313
325
  vue.onMounted(async () => {
314
326
  loading.value = true;
315
- await initEditor();
316
- if (!globalThis.monaco) {
317
- const interval = setInterval(() => {
318
- if (globalThis.monaco) {
319
- clearInterval(interval);
320
- init();
321
- }
322
- }, 300);
323
- } else {
324
- init();
325
- }
327
+ init();
326
328
  });
327
329
  vue.onUnmounted(() => {
328
330
  globalThis.removeEventListener("resize", resizeHandler);
@@ -332,23 +334,24 @@
332
334
  loading,
333
335
  codeEditor,
334
336
  getEditor() {
335
- return vsEditor;
337
+ return vsEditor || vsDiffEditor;
336
338
  },
337
339
  setEditorValue,
338
340
  focus() {
339
- vsEditor.focus();
341
+ vsEditor?.focus();
342
+ vsDiffEditor?.focus();
340
343
  }
341
344
  };
342
345
  }
343
346
  });
344
- const _hoisted_1$c = {
347
+ const _hoisted_1$d = {
345
348
  ref: "codeEditor",
346
349
  class: "magic-code-editor"
347
350
  };
348
- function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
349
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$c, null, 512);
351
+ function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
352
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$d, null, 512);
350
353
  }
351
- var CodeEditor = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render$g]]);
354
+ var CodeEditor = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["render", _sfc_render$h]]);
352
355
 
353
356
  let $TMAGIC_EDITOR = {};
354
357
  const setConfig = (option) => {
@@ -432,10 +435,39 @@
432
435
 
433
436
  const methodName = (prefix, name) => `${prefix}${name[0].toUpperCase()}${name.substring(1)}`;
434
437
  const isError = (error) => Object.prototype.toString.call(error) === "[object Error]";
438
+ const doAction = async (args, scope, sourceMethod, beforeMethodName, afterMethodName, fn) => {
439
+ try {
440
+ let beforeArgs = args;
441
+ for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
442
+ let beforeReturnValue = await beforeMethod(...beforeArgs) || [];
443
+ if (isError(beforeReturnValue))
444
+ throw beforeReturnValue;
445
+ if (!Array.isArray(beforeReturnValue)) {
446
+ beforeReturnValue = [beforeReturnValue];
447
+ }
448
+ beforeArgs = beforeArgs.map((v, index) => {
449
+ if (typeof beforeReturnValue[index] === "undefined")
450
+ return v;
451
+ return beforeReturnValue[index];
452
+ });
453
+ }
454
+ let returnValue = await fn(beforeArgs, sourceMethod.bind(scope));
455
+ for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
456
+ returnValue = await afterMethod(...beforeArgs, returnValue);
457
+ if (isError(returnValue))
458
+ throw returnValue;
459
+ }
460
+ return returnValue;
461
+ } catch (error) {
462
+ throw error;
463
+ }
464
+ };
435
465
  class BaseService extends events.EventEmitter {
436
466
  pluginOptionsList = {};
437
467
  middleware = {};
438
- constructor(methods) {
468
+ taskList = [];
469
+ doingTask = false;
470
+ constructor(methods = [], serialMethods = []) {
439
471
  super();
440
472
  methods.forEach((propertyName) => {
441
473
  const scope = this;
@@ -448,27 +480,23 @@
448
480
  const fn = compose(this.middleware[propertyName]);
449
481
  Object.defineProperty(scope, propertyName, {
450
482
  value: async (...args) => {
451
- let beforeArgs = args;
452
- for (const beforeMethod of this.pluginOptionsList[beforeMethodName]) {
453
- let beforeReturnValue = await beforeMethod(...beforeArgs) || [];
454
- if (isError(beforeReturnValue))
455
- throw beforeReturnValue;
456
- if (!Array.isArray(beforeReturnValue)) {
457
- beforeReturnValue = [beforeReturnValue];
458
- }
459
- beforeArgs = beforeArgs.map((v, index) => {
460
- if (typeof beforeReturnValue[index] === "undefined")
461
- return v;
462
- return beforeReturnValue[index];
463
- });
483
+ if (!serialMethods.includes(propertyName)) {
484
+ return doAction(args, scope, sourceMethod, beforeMethodName, afterMethodName, fn);
464
485
  }
465
- let returnValue = await fn(beforeArgs, sourceMethod.bind(scope));
466
- for (const afterMethod of this.pluginOptionsList[afterMethodName]) {
467
- returnValue = await afterMethod(...beforeArgs, returnValue);
468
- if (isError(returnValue))
469
- throw returnValue;
486
+ const promise = new Promise((resolve, reject) => {
487
+ this.taskList.push(async () => {
488
+ try {
489
+ const value = await doAction(args, scope, sourceMethod, beforeMethodName, afterMethodName, fn);
490
+ resolve(value);
491
+ } catch (e) {
492
+ reject(e);
493
+ }
494
+ });
495
+ });
496
+ if (!this.doingTask) {
497
+ this.doTask();
470
498
  }
471
- return returnValue;
499
+ return promise;
472
500
  }
473
501
  });
474
502
  });
@@ -485,6 +513,15 @@
485
513
  this.pluginOptionsList[methodName2].push(method);
486
514
  });
487
515
  }
516
+ async doTask() {
517
+ this.doingTask = true;
518
+ let task = this.taskList.shift();
519
+ while (task) {
520
+ await task();
521
+ task = this.taskList.shift();
522
+ }
523
+ this.doingTask = false;
524
+ }
488
525
  }
489
526
 
490
527
  class History extends BaseService {
@@ -591,7 +628,7 @@
591
628
  setPropsValue(type, value) {
592
629
  this.state.propsValueMap[type] = value;
593
630
  }
594
- async getPropsValue(type) {
631
+ async getPropsValue(type, defaultValue = {}) {
595
632
  if (type === "area") {
596
633
  const value = await this.getPropsValue("button");
597
634
  value.className = "action-area";
@@ -603,6 +640,7 @@
603
640
  }
604
641
  return lodashEs.cloneDeep({
605
642
  ...getDefaultPropsValue(type),
643
+ ...defaultValue,
606
644
  ...this.state.propsValueMap[type] || {}
607
645
  });
608
646
  }
@@ -621,12 +659,16 @@
621
659
  Layout2["ABSOLUTE"] = "absolute";
622
660
  return Layout2;
623
661
  })(Layout || {});
662
+ var Keys = /* @__PURE__ */ ((Keys2) => {
663
+ Keys2["ESCAPE"] = "Space";
664
+ return Keys2;
665
+ })(Keys || {});
624
666
 
625
667
  const COPY_STORAGE_KEY = "$MagicEditorCopyData";
626
668
  const generateId = (type) => `${type}_${lodashEs.random(1e4, false)}`;
627
669
  const getPageList = (app) => {
628
670
  if (app.items && Array.isArray(app.items)) {
629
- return app.items.filter((item) => item.type === "page");
671
+ return app.items.filter((item) => item.type === schema.NodeType.PAGE);
630
672
  }
631
673
  return [];
632
674
  };
@@ -660,9 +702,9 @@
660
702
  };
661
703
  const setNewItemId = (config, parent) => {
662
704
  const oldId = config.id;
663
- config.id = generateId(config.type);
705
+ config.id = generateId(config.type || "component");
664
706
  config.name = `${config.name?.replace(/_(\d+)$/, "")}_${config.id}`;
665
- if (utils.isPop(config) && parent?.type === "page") {
707
+ if (utils.isPop(config) && parent?.type === schema.NodeType.PAGE) {
666
708
  updatePopId(oldId, config.id, parent);
667
709
  }
668
710
  if (config.items && Array.isArray(config.items)) {
@@ -683,11 +725,25 @@
683
725
  };
684
726
  return node;
685
727
  };
686
- const initPosition = (node, layout) => {
728
+ const setTop2Middle = (node, parentNode, stage) => {
729
+ const style = node.style || {};
730
+ const height = style.height || 0;
731
+ if (!stage || style.top || !parentNode.style || !utils.isNumber(height))
732
+ return style;
733
+ const { height: parentHeight } = parentNode.style;
734
+ if (utils.isPage(parentNode)) {
735
+ const { scrollTop = 0, wrapperHeight } = stage.mask;
736
+ style.top = (wrapperHeight - height) / 2 + scrollTop;
737
+ } else {
738
+ style.top = (parentHeight - height) / 2;
739
+ }
740
+ return style;
741
+ };
742
+ const initPosition = (node, layout, parentNode, stage) => {
687
743
  if (layout === Layout.ABSOLUTE) {
688
744
  node.style = {
689
745
  position: "absolute",
690
- ...node.style || {}
746
+ ...setTop2Middle(node, parentNode, stage)
691
747
  };
692
748
  return node;
693
749
  }
@@ -734,7 +790,9 @@
734
790
  const cur = path.pop();
735
791
  const offset = {
736
792
  left: cur?.style?.left || 0,
737
- top: cur?.style?.top || 0
793
+ top: cur?.style?.top || 0,
794
+ right: "",
795
+ bottom: ""
738
796
  };
739
797
  path.forEach((value) => {
740
798
  offset.left = offset.left - globalThis.parseFloat(value.style?.left || 0);
@@ -755,22 +813,6 @@
755
813
  }
756
814
  return toRelative(node);
757
815
  };
758
- const defaults = (object, source) => {
759
- let o = source;
760
- if (Array.isArray(object)) {
761
- o = object;
762
- }
763
- Object.entries(o).forEach(([key, value]) => {
764
- if (typeof object[key] === "undefined") {
765
- object[key] = value;
766
- return;
767
- }
768
- if (value && typeof value !== "string" && Object.keys(value).length) {
769
- object[key] = defaults(lodashEs.cloneDeep(object[key]), value);
770
- }
771
- });
772
- return object;
773
- };
774
816
 
775
817
  const log = (...args) => {
776
818
  };
@@ -791,6 +833,7 @@
791
833
  parent: null,
792
834
  node: null,
793
835
  stage: null,
836
+ highlightNode: null,
794
837
  modifiedNodeIds: /* @__PURE__ */ new Map()
795
838
  });
796
839
  constructor() {
@@ -806,8 +849,9 @@
806
849
  "alignCenter",
807
850
  "moveLayer",
808
851
  "undo",
809
- "redo"
810
- ]);
852
+ "redo",
853
+ "highlight"
854
+ ], ["select", "update", "moveLayer"]);
811
855
  }
812
856
  set(name, value) {
813
857
  this.state[name] = value;
@@ -833,7 +877,7 @@
833
877
  info.node = path[path.length - 1];
834
878
  info.parent = path[path.length - 2];
835
879
  path.forEach((item) => {
836
- if (item.type === "page") {
880
+ if (item.type === schema.NodeType.PAGE) {
837
881
  info.page = item;
838
882
  return;
839
883
  }
@@ -860,18 +904,7 @@
860
904
  return Layout.ABSOLUTE;
861
905
  }
862
906
  async select(config2) {
863
- let id;
864
- if (typeof config2 === "string" || typeof config2 === "number") {
865
- id = config2;
866
- } else {
867
- id = config2.id;
868
- }
869
- if (!id) {
870
- throw new Error("\u6CA1\u6709ID\uFF0C\u65E0\u6CD5\u9009\u4E2D");
871
- }
872
- const { node, parent, page } = this.getNodeInfo(id);
873
- if (!node)
874
- throw new Error("\u83B7\u53D6\u4E0D\u5230\u7EC4\u4EF6\u4FE1\u606F");
907
+ const { node, page, parent } = this.selectedConfigExceptionHandler(config2);
875
908
  this.set("node", node);
876
909
  this.set("page", page || null);
877
910
  this.set("parent", parent || null);
@@ -882,10 +915,17 @@
882
915
  }
883
916
  return node;
884
917
  }
918
+ highlight(config2) {
919
+ const { node } = this.selectedConfigExceptionHandler(config2);
920
+ const currentHighlightNode = this.get("highlightNode");
921
+ if (currentHighlightNode === node)
922
+ return;
923
+ this.set("highlightNode", node);
924
+ }
885
925
  async add({ type, ...config2 }, parent) {
886
926
  const curNode = this.get("node");
887
927
  let parentNode;
888
- if (type === "page") {
928
+ if (type === schema.NodeType.PAGE) {
889
929
  parentNode = this.get("root");
890
930
  } else if (parent && typeof parent !== "function") {
891
931
  parentNode = parent;
@@ -897,15 +937,19 @@
897
937
  if (!parentNode)
898
938
  throw new Error("\u672A\u627E\u5230\u7236\u5143\u7D20");
899
939
  const layout = await this.getLayout(parentNode);
900
- const newNode = initPosition({ ...vue.toRaw(await propsService.getPropsValue(type)), ...config2 }, layout);
901
- if ((parentNode?.type === "app" || curNode.type === "app") && newNode.type !== "page") {
940
+ const newNode = initPosition({ ...vue.toRaw(await propsService.getPropsValue(type, config2)) }, layout, parentNode, this.get("stage"));
941
+ if ((parentNode?.type === schema.NodeType.ROOT || curNode.type === schema.NodeType.ROOT) && newNode.type !== schema.NodeType.PAGE) {
902
942
  throw new Error("app\u4E0B\u4E0D\u80FD\u6DFB\u52A0\u7EC4\u4EF6");
903
943
  }
904
944
  parentNode?.items?.push(newNode);
905
- await this.get("stage")?.add({ config: lodashEs.cloneDeep(newNode), root: lodashEs.cloneDeep(this.get("root")) });
945
+ const stage = this.get("stage");
946
+ await stage?.add({ config: lodashEs.cloneDeep(newNode), root: lodashEs.cloneDeep(this.get("root")) });
906
947
  await this.select(newNode);
907
948
  this.addModifiedNodeId(newNode.id);
908
- this.pushHistoryState();
949
+ if (type !== schema.NodeType.PAGE) {
950
+ this.pushHistoryState();
951
+ }
952
+ stage?.select(newNode.id);
909
953
  return newNode;
910
954
  }
911
955
  async remove(node) {
@@ -921,11 +965,16 @@
921
965
  if (typeof index !== "number" || index === -1)
922
966
  throw new Error("\u627E\u4E0D\u8981\u5220\u9664\u7684\u8282\u70B9");
923
967
  parent.items?.splice(index, 1);
924
- this.get("stage")?.remove({ id: node.id, root: this.get("root") });
925
- if (node.type === "page") {
926
- await this.select(root.items[0] || root);
968
+ const stage = this.get("stage");
969
+ stage?.remove({ id: node.id, root: this.get("root") });
970
+ if (node.type === schema.NodeType.PAGE) {
971
+ if (root.items[0]) {
972
+ await this.select(root.items[0]);
973
+ stage?.select(root.items[0].id);
974
+ }
927
975
  } else {
928
976
  await this.select(parent);
977
+ stage?.select(parent.id);
929
978
  }
930
979
  this.addModifiedNodeId(parent.id);
931
980
  this.pushHistoryState();
@@ -938,17 +987,21 @@
938
987
  if (!info.node)
939
988
  throw new Error(`\u83B7\u53D6\u4E0D\u5230id\u4E3A${config2.id}\u7684\u8282\u70B9`);
940
989
  const node = lodashEs.cloneDeep(vue.toRaw(info.node));
941
- const { parent } = info;
942
- if (!parent)
943
- throw new Error("\u83B7\u53D6\u4E0D\u5230\u7236\u7EA7\u8282\u70B9");
944
990
  let newConfig = await this.toggleFixedPosition(vue.toRaw(config2), node, this.get("root"));
945
- defaults(newConfig, node);
991
+ newConfig = lodashEs.mergeWith(lodashEs.cloneDeep(node), newConfig, (objValue, srcValue) => {
992
+ if (Array.isArray(srcValue)) {
993
+ return srcValue;
994
+ }
995
+ });
946
996
  if (!newConfig.type)
947
997
  throw new Error("\u914D\u7F6E\u7F3A\u5C11type\u503C");
948
- if (newConfig.type === "app") {
998
+ if (newConfig.type === schema.NodeType.ROOT) {
949
999
  this.set("root", newConfig);
950
1000
  return newConfig;
951
1001
  }
1002
+ const { parent } = info;
1003
+ if (!parent)
1004
+ throw new Error("\u83B7\u53D6\u4E0D\u5230\u7236\u7EA7\u8282\u70B9");
952
1005
  const parentNodeItems = parent.items;
953
1006
  const index = getNodeIndex(newConfig, parent);
954
1007
  if (!parentNodeItems || typeof index === "undefined" || index === -1)
@@ -959,11 +1012,11 @@
959
1012
  newConfig = setLayout(newConfig, newLayout);
960
1013
  }
961
1014
  parentNodeItems[index] = newConfig;
962
- if (newConfig.id === this.get("node").id) {
1015
+ if (`${newConfig.id}` === `${this.get("node").id}`) {
963
1016
  this.set("node", newConfig);
964
1017
  }
965
1018
  this.get("stage")?.update({ config: lodashEs.cloneDeep(newConfig), root: this.get("root") });
966
- if (newConfig.type === "page") {
1019
+ if (newConfig.type === schema.NodeType.PAGE) {
967
1020
  this.set("page", newConfig);
968
1021
  }
969
1022
  this.addModifiedNodeId(newConfig.id);
@@ -980,6 +1033,7 @@
980
1033
  parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
981
1034
  await this.update(parent);
982
1035
  await this.select(node);
1036
+ this.get("stage")?.update({ config: lodashEs.cloneDeep(node), root: this.get("root") });
983
1037
  this.addModifiedNodeId(parent.id);
984
1038
  this.pushHistoryState();
985
1039
  }
@@ -1079,7 +1133,12 @@
1079
1133
  this.isHistoryStateChange = true;
1080
1134
  await this.update(value.data);
1081
1135
  this.set("modifiedNodeIds", value.modifiedNodeIds);
1082
- setTimeout(() => value.nodeId && this.select(value.nodeId), 0);
1136
+ setTimeout(async () => {
1137
+ if (!value.nodeId)
1138
+ return;
1139
+ await this.select(value.nodeId);
1140
+ this.get("stage")?.select(value.nodeId);
1141
+ }, 0);
1083
1142
  }
1084
1143
  async toggleFixedPosition(dist, src, root) {
1085
1144
  let newConfig = lodashEs.cloneDeep(dist);
@@ -1092,6 +1151,28 @@
1092
1151
  }
1093
1152
  return newConfig;
1094
1153
  }
1154
+ selectedConfigExceptionHandler(config2) {
1155
+ let id;
1156
+ if (typeof config2 === "string" || typeof config2 === "number") {
1157
+ id = config2;
1158
+ } else {
1159
+ id = config2.id;
1160
+ }
1161
+ if (!id) {
1162
+ throw new Error("\u6CA1\u6709ID\uFF0C\u65E0\u6CD5\u9009\u4E2D");
1163
+ }
1164
+ const { node, parent, page } = this.getNodeInfo(id);
1165
+ if (!node)
1166
+ throw new Error("\u83B7\u53D6\u4E0D\u5230\u7EC4\u4EF6\u4FE1\u606F");
1167
+ if (node.id === this.state.root?.id) {
1168
+ throw new Error("\u4E0D\u80FD\u9009\u6839\u8282\u70B9");
1169
+ }
1170
+ return {
1171
+ node,
1172
+ parent,
1173
+ page
1174
+ };
1175
+ }
1095
1176
  }
1096
1177
  var editorService = new Editor$1();
1097
1178
 
@@ -1281,7 +1362,7 @@
1281
1362
  type: "select",
1282
1363
  options: (mForm, { model }) => {
1283
1364
  const node = editorService.getNodeById(model.to);
1284
- if (!node)
1365
+ if (!node?.type)
1285
1366
  return [];
1286
1367
  return eventsService.getMethod(node.type).map((option) => ({
1287
1368
  text: option.label,
@@ -1316,7 +1397,7 @@
1316
1397
  name: type
1317
1398
  });
1318
1399
 
1319
- const _sfc_main$f = vue.defineComponent({
1400
+ const _sfc_main$g = vue.defineComponent({
1320
1401
  components: { Plus: icons.Plus },
1321
1402
  setup() {
1322
1403
  const services = vue.inject("services");
@@ -1326,20 +1407,20 @@
1326
1407
  if (!editorService)
1327
1408
  return;
1328
1409
  editorService.add({
1329
- type: "page",
1410
+ type: schema.NodeType.PAGE,
1330
1411
  name: generatePageNameByApp(vue.toRaw(editorService.get("root")))
1331
1412
  });
1332
1413
  }
1333
1414
  };
1334
1415
  }
1335
1416
  });
1336
- const _hoisted_1$b = { class: "m-editor-empty-panel" };
1417
+ const _hoisted_1$c = { class: "m-editor-empty-panel" };
1337
1418
  const _hoisted_2$6 = { class: "m-editor-empty-content" };
1338
1419
  const _hoisted_3$4 = /* @__PURE__ */ vue.createElementVNode("p", null, "\u65B0\u589E\u9875\u9762", -1);
1339
- function _sfc_render$f(_ctx, _cache, $props, $setup, $data, $options) {
1420
+ function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
1340
1421
  const _component_plus = vue.resolveComponent("plus");
1341
1422
  const _component_el_icon = vue.resolveComponent("el-icon");
1342
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$b, [
1423
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$c, [
1343
1424
  vue.createElementVNode("div", _hoisted_2$6, [
1344
1425
  vue.createElementVNode("div", {
1345
1426
  class: "m-editor-empty-button",
@@ -1358,7 +1439,7 @@
1358
1439
  ])
1359
1440
  ]);
1360
1441
  }
1361
- var AddPageBox = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$f]]);
1442
+ var AddPageBox = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render$g]]);
1362
1443
 
1363
1444
  /*
1364
1445
  Copyright (c) 2018 Daybrush
@@ -2527,7 +2608,7 @@
2527
2608
 
2528
2609
  var Gesto$1 = Gesto;
2529
2610
 
2530
- const _sfc_main$e = vue.defineComponent({
2611
+ const _sfc_main$f = vue.defineComponent({
2531
2612
  name: "m-editor-resize",
2532
2613
  props: {
2533
2614
  type: {
@@ -2569,18 +2650,18 @@
2569
2650
  };
2570
2651
  }
2571
2652
  });
2572
- const _hoisted_1$a = {
2653
+ const _hoisted_1$b = {
2573
2654
  ref: "target",
2574
2655
  class: "m-editor-resizer"
2575
2656
  };
2576
- function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
2577
- return vue.openBlock(), vue.createElementBlock("span", _hoisted_1$a, [
2657
+ function _sfc_render$f(_ctx, _cache, $props, $setup, $data, $options) {
2658
+ return vue.openBlock(), vue.createElementBlock("span", _hoisted_1$b, [
2578
2659
  vue.renderSlot(_ctx.$slots, "default")
2579
2660
  ], 512);
2580
2661
  }
2581
- var Resizer = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render$e]]);
2662
+ var Resizer = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$f]]);
2582
2663
 
2583
- const _sfc_main$d = vue.defineComponent({
2664
+ const _sfc_main$e = vue.defineComponent({
2584
2665
  components: {
2585
2666
  AddPageBox,
2586
2667
  Resizer
@@ -2603,17 +2684,17 @@
2603
2684
  };
2604
2685
  }
2605
2686
  });
2606
- const _hoisted_1$9 = { class: "m-editor" };
2687
+ const _hoisted_1$a = { class: "m-editor" };
2607
2688
  const _hoisted_2$5 = {
2608
2689
  key: 1,
2609
2690
  class: "m-editor-content"
2610
2691
  };
2611
- function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
2692
+ function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
2612
2693
  const _component_magic_code_editor = vue.resolveComponent("magic-code-editor");
2613
2694
  const _component_resizer = vue.resolveComponent("resizer");
2614
2695
  const _component_el_scrollbar = vue.resolveComponent("el-scrollbar");
2615
2696
  const _component_add_page_box = vue.resolveComponent("add-page-box");
2616
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$9, [
2697
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$a, [
2617
2698
  vue.renderSlot(_ctx.$slots, "nav", { class: "m-editor-nav-menu" }),
2618
2699
  _ctx.showSrc ? (vue.openBlock(), vue.createBlock(_component_magic_code_editor, {
2619
2700
  key: 0,
@@ -2653,9 +2734,9 @@
2653
2734
  ]))
2654
2735
  ]);
2655
2736
  }
2656
- var Framework = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$d]]);
2737
+ var Framework = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render$e]]);
2657
2738
 
2658
- const _sfc_main$c = vue.defineComponent({
2739
+ const _sfc_main$d = vue.defineComponent({
2659
2740
  name: "m-icon",
2660
2741
  components: { Edit: icons.Edit },
2661
2742
  props: {
@@ -2669,8 +2750,8 @@
2669
2750
  };
2670
2751
  }
2671
2752
  });
2672
- const _hoisted_1$8 = ["src"];
2673
- function _sfc_render$c(_ctx, _cache, $props, $setup, $data, $options) {
2753
+ const _hoisted_1$9 = ["src"];
2754
+ function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
2674
2755
  const _component_edit = vue.resolveComponent("edit");
2675
2756
  const _component_el_icon = vue.resolveComponent("el-icon");
2676
2757
  return !_ctx.icon ? (vue.openBlock(), vue.createBlock(_component_el_icon, { key: 0 }, {
@@ -2681,7 +2762,7 @@
2681
2762
  })) : typeof _ctx.icon === "string" && _ctx.icon.startsWith("http") ? (vue.openBlock(), vue.createElementBlock("img", {
2682
2763
  key: 1,
2683
2764
  src: _ctx.icon
2684
- }, null, 8, _hoisted_1$8)) : typeof _ctx.icon === "string" ? (vue.openBlock(), vue.createElementBlock("i", {
2765
+ }, null, 8, _hoisted_1$9)) : typeof _ctx.icon === "string" ? (vue.openBlock(), vue.createElementBlock("i", {
2685
2766
  key: 2,
2686
2767
  class: vue.normalizeClass(_ctx.icon)
2687
2768
  }, null, 2)) : (vue.openBlock(), vue.createBlock(_component_el_icon, { key: 3 }, {
@@ -2691,9 +2772,9 @@
2691
2772
  _: 1
2692
2773
  }));
2693
2774
  }
2694
- var MIcon = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$c]]);
2775
+ var MIcon = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$d]]);
2695
2776
 
2696
- const _sfc_main$b = vue.defineComponent({
2777
+ const _sfc_main$c = vue.defineComponent({
2697
2778
  components: { MIcon, ArrowDown: icons.ArrowDown },
2698
2779
  props: {
2699
2780
  data: {
@@ -2731,7 +2812,7 @@
2731
2812
  type: "button",
2732
2813
  icon: icons.Delete,
2733
2814
  tooltip: "\u522A\u9664",
2734
- disabled: () => services?.editorService.get("node")?.type === "page",
2815
+ disabled: () => services?.editorService.get("node")?.type === schema.NodeType.PAGE,
2735
2816
  handler: () => services?.editorService.remove(services?.editorService.get("node"))
2736
2817
  };
2737
2818
  case "undo":
@@ -2828,7 +2909,7 @@
2828
2909
  };
2829
2910
  }
2830
2911
  });
2831
- const _hoisted_1$7 = {
2912
+ const _hoisted_1$8 = {
2832
2913
  key: 0,
2833
2914
  class: "menu-item"
2834
2915
  };
@@ -2840,8 +2921,8 @@
2840
2921
  class: "menu-item-text",
2841
2922
  style: { "margin": "0 5px" }
2842
2923
  };
2843
- const _hoisted_4$3 = { class: "el-dropdown-link menubar-menu-button" };
2844
- function _sfc_render$b(_ctx, _cache, $props, $setup, $data, $options) {
2924
+ const _hoisted_4$2 = { class: "el-dropdown-link menubar-menu-button" };
2925
+ function _sfc_render$c(_ctx, _cache, $props, $setup, $data, $options) {
2845
2926
  const _component_el_divider = vue.resolveComponent("el-divider");
2846
2927
  const _component_m_icon = vue.resolveComponent("m-icon");
2847
2928
  const _component_el_button = vue.resolveComponent("el-button");
@@ -2851,20 +2932,36 @@
2851
2932
  const _component_el_dropdown_item = vue.resolveComponent("el-dropdown-item");
2852
2933
  const _component_el_dropdown_menu = vue.resolveComponent("el-dropdown-menu");
2853
2934
  const _component_el_dropdown = vue.resolveComponent("el-dropdown");
2854
- return _ctx.display ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$7, [
2935
+ return _ctx.display ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$8, [
2855
2936
  _ctx.item.type === "divider" ? (vue.openBlock(), vue.createBlock(_component_el_divider, {
2856
2937
  key: 0,
2857
2938
  direction: "vertical"
2858
2939
  })) : _ctx.item.type === "text" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$4, vue.toDisplayString(_ctx.item.text), 1)) : _ctx.item.type === "zoom" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 2 }, [
2859
- vue.createVNode(_component_m_icon, {
2860
- icon: _ctx.ZoomIn,
2861
- onClick: _ctx.zoomInHandler
2862
- }, null, 8, ["icon", "onClick"]),
2940
+ vue.createVNode(_component_el_button, {
2941
+ size: "small",
2942
+ type: "text"
2943
+ }, {
2944
+ default: vue.withCtx(() => [
2945
+ vue.createVNode(_component_m_icon, {
2946
+ icon: _ctx.ZoomIn,
2947
+ onClick: _ctx.zoomInHandler
2948
+ }, null, 8, ["icon", "onClick"])
2949
+ ]),
2950
+ _: 1
2951
+ }),
2863
2952
  vue.createElementVNode("span", _hoisted_3$3, vue.toDisplayString(parseInt(`${_ctx.zoom * 100}`, 10)) + "%", 1),
2864
- vue.createVNode(_component_m_icon, {
2865
- icon: _ctx.ZoomOut,
2866
- onClick: _ctx.zoomOutHandler
2867
- }, null, 8, ["icon", "onClick"])
2953
+ vue.createVNode(_component_el_button, {
2954
+ size: "small",
2955
+ type: "text"
2956
+ }, {
2957
+ default: vue.withCtx(() => [
2958
+ vue.createVNode(_component_m_icon, {
2959
+ icon: _ctx.ZoomOut,
2960
+ onClick: _ctx.zoomOutHandler
2961
+ }, null, 8, ["icon", "onClick"])
2962
+ ]),
2963
+ _: 1
2964
+ })
2868
2965
  ], 64)) : _ctx.item.type === "button" ? (vue.openBlock(), vue.createBlock(_component_el_tooltip, {
2869
2966
  key: 3,
2870
2967
  effect: "dark",
@@ -2913,7 +3010,7 @@
2913
3010
  })) : vue.createCommentVNode("", true)
2914
3011
  ]),
2915
3012
  default: vue.withCtx(() => [
2916
- vue.createElementVNode("span", _hoisted_4$3, [
3013
+ vue.createElementVNode("span", _hoisted_4$2, [
2917
3014
  vue.createTextVNode(vue.toDisplayString(_ctx.item.text), 1),
2918
3015
  vue.createVNode(_component_el_icon, { class: "el-icon--right" }, {
2919
3016
  default: vue.withCtx(() => [
@@ -2927,9 +3024,9 @@
2927
3024
  }, 8, ["disabled", "onCommand"])) : _ctx.item.type === "component" ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(_ctx.item.component), vue.normalizeProps(vue.mergeProps({ key: 5 }, _ctx.item.props || {})), null, 16)) : vue.createCommentVNode("", true)
2928
3025
  ])) : vue.createCommentVNode("", true);
2929
3026
  }
2930
- var ToolButton = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["render", _sfc_render$b]]);
3027
+ var ToolButton = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$c]]);
2931
3028
 
2932
- const _sfc_main$a = vue.defineComponent({
3029
+ const _sfc_main$b = vue.defineComponent({
2933
3030
  name: "nav-menu",
2934
3031
  components: { ToolButton },
2935
3032
  props: {
@@ -2942,12 +3039,14 @@
2942
3039
  }
2943
3040
  },
2944
3041
  setup(props) {
3042
+ const services = vue.inject("services");
2945
3043
  return {
2946
- keys: vue.computed(() => Object.keys(props.data))
3044
+ keys: vue.computed(() => Object.keys(props.data)),
3045
+ columnWidth: vue.computed(() => services?.uiService.get("columnWidth"))
2947
3046
  };
2948
3047
  }
2949
3048
  });
2950
- function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
3049
+ function _sfc_render$b(_ctx, _cache, $props, $setup, $data, $options) {
2951
3050
  const _component_tool_button = vue.resolveComponent("tool-button");
2952
3051
  return vue.openBlock(), vue.createElementBlock("div", {
2953
3052
  class: "m-editor-nav-menu",
@@ -2956,7 +3055,8 @@
2956
3055
  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.keys, (key) => {
2957
3056
  return vue.openBlock(), vue.createElementBlock("div", {
2958
3057
  class: vue.normalizeClass(`menu-${key}`),
2959
- key
3058
+ key,
3059
+ style: vue.normalizeStyle(`width: ${_ctx.columnWidth?.[key]}px`)
2960
3060
  }, [
2961
3061
  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.data[key], (item, index) => {
2962
3062
  return vue.openBlock(), vue.createBlock(_component_tool_button, {
@@ -2964,13 +3064,13 @@
2964
3064
  key: index
2965
3065
  }, null, 8, ["data"]);
2966
3066
  }), 128))
2967
- ], 2);
3067
+ ], 6);
2968
3068
  }), 128))
2969
3069
  ], 4);
2970
3070
  }
2971
- var NavMenu = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$a]]);
3071
+ var NavMenu = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["render", _sfc_render$b]]);
2972
3072
 
2973
- const _sfc_main$9 = vue.defineComponent({
3073
+ const _sfc_main$a = vue.defineComponent({
2974
3074
  name: "m-editor-props-panel",
2975
3075
  emits: ["mounted"],
2976
3076
  setup(props, { emit }) {
@@ -2979,18 +3079,15 @@
2979
3079
  const configForm = vue.ref();
2980
3080
  const curFormConfig = vue.ref([]);
2981
3081
  const services = vue.inject("services");
3082
+ const node = vue.computed(() => services?.editorService.get("node"));
2982
3083
  const init = async () => {
2983
- const node = services?.editorService.get("node");
2984
- if (!node) {
3084
+ if (!node.value) {
2985
3085
  curFormConfig.value = [];
2986
3086
  return;
2987
3087
  }
2988
- if (node.devconfig && node.style && !isNaN(+node.style.height) && !isNaN(+node.style.width)) {
2989
- node.devconfig.ratio = node.style.height / node.style.width || 1;
2990
- }
2991
- values.value = node;
2992
- const type = node.type || (node.items ? "container" : "text");
3088
+ const type = node.value.type || (node.value.items ? "container" : "text");
2993
3089
  curFormConfig.value = await services?.propsService.getPropsConfig(type) || [];
3090
+ values.value = node.value;
2994
3091
  };
2995
3092
  vue.watchEffect(init);
2996
3093
  services?.propsService.on("props-configs-change", init);
@@ -3019,10 +3116,11 @@
3019
3116
  };
3020
3117
  }
3021
3118
  });
3022
- function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
3119
+ function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
3023
3120
  const _component_m_form = vue.resolveComponent("m-form");
3024
3121
  return vue.openBlock(), vue.createBlock(_component_m_form, {
3025
3122
  class: "m-editor-props-panel",
3123
+ "popper-class": "m-editor-props-panel-popper",
3026
3124
  ref: "configForm",
3027
3125
  size: "small",
3028
3126
  "init-values": _ctx.values,
@@ -3030,9 +3128,9 @@
3030
3128
  onChange: _ctx.submit
3031
3129
  }, null, 8, ["init-values", "config", "onChange"]);
3032
3130
  }
3033
- var PropsPanel = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$9]]);
3131
+ var PropsPanel = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$a]]);
3034
3132
 
3035
- const _sfc_main$8 = vue.defineComponent({
3133
+ const _sfc_main$9 = vue.defineComponent({
3036
3134
  name: "ui-component-panel",
3037
3135
  components: { MIcon },
3038
3136
  setup() {
@@ -3047,19 +3145,19 @@
3047
3145
  searchText,
3048
3146
  collapseValue,
3049
3147
  list,
3050
- appendComponent({ text, type, ...config }) {
3148
+ appendComponent({ text, type, data = {} }) {
3051
3149
  services?.editorService.add({
3052
3150
  name: text,
3053
3151
  type,
3054
- ...config
3152
+ ...data
3055
3153
  });
3056
3154
  }
3057
3155
  };
3058
3156
  }
3059
3157
  });
3060
- const _hoisted_1$6 = /* @__PURE__ */ vue.createElementVNode("i", { class: "el-icon-s-grid" }, null, -1);
3158
+ const _hoisted_1$7 = /* @__PURE__ */ vue.createElementVNode("i", { class: "el-icon-s-grid" }, null, -1);
3061
3159
  const _hoisted_2$3 = ["onClick"];
3062
- function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
3160
+ function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
3063
3161
  const _component_el_input = vue.resolveComponent("el-input");
3064
3162
  const _component_m_icon = vue.resolveComponent("m-icon");
3065
3163
  const _component_el_tooltip = vue.resolveComponent("el-tooltip");
@@ -3089,7 +3187,7 @@
3089
3187
  name: index
3090
3188
  }, {
3091
3189
  title: vue.withCtx(() => [
3092
- _hoisted_1$6,
3190
+ _hoisted_1$7,
3093
3191
  vue.createTextVNode(vue.toDisplayString(group.title), 1)
3094
3192
  ]),
3095
3193
  default: vue.withCtx(() => [
@@ -3126,65 +3224,51 @@
3126
3224
  _: 1
3127
3225
  });
3128
3226
  }
3129
- var ComponentListPanel = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$8]]);
3227
+ var ComponentListPanel = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$9]]);
3130
3228
 
3131
- const _sfc_main$7 = vue.defineComponent({
3229
+ const _sfc_main$8 = vue.defineComponent({
3132
3230
  name: "magic-editor-content-menu",
3133
- props: {
3134
- componentGroupList: {
3135
- type: Array,
3136
- default: () => []
3137
- }
3138
- },
3139
- setup(props) {
3231
+ setup() {
3140
3232
  const services = vue.inject("services");
3141
3233
  const subVisible = vue.ref(false);
3142
3234
  const node = vue.computed(() => services?.editorService.get("node"));
3143
3235
  return {
3144
3236
  subVisible,
3145
3237
  node,
3146
- menu: vue.computed(() => ({
3147
- app: [
3148
- {
3149
- type: "page",
3150
- text: "\u9875\u9762"
3151
- }
3152
- ],
3153
- component: props.componentGroupList
3154
- })),
3238
+ componentGroupList: vue.computed(() => services?.componentListService.getList()),
3155
3239
  append(config) {
3156
3240
  services?.editorService.add({
3157
3241
  name: config.text,
3158
- type: config.type
3242
+ type: config.type,
3243
+ ...config.data || {}
3159
3244
  });
3160
3245
  },
3161
3246
  remove() {
3162
3247
  node.value && services?.editorService.remove(node.value);
3163
3248
  },
3164
3249
  copy(node2) {
3165
- services?.editorService.copy(node2);
3250
+ node2 && services?.editorService.copy(node2);
3166
3251
  },
3167
- setSubVisiable(v) {
3252
+ setSubVisitable(v) {
3168
3253
  subVisible.value = v;
3169
3254
  }
3170
3255
  };
3171
3256
  }
3172
3257
  });
3173
- const _hoisted_1$5 = {
3258
+ const _hoisted_1$6 = {
3174
3259
  key: 0,
3175
3260
  class: "magic-editor-content-menu"
3176
3261
  };
3177
3262
  const _hoisted_2$2 = ["onClick"];
3178
- const _hoisted_3$2 = ["onClick"];
3179
- const _hoisted_4$2 = /* @__PURE__ */ vue.createElementVNode("div", { class: "separation" }, null, -1);
3180
- function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
3263
+ const _hoisted_3$2 = /* @__PURE__ */ vue.createElementVNode("div", { class: "separation" }, null, -1);
3264
+ function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
3181
3265
  const _component_el_scrollbar = vue.resolveComponent("el-scrollbar");
3182
- return _ctx.node ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$5, [
3266
+ return _ctx.node ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [
3183
3267
  _ctx.node.items ? (vue.openBlock(), vue.createElementBlock("div", {
3184
3268
  key: 0,
3185
3269
  class: "magic-editor-content-menu-item",
3186
- onMouseenter: _cache[0] || (_cache[0] = ($event) => _ctx.setSubVisiable(true)),
3187
- onMouseleave: _cache[1] || (_cache[1] = ($event) => _ctx.setSubVisiable(false))
3270
+ onMouseenter: _cache[0] || (_cache[0] = ($event) => _ctx.setSubVisitable(true)),
3271
+ onMouseleave: _cache[1] || (_cache[1] = ($event) => _ctx.setSubVisitable(false))
3188
3272
  }, " \u65B0\u589E ", 32)) : vue.createCommentVNode("", true),
3189
3273
  _ctx.node.type !== "app" ? (vue.openBlock(), vue.createElementBlock("div", {
3190
3274
  key: 1,
@@ -3198,8 +3282,8 @@
3198
3282
  }, " \u5220\u9664 ")) : vue.createCommentVNode("", true),
3199
3283
  vue.withDirectives(vue.createElementVNode("div", {
3200
3284
  class: "subMenu",
3201
- onMouseenter: _cache[5] || (_cache[5] = ($event) => _ctx.setSubVisiable(true)),
3202
- onMouseleave: _cache[6] || (_cache[6] = ($event) => _ctx.setSubVisiable(false))
3285
+ onMouseenter: _cache[5] || (_cache[5] = ($event) => _ctx.setSubVisitable(true)),
3286
+ onMouseleave: _cache[6] || (_cache[6] = ($event) => _ctx.setSubVisitable(false))
3203
3287
  }, [
3204
3288
  vue.createVNode(_component_el_scrollbar, null, {
3205
3289
  default: vue.withCtx(() => [
@@ -3209,13 +3293,7 @@
3209
3293
  onClick: _cache[4] || (_cache[4] = () => _ctx.append({
3210
3294
  type: "tab-pane"
3211
3295
  }))
3212
- }, " \u6807\u7B7E ")) : _ctx.node.type === "app" ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 1 }, vue.renderList(_ctx.menu.app, (item) => {
3213
- return vue.openBlock(), vue.createElementBlock("div", {
3214
- class: "magic-editor-content-menu-item",
3215
- key: item.type,
3216
- onClick: () => _ctx.append(item)
3217
- }, vue.toDisplayString(item.text), 9, _hoisted_2$2);
3218
- }), 128)) : _ctx.node.items ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 2 }, vue.renderList(_ctx.menu.component, (list) => {
3296
+ }, " \u6807\u7B7E ")) : _ctx.node.items ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 1 }, vue.renderList(_ctx.componentGroupList, (list) => {
3219
3297
  return vue.openBlock(), vue.createElementBlock("div", {
3220
3298
  key: list.title
3221
3299
  }, [
@@ -3225,10 +3303,10 @@
3225
3303
  class: "magic-editor-content-menu-item",
3226
3304
  key: item.type,
3227
3305
  onClick: () => _ctx.append(item)
3228
- }, vue.toDisplayString(item.text), 9, _hoisted_3$2)) : vue.createCommentVNode("", true)
3306
+ }, vue.toDisplayString(item.text), 9, _hoisted_2$2)) : vue.createCommentVNode("", true)
3229
3307
  ], 64);
3230
3308
  }), 256)),
3231
- _hoisted_4$2
3309
+ _hoisted_3$2
3232
3310
  ]);
3233
3311
  }), 128)) : vue.createCommentVNode("", true)
3234
3312
  ]),
@@ -3239,22 +3317,31 @@
3239
3317
  ])
3240
3318
  ])) : vue.createCommentVNode("", true);
3241
3319
  }
3242
- var LayerMenu = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$7]]);
3320
+ var LayerMenu = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$8]]);
3243
3321
 
3244
- const select = (data, editorService) => {
3322
+ const throttleTime = 150;
3323
+ const select = async (data, editorService) => {
3245
3324
  if (!data.id) {
3246
3325
  throw new Error("\u6CA1\u6709id");
3247
3326
  }
3248
- editorService?.select(data);
3327
+ await editorService?.select(data);
3328
+ editorService?.get("stage")?.select(data.id);
3329
+ };
3330
+ const highlight = (data, editorService) => {
3331
+ if (!data?.id) {
3332
+ throw new Error("\u6CA1\u6709id");
3333
+ }
3334
+ editorService?.highlight(data);
3335
+ editorService?.get("stage")?.highlight(data.id);
3249
3336
  };
3250
3337
  const useDrop = (tree, editorService) => ({
3251
3338
  allowDrop: (draggingNode, dropNode, type) => {
3252
3339
  const { data } = dropNode || {};
3253
3340
  const { data: ingData } = draggingNode;
3254
3341
  const { type: ingType } = ingData;
3255
- if (ingType !== "page" && data.type === "page")
3342
+ if (ingType !== schema.NodeType.PAGE && data.type === schema.NodeType.PAGE)
3256
3343
  return false;
3257
- if (ingType === "page" && data.type !== "page")
3344
+ if (ingType === schema.NodeType.PAGE && data.type !== schema.NodeType.PAGE)
3258
3345
  return false;
3259
3346
  if (!data || !data.type)
3260
3347
  return false;
@@ -3273,29 +3360,35 @@
3273
3360
  }
3274
3361
  });
3275
3362
  const useStatus = (tree, editorService) => {
3363
+ const highlightNode = vue.ref();
3364
+ const node = vue.ref();
3276
3365
  const page = vue.computed(() => editorService?.get("page"));
3277
3366
  vue.watchEffect(() => {
3278
3367
  if (!tree.value)
3279
3368
  return;
3280
- const node = editorService?.get("node");
3281
- node && tree.value.setCurrentKey(node.id, true);
3369
+ node.value = editorService?.get("node");
3370
+ node.value && tree.value.setCurrentKey(node.value.id, true);
3282
3371
  const parent = editorService?.get("parent");
3283
3372
  if (!parent?.id)
3284
3373
  return;
3285
3374
  const treeNode = tree.value.getNode(parent.id);
3286
3375
  treeNode?.updateChildren();
3376
+ highlightNode.value = editorService?.get("highlightNode");
3287
3377
  });
3288
3378
  return {
3289
3379
  values: vue.computed(() => page.value ? [page.value] : []),
3290
- loadItems: (node, resolve) => {
3291
- if (Array.isArray(node.data)) {
3292
- return resolve(node.data);
3380
+ loadItems: (node2, resolve) => {
3381
+ if (Array.isArray(node2.data)) {
3382
+ return resolve(node2.data);
3293
3383
  }
3294
- if (Array.isArray(node.data?.items)) {
3295
- return resolve(node.data?.items);
3384
+ if (Array.isArray(node2.data?.items)) {
3385
+ return resolve(node2.data?.items);
3296
3386
  }
3297
3387
  resolve([]);
3298
- }
3388
+ },
3389
+ highlightNode,
3390
+ clickNode: node,
3391
+ expandedKeys: vue.computed(() => node.value ? [node.value.id] : [])
3299
3392
  };
3300
3393
  };
3301
3394
  const useFilter = (tree) => ({
@@ -3307,12 +3400,10 @@
3307
3400
  let name = "";
3308
3401
  if (data.name) {
3309
3402
  name = data.name;
3310
- } else if (data.type) {
3311
- name = data.type;
3312
3403
  } else if (data.items) {
3313
3404
  name = "container";
3314
3405
  }
3315
- return name.indexOf(value) !== -1;
3406
+ return `${data.id}${name}${data.type}`.indexOf(value) !== -1;
3316
3407
  },
3317
3408
  filterTextChangeHandler(val) {
3318
3409
  tree.value?.filter(val);
@@ -3346,17 +3437,26 @@
3346
3437
  }
3347
3438
  };
3348
3439
  };
3349
- const _sfc_main$6 = vue.defineComponent({
3440
+ const _sfc_main$7 = vue.defineComponent({
3350
3441
  name: "magic-editor-layer-panel",
3351
3442
  components: { LayerMenu },
3352
3443
  setup() {
3353
3444
  const services = vue.inject("services");
3354
3445
  const tree = vue.ref();
3446
+ const clicked = vue.ref(false);
3355
3447
  const editorService = services?.editorService;
3448
+ const highlightHandler = lodashEs.throttle((data) => {
3449
+ highlight(data, editorService);
3450
+ }, throttleTime);
3451
+ const toogleClickFlag = () => {
3452
+ clicked.value = !clicked.value;
3453
+ };
3454
+ const statusData = useStatus(tree, editorService);
3455
+ const canHighlight = vue.computed(() => statusData.highlightNode.value?.id !== statusData.clickNode.value?.id && !clicked.value);
3356
3456
  return {
3357
3457
  tree,
3458
+ ...statusData,
3358
3459
  ...useDrop(tree, editorService),
3359
- ...useStatus(tree, editorService),
3360
3460
  ...useFilter(tree),
3361
3461
  ...useContentMenu(editorService),
3362
3462
  clickHandler(data) {
@@ -3364,12 +3464,17 @@
3364
3464
  document.dispatchEvent(new CustomEvent("ui-select", { detail: data }));
3365
3465
  return;
3366
3466
  }
3467
+ tree.value?.setCurrentKey(data.id);
3367
3468
  select(data, editorService);
3368
- }
3469
+ },
3470
+ highlightHandler,
3471
+ toogleClickFlag,
3472
+ canHighlight
3369
3473
  };
3370
3474
  }
3371
3475
  });
3372
- function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
3476
+ const _hoisted_1$5 = ["id", "onMouseenter"];
3477
+ function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
3373
3478
  const _component_el_input = vue.resolveComponent("el-input");
3374
3479
  const _component_el_tree = vue.resolveComponent("el-tree");
3375
3480
  const _component_layer_menu = vue.resolveComponent("layer-menu");
@@ -3390,6 +3495,7 @@
3390
3495
  ref: "tree",
3391
3496
  "node-key": "id",
3392
3497
  draggable: "",
3498
+ "default-expanded-keys": _ctx.expandedKeys,
3393
3499
  load: _ctx.loadItems,
3394
3500
  data: _ctx.values,
3395
3501
  "expand-on-click-node": false,
@@ -3405,15 +3511,23 @@
3405
3511
  "empty-text": "\u9875\u9762\u7A7A\u8361\u8361\u7684"
3406
3512
  }, {
3407
3513
  default: vue.withCtx(({ node, data }) => [
3408
- vue.renderSlot(_ctx.$slots, "layer-node-content", {
3409
- node,
3410
- data
3411
- }, () => [
3412
- vue.createElementVNode("span", null, vue.toDisplayString(`${data.name} (${data.id})`), 1)
3413
- ])
3514
+ vue.createElementVNode("div", {
3515
+ id: data.id,
3516
+ class: vue.normalizeClass(["cus-tree-node", { "cus-tree-node-hover": _ctx.canHighlight && data.id === _ctx.highlightNode?.id }]),
3517
+ onMousedown: _cache[1] || (_cache[1] = (...args) => _ctx.toogleClickFlag && _ctx.toogleClickFlag(...args)),
3518
+ onMouseup: _cache[2] || (_cache[2] = (...args) => _ctx.toogleClickFlag && _ctx.toogleClickFlag(...args)),
3519
+ onMouseenter: ($event) => _ctx.highlightHandler(data)
3520
+ }, [
3521
+ vue.renderSlot(_ctx.$slots, "layer-node-content", {
3522
+ node,
3523
+ data
3524
+ }, () => [
3525
+ vue.createElementVNode("span", null, vue.toDisplayString(`${data.name} (${data.id})`), 1)
3526
+ ])
3527
+ ], 42, _hoisted_1$5)
3414
3528
  ]),
3415
3529
  _: 3
3416
- }, 8, ["load", "data", "filter-node-method", "allow-drop", "onNodeClick", "onNodeContextmenu", "onNodeDragEnd"])) : vue.createCommentVNode("", true),
3530
+ }, 8, ["default-expanded-keys", "load", "data", "filter-node-method", "allow-drop", "onNodeClick", "onNodeContextmenu", "onNodeDragEnd"])) : vue.createCommentVNode("", true),
3417
3531
  (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
3418
3532
  vue.createVNode(_component_layer_menu, {
3419
3533
  style: vue.normalizeStyle(_ctx.menuStyle)
@@ -3423,9 +3537,9 @@
3423
3537
  _: 3
3424
3538
  });
3425
3539
  }
3426
- var LayerPanel = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6]]);
3540
+ var LayerPanel = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$7]]);
3427
3541
 
3428
- const _sfc_main$5 = vue.defineComponent({
3542
+ const _sfc_main$6 = vue.defineComponent({
3429
3543
  name: "m-sidebar",
3430
3544
  components: { MIcon },
3431
3545
  props: {
@@ -3473,7 +3587,7 @@
3473
3587
  key: 1,
3474
3588
  class: "magic-editor-tab-panel-title"
3475
3589
  };
3476
- function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
3590
+ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
3477
3591
  const _component_m_icon = vue.resolveComponent("m-icon");
3478
3592
  const _component_el_tab_pane = vue.resolveComponent("el-tab-pane");
3479
3593
  const _component_el_tabs = vue.resolveComponent("el-tabs");
@@ -3520,15 +3634,81 @@
3520
3634
  _: 1
3521
3635
  }, 8, ["modelValue"])) : vue.createCommentVNode("", true);
3522
3636
  }
3523
- var Sidebar = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$5]]);
3524
-
3525
- const _sfc_main$4 = vue.defineComponent({
3526
- components: { CaretBottom: icons.CaretBottom, Plus: icons.Plus },
3637
+ var Sidebar = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6]]);
3638
+
3639
+ const useScroll = (root) => {
3640
+ const pageBar = vue.ref();
3641
+ const itemsContainer = vue.ref();
3642
+ const pageBarWidth = vue.ref(0);
3643
+ const canScroll = vue.ref(false);
3644
+ const itemsContainerWidth = vue.computed(() => pageBarWidth.value - 105);
3645
+ let translateLeft = 0;
3646
+ const resizeObserver = new ResizeObserver((entries) => {
3647
+ for (const { contentRect } of entries) {
3648
+ const { width } = contentRect;
3649
+ pageBarWidth.value = width || 0;
3650
+ setCanScroll();
3651
+ }
3652
+ });
3653
+ const setCanScroll = () => {
3654
+ if (itemsContainer.value) {
3655
+ canScroll.value = itemsContainer.value.scrollWidth > pageBarWidth.value - 105;
3656
+ }
3657
+ };
3658
+ const scroll = (type) => {
3659
+ if (!itemsContainer.value)
3660
+ return;
3661
+ const maxScrollLeft = itemsContainer.value.scrollWidth - itemsContainerWidth.value;
3662
+ if (type === "left") {
3663
+ translateLeft += 100;
3664
+ if (translateLeft > 0) {
3665
+ translateLeft = 0;
3666
+ }
3667
+ } else if (type === "right") {
3668
+ translateLeft -= 100;
3669
+ if (-translateLeft > maxScrollLeft) {
3670
+ translateLeft = -maxScrollLeft;
3671
+ }
3672
+ } else if (type === "start") {
3673
+ translateLeft = 0;
3674
+ } else if (type === "end") {
3675
+ translateLeft = -maxScrollLeft;
3676
+ }
3677
+ itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
3678
+ };
3679
+ vue.onMounted(() => {
3680
+ pageBar.value && resizeObserver.observe(pageBar.value);
3681
+ });
3682
+ vue.onUnmounted(() => {
3683
+ resizeObserver.disconnect();
3684
+ });
3685
+ vue.watch(() => root.value?.items.length, (length = 0, preLength = 0) => {
3686
+ setTimeout(() => {
3687
+ setCanScroll();
3688
+ if (length < preLength) {
3689
+ scroll("start");
3690
+ } else {
3691
+ scroll("end");
3692
+ }
3693
+ });
3694
+ });
3695
+ return {
3696
+ pageBar,
3697
+ itemsContainer,
3698
+ canScroll,
3699
+ itemsContainerWidth,
3700
+ scroll
3701
+ };
3702
+ };
3703
+ const _sfc_main$5 = vue.defineComponent({
3704
+ components: { ArrowLeftBold: icons.ArrowLeftBold, ArrowRightBold: icons.ArrowRightBold, CaretBottom: icons.CaretBottom, Plus: icons.Plus },
3527
3705
  setup() {
3528
3706
  const services = vue.inject("services");
3529
3707
  const editorService = services?.editorService;
3708
+ const root = vue.computed(() => editorService?.get("root"));
3530
3709
  return {
3531
- root: vue.computed(() => editorService?.get("root")),
3710
+ ...useScroll(root),
3711
+ root,
3532
3712
  page: vue.computed(() => editorService?.get("page")),
3533
3713
  switchPage(page) {
3534
3714
  editorService?.select(page);
@@ -3537,7 +3717,7 @@
3537
3717
  if (!editorService)
3538
3718
  return;
3539
3719
  const pageConfig = {
3540
- type: "page",
3720
+ type: schema.NodeType.PAGE,
3541
3721
  name: generatePageNameByApp(vue.toRaw(editorService.get("root")))
3542
3722
  };
3543
3723
  editorService.add(pageConfig);
@@ -3555,70 +3735,339 @@
3555
3735
  };
3556
3736
  }
3557
3737
  });
3558
- const _hoisted_1$3 = { class: "m-editor-page-bar" };
3738
+ const _hoisted_1$3 = {
3739
+ class: "m-editor-page-bar",
3740
+ ref: "pageBar"
3741
+ };
3559
3742
  const _hoisted_2$1 = ["onClick"];
3560
- const _hoisted_3$1 = ["onClick"];
3743
+ const _hoisted_3$1 = { class: "m-editor-page-bar-title" };
3561
3744
  const _hoisted_4$1 = ["onClick"];
3562
- function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
3745
+ const _hoisted_5 = ["onClick"];
3746
+ function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
3563
3747
  const _component_plus = vue.resolveComponent("plus");
3564
3748
  const _component_el_icon = vue.resolveComponent("el-icon");
3749
+ const _component_arrow_left_bold = vue.resolveComponent("arrow-left-bold");
3750
+ const _component_el_tooltip = vue.resolveComponent("el-tooltip");
3565
3751
  const _component_caret_bottom = vue.resolveComponent("caret-bottom");
3566
3752
  const _component_el_popover = vue.resolveComponent("el-popover");
3753
+ const _component_arrow_right_bold = vue.resolveComponent("arrow-right-bold");
3567
3754
  return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
3568
3755
  vue.createElementVNode("div", {
3569
- class: "m-editor-page-bar-item",
3756
+ id: "m-editor-page-bar-add-icon",
3757
+ class: "m-editor-page-bar-item m-editor-page-bar-item-icon",
3570
3758
  onClick: _cache[0] || (_cache[0] = (...args) => _ctx.addPage && _ctx.addPage(...args))
3571
3759
  }, [
3572
- vue.createVNode(_component_el_icon, { class: "m-editor-page-bar-menu-add-icon" }, {
3760
+ vue.createVNode(_component_el_icon, null, {
3573
3761
  default: vue.withCtx(() => [
3574
3762
  vue.createVNode(_component_plus)
3575
3763
  ]),
3576
3764
  _: 1
3577
3765
  })
3578
3766
  ]),
3579
- _ctx.root ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 0 }, vue.renderList(_ctx.root.items, (item) => {
3580
- return vue.openBlock(), vue.createElementBlock("div", {
3581
- key: item.key,
3582
- class: vue.normalizeClass(["m-editor-page-bar-item", { active: _ctx.page?.id === item.id }]),
3583
- onClick: ($event) => _ctx.switchPage(item)
3584
- }, [
3585
- vue.renderSlot(_ctx.$slots, "page-bar-title", { page: item }, () => [
3586
- vue.createElementVNode("span", null, vue.toDisplayString(item.name), 1)
3767
+ _ctx.canScroll ? (vue.openBlock(), vue.createElementBlock("div", {
3768
+ key: 0,
3769
+ class: "m-editor-page-bar-item m-editor-page-bar-item-icon",
3770
+ onClick: _cache[1] || (_cache[1] = ($event) => _ctx.scroll("left"))
3771
+ }, [
3772
+ vue.createVNode(_component_el_icon, null, {
3773
+ default: vue.withCtx(() => [
3774
+ vue.createVNode(_component_arrow_left_bold)
3587
3775
  ]),
3588
- vue.createVNode(_component_el_popover, {
3589
- placement: "top",
3590
- width: 160,
3591
- trigger: "hover"
3592
- }, {
3593
- reference: vue.withCtx(() => [
3594
- vue.createVNode(_component_el_icon, { class: "m-editor-page-bar-menu-icon" }, {
3595
- default: vue.withCtx(() => [
3596
- vue.createVNode(_component_caret_bottom)
3597
- ]),
3598
- _: 1
3599
- })
3600
- ]),
3601
- default: vue.withCtx(() => [
3602
- vue.createElementVNode("div", null, [
3603
- vue.renderSlot(_ctx.$slots, "page-bar-popover", { page: item }, () => [
3604
- vue.createElementVNode("div", {
3605
- class: "magic-editor-content-menu-item",
3606
- onClick: () => _ctx.copy(item)
3607
- }, "\u590D\u5236", 8, _hoisted_3$1),
3608
- vue.createElementVNode("div", {
3609
- class: "magic-editor-content-menu-item",
3610
- onClick: () => _ctx.remove(item)
3611
- }, "\u5220\u9664", 8, _hoisted_4$1)
3612
- ])
3776
+ _: 1
3777
+ })
3778
+ ])) : vue.createCommentVNode("", true),
3779
+ _ctx.root ? (vue.openBlock(), vue.createElementBlock("div", {
3780
+ key: 1,
3781
+ class: "m-editor-page-bar-items",
3782
+ ref: "itemsContainer",
3783
+ style: vue.normalizeStyle(`width: ${_ctx.itemsContainerWidth}px`)
3784
+ }, [
3785
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.root.items, (item) => {
3786
+ return vue.openBlock(), vue.createElementBlock("div", {
3787
+ key: item.key,
3788
+ class: vue.normalizeClass(["m-editor-page-bar-item", { active: _ctx.page?.id === item.id }]),
3789
+ onClick: ($event) => _ctx.switchPage(item)
3790
+ }, [
3791
+ vue.createElementVNode("div", _hoisted_3$1, [
3792
+ vue.renderSlot(_ctx.$slots, "page-bar-title", { page: item }, () => [
3793
+ vue.createVNode(_component_el_tooltip, {
3794
+ effect: "dark",
3795
+ placement: "top-start",
3796
+ content: item.name
3797
+ }, {
3798
+ default: vue.withCtx(() => [
3799
+ vue.createElementVNode("span", null, vue.toDisplayString(item.name), 1)
3800
+ ]),
3801
+ _: 2
3802
+ }, 1032, ["content"])
3613
3803
  ])
3614
3804
  ]),
3615
- _: 2
3616
- }, 1024)
3617
- ], 10, _hoisted_2$1);
3618
- }), 128)) : vue.createCommentVNode("", true)
3619
- ]);
3805
+ vue.createVNode(_component_el_popover, {
3806
+ placement: "top",
3807
+ width: 160,
3808
+ trigger: "hover"
3809
+ }, {
3810
+ reference: vue.withCtx(() => [
3811
+ vue.createVNode(_component_el_icon, { class: "m-editor-page-bar-menu-icon" }, {
3812
+ default: vue.withCtx(() => [
3813
+ vue.createVNode(_component_caret_bottom)
3814
+ ]),
3815
+ _: 1
3816
+ })
3817
+ ]),
3818
+ default: vue.withCtx(() => [
3819
+ vue.createElementVNode("div", null, [
3820
+ vue.renderSlot(_ctx.$slots, "page-bar-popover", { page: item }, () => [
3821
+ vue.createElementVNode("div", {
3822
+ class: "magic-editor-content-menu-item",
3823
+ onClick: () => _ctx.copy(item)
3824
+ }, "\u590D\u5236", 8, _hoisted_4$1),
3825
+ vue.createElementVNode("div", {
3826
+ class: "magic-editor-content-menu-item",
3827
+ onClick: () => _ctx.remove(item)
3828
+ }, "\u5220\u9664", 8, _hoisted_5)
3829
+ ])
3830
+ ])
3831
+ ]),
3832
+ _: 2
3833
+ }, 1024)
3834
+ ], 10, _hoisted_2$1);
3835
+ }), 128))
3836
+ ], 4)) : vue.createCommentVNode("", true),
3837
+ _ctx.canScroll ? (vue.openBlock(), vue.createElementBlock("div", {
3838
+ key: 2,
3839
+ class: "m-editor-page-bar-item m-editor-page-bar-item-icon",
3840
+ onClick: _cache[2] || (_cache[2] = ($event) => _ctx.scroll("right"))
3841
+ }, [
3842
+ vue.createVNode(_component_el_icon, null, {
3843
+ default: vue.withCtx(() => [
3844
+ vue.createVNode(_component_arrow_right_bold)
3845
+ ]),
3846
+ _: 1
3847
+ })
3848
+ ])) : vue.createCommentVNode("", true)
3849
+ ], 512);
3850
+ }
3851
+ var PageBar = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$5]]);
3852
+
3853
+ class ScrollViewer$1 {
3854
+ enter = false;
3855
+ targetEnter = false;
3856
+ keydown = false;
3857
+ container;
3858
+ target;
3859
+ zoom = 1;
3860
+ scrollLeft = 0;
3861
+ scrollTop = 0;
3862
+ x = 0;
3863
+ y = 0;
3864
+ resizeObserver = new ResizeObserver((entries) => {
3865
+ for (const { contentRect } of entries) {
3866
+ const { width, height } = contentRect;
3867
+ const targetRect = this.target.getBoundingClientRect();
3868
+ const targetWidth = targetRect.width * this.zoom;
3869
+ const targetMarginTop = Number(this.target.style.marginTop) || 0;
3870
+ const targetHeight = (targetRect.height + targetMarginTop) * this.zoom;
3871
+ if (targetWidth < width) {
3872
+ this.target._left = 0;
3873
+ }
3874
+ if (targetHeight < height) {
3875
+ this.target._top = 0;
3876
+ }
3877
+ this.scroll();
3878
+ }
3879
+ });
3880
+ constructor(options) {
3881
+ this.container = options.container;
3882
+ this.target = options.target;
3883
+ this.zoom = options.zoom;
3884
+ globalThis.addEventListener("keydown", this.keydownHandler);
3885
+ globalThis.addEventListener("keyup", this.keyupHandler);
3886
+ this.container.addEventListener("mouseenter", this.mouseEnterHandler);
3887
+ this.container.addEventListener("mouseleave", this.mouseLeaveHandler);
3888
+ this.target.addEventListener("mouseenter", this.targetMouseEnterHandler);
3889
+ this.target.addEventListener("mouseleave", this.targetMouseLeaveHandler);
3890
+ this.container.addEventListener("wheel", this.wheelHandler);
3891
+ this.resizeObserver.observe(this.container);
3892
+ }
3893
+ destroy() {
3894
+ this.resizeObserver.disconnect();
3895
+ this.container.removeEventListener("mouseenter", this.mouseEnterHandler);
3896
+ this.container.removeEventListener("mouseleave", this.mouseLeaveHandler);
3897
+ this.target.removeEventListener("mouseenter", this.targetMouseEnterHandler);
3898
+ this.target.removeEventListener("mouseleave", this.targetMouseLeaveHandler);
3899
+ globalThis.removeEventListener("keydown", this.keydownHandler);
3900
+ globalThis.removeEventListener("keyup", this.keyupHandler);
3901
+ }
3902
+ setZoom(zoom) {
3903
+ this.zoom = zoom;
3904
+ }
3905
+ scroll() {
3906
+ const scrollLeft = this.target._left;
3907
+ const scrollTop = this.target._top;
3908
+ this.target.style.transform = `translate(${scrollLeft}px, ${scrollTop}px)`;
3909
+ }
3910
+ removeHandler() {
3911
+ this.target.style.cursor = "";
3912
+ this.target.removeEventListener("mousedown", this.mousedownHandler);
3913
+ document.removeEventListener("mousemove", this.mousemoveHandler);
3914
+ document.removeEventListener("mouseup", this.mouseupHandler);
3915
+ }
3916
+ wheelHandler = (event) => {
3917
+ if (this.targetEnter)
3918
+ return;
3919
+ const { deltaX, deltaY, currentTarget } = event;
3920
+ if (currentTarget !== this.container)
3921
+ return;
3922
+ this.setScrollOffset(deltaX, deltaY);
3923
+ this.scroll();
3924
+ this.scrollLeft = this.target._left;
3925
+ this.scrollTop = this.target._top;
3926
+ };
3927
+ mouseEnterHandler = () => {
3928
+ this.enter = true;
3929
+ };
3930
+ mouseLeaveHandler = () => {
3931
+ this.enter = false;
3932
+ };
3933
+ targetMouseEnterHandler = () => {
3934
+ this.targetEnter = true;
3935
+ };
3936
+ targetMouseLeaveHandler = () => {
3937
+ this.targetEnter = false;
3938
+ };
3939
+ mousedownHandler = (event) => {
3940
+ if (!this.keydown)
3941
+ return;
3942
+ event.stopImmediatePropagation();
3943
+ event.stopPropagation();
3944
+ this.target.style.cursor = "grabbing";
3945
+ this.x = event.clientX;
3946
+ this.y = event.clientY;
3947
+ document.addEventListener("mousemove", this.mousemoveHandler);
3948
+ document.addEventListener("mouseup", this.mouseupHandler);
3949
+ };
3950
+ mouseupHandler = () => {
3951
+ this.x = 0;
3952
+ this.y = 0;
3953
+ this.scrollLeft = this.target._left;
3954
+ this.scrollTop = this.target._top;
3955
+ this.removeHandler();
3956
+ };
3957
+ mousemoveHandler = (event) => {
3958
+ event.stopImmediatePropagation();
3959
+ event.stopPropagation();
3960
+ const deltaX = event.clientX - this.x;
3961
+ const deltaY = event.clientY - this.y;
3962
+ this.setScrollOffset(deltaX, deltaY);
3963
+ this.scroll();
3964
+ };
3965
+ keydownHandler = (event) => {
3966
+ if (event.code === Keys.ESCAPE && this.enter) {
3967
+ event.preventDefault();
3968
+ event.stopImmediatePropagation();
3969
+ event.stopPropagation();
3970
+ }
3971
+ if (event.code !== Keys.ESCAPE || !this.enter || this.keydown) {
3972
+ return;
3973
+ }
3974
+ this.keydown = true;
3975
+ this.target.style.cursor = "grab";
3976
+ this.container.addEventListener("mousedown", this.mousedownHandler);
3977
+ };
3978
+ keyupHandler = (event) => {
3979
+ if (event.code !== Keys.ESCAPE || !this.keydown) {
3980
+ return;
3981
+ }
3982
+ event.preventDefault();
3983
+ event.stopImmediatePropagation();
3984
+ event.stopPropagation();
3985
+ this.keydown = false;
3986
+ event.preventDefault();
3987
+ this.removeHandler();
3988
+ };
3989
+ setScrollOffset(deltaX, deltaY) {
3990
+ const { width, height } = this.container.getBoundingClientRect();
3991
+ const targetRect = this.target.getBoundingClientRect();
3992
+ const targetWidth = targetRect.width * this.zoom;
3993
+ const targetHeight = targetRect.height * this.zoom;
3994
+ let y = 0;
3995
+ if (targetHeight > height) {
3996
+ if (deltaY > 0) {
3997
+ y = this.scrollTop + Math.min(targetHeight - height - this.scrollTop, deltaY);
3998
+ } else {
3999
+ y = this.scrollTop + Math.max(-(targetHeight - height + this.scrollTop), deltaY);
4000
+ }
4001
+ }
4002
+ let x = 0;
4003
+ if (targetWidth > width) {
4004
+ if (deltaX > 0) {
4005
+ x = this.scrollLeft + Math.min(targetWidth - width - this.scrollLeft, deltaX);
4006
+ } else {
4007
+ x = this.scrollLeft + Math.max(-(targetWidth - width + this.scrollLeft), deltaX);
4008
+ }
4009
+ }
4010
+ this.target._left = x;
4011
+ this.target._top = y;
4012
+ }
3620
4013
  }
3621
- var PageBar = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$4]]);
4014
+
4015
+ const _sfc_main$4 = vue.defineComponent({
4016
+ name: "m-editor-scroll-viewer",
4017
+ props: {
4018
+ width: Number,
4019
+ height: Number,
4020
+ zoom: {
4021
+ type: Number,
4022
+ default: 1
4023
+ }
4024
+ },
4025
+ setup(props) {
4026
+ const container = vue.ref();
4027
+ const el = vue.ref();
4028
+ let scrollViewer;
4029
+ vue.onMounted(() => {
4030
+ if (!container.value || !el.value)
4031
+ return;
4032
+ scrollViewer = new ScrollViewer$1({
4033
+ container: container.value,
4034
+ target: el.value,
4035
+ zoom: props.zoom
4036
+ });
4037
+ });
4038
+ vue.onUnmounted(() => {
4039
+ scrollViewer.destroy();
4040
+ });
4041
+ vue.watch(() => props.zoom, () => {
4042
+ scrollViewer.setZoom(props.zoom);
4043
+ });
4044
+ return {
4045
+ container,
4046
+ el,
4047
+ style: vue.computed(() => `
4048
+ width: ${props.width}px;
4049
+ height: ${props.height}px;
4050
+ position: absolute;
4051
+ margin-top: 30px;
4052
+ `)
4053
+ };
4054
+ }
4055
+ });
4056
+ const _hoisted_1$2 = {
4057
+ class: "m-editor-scroll-viewer-container",
4058
+ ref: "container"
4059
+ };
4060
+ function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
4061
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
4062
+ vue.createElementVNode("div", {
4063
+ ref: "el",
4064
+ style: vue.normalizeStyle(_ctx.style)
4065
+ }, [
4066
+ vue.renderSlot(_ctx.$slots, "default")
4067
+ ], 4)
4068
+ ], 512);
4069
+ }
4070
+ var ScrollViewer = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$4]]);
3622
4071
 
3623
4072
  const _sfc_main$3 = vue.defineComponent({
3624
4073
  name: "magic-editor-ui-viewer-menu",
@@ -3638,13 +4087,13 @@
3638
4087
  if (!parent.value || !editorService)
3639
4088
  return canCenter.value = false;
3640
4089
  const layout = await editorService.getLayout(parent.value);
3641
- canCenter.value = [Layout.ABSOLUTE, Layout.FIXED].includes(layout) && !["app", "page", "pop"].includes(`${node.value?.type}`);
4090
+ canCenter.value = [Layout.ABSOLUTE, Layout.FIXED].includes(layout) && ![schema.NodeType.ROOT, schema.NodeType.PAGE, "pop"].includes(`${node.value?.type}`);
3642
4091
  }, { immediate: true });
3643
4092
  return {
3644
4093
  menu,
3645
4094
  canPaste,
3646
- canDelete: vue.computed(() => node.value?.type !== "page"),
3647
- canMoveZPos: vue.computed(() => node.value?.type !== "page"),
4095
+ canDelete: vue.computed(() => node.value?.type !== schema.NodeType.PAGE),
4096
+ canMoveZPos: vue.computed(() => node.value?.type !== schema.NodeType.PAGE),
3648
4097
  canCenter,
3649
4098
  center() {
3650
4099
  node.value && editorService?.alignCenter(node.value);
@@ -3679,7 +4128,7 @@
3679
4128
  };
3680
4129
  }
3681
4130
  });
3682
- const _hoisted_1$2 = {
4131
+ const _hoisted_1$1 = {
3683
4132
  class: "magic-editor-content-menu",
3684
4133
  ref: "menu"
3685
4134
  };
@@ -3687,7 +4136,7 @@
3687
4136
  const _hoisted_3 = /* @__PURE__ */ vue.createElementVNode("div", { class: "separation" }, null, -1);
3688
4137
  const _hoisted_4 = /* @__PURE__ */ vue.createElementVNode("div", { class: "separation" }, null, -1);
3689
4138
  function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
3690
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
4139
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
3691
4140
  vue.createElementVNode("div", null, [
3692
4141
  _ctx.canCenter ? (vue.openBlock(), vue.createElementBlock("div", {
3693
4142
  key: 0,
@@ -3772,28 +4221,14 @@
3772
4221
  const _sfc_main$2 = vue.defineComponent({
3773
4222
  name: "magic-stage",
3774
4223
  components: {
3775
- ViewerMenu
4224
+ ViewerMenu,
4225
+ ScrollViewer
3776
4226
  },
3777
4227
  props: {
3778
4228
  render: {
3779
4229
  type: Function
3780
4230
  },
3781
4231
  runtimeUrl: String,
3782
- root: {
3783
- type: Object
3784
- },
3785
- page: {
3786
- type: Object
3787
- },
3788
- node: {
3789
- type: Object
3790
- },
3791
- uiSelectMode: {
3792
- type: Boolean
3793
- },
3794
- zoom: {
3795
- type: Number
3796
- },
3797
4232
  canSelect: {
3798
4233
  type: Function,
3799
4234
  default: (el) => Boolean(el.id)
@@ -3805,14 +4240,16 @@
3805
4240
  })
3806
4241
  }
3807
4242
  },
3808
- emits: ["select", "update", "sort"],
3809
- setup(props, { emit }) {
4243
+ setup(props) {
3810
4244
  const services = vue.inject("services");
4245
+ const stageWrap = vue.ref();
3811
4246
  const stageContainer = vue.ref();
3812
- const stageStyle = vue.computed(() => ({
3813
- ...services?.uiService.get("stageStyle"),
3814
- transform: `scale(${props.zoom}) translate3d(0, -50%, 0)`
3815
- }));
4247
+ const stageRect = vue.computed(() => services?.uiService.get("stageRect"));
4248
+ const uiSelectMode = vue.computed(() => services?.uiService.get("uiSelectMode"));
4249
+ const root = vue.computed(() => services?.editorService.get("root"));
4250
+ const page = vue.computed(() => services?.editorService.get("page"));
4251
+ const zoom = vue.computed(() => services?.uiService.get("zoom"));
4252
+ const node = vue.computed(() => services?.editorService.get("node"));
3816
4253
  let stage = null;
3817
4254
  let runtime = null;
3818
4255
  vue.watchEffect(() => {
@@ -3820,15 +4257,15 @@
3820
4257
  return;
3821
4258
  if (!stageContainer.value)
3822
4259
  return;
3823
- if (!(props.runtimeUrl || props.render) || !props.root)
4260
+ if (!(props.runtimeUrl || props.render) || !root.value)
3824
4261
  return;
3825
4262
  stage = new StageCore__default["default"]({
3826
4263
  render: props.render,
3827
4264
  runtimeUrl: props.runtimeUrl,
3828
- zoom: props.zoom,
3829
- canSelect: (el, stop) => {
4265
+ zoom: zoom.value,
4266
+ canSelect: (el, event, stop) => {
3830
4267
  const elCanSelect = props.canSelect(el);
3831
- if (props.uiSelectMode && elCanSelect) {
4268
+ if (uiSelectMode.value && elCanSelect && event.type === "mousedown") {
3832
4269
  document.dispatchEvent(new CustomEvent("ui-select", { detail: el }));
3833
4270
  return stop();
3834
4271
  }
@@ -3836,67 +4273,95 @@
3836
4273
  },
3837
4274
  moveableOptions: props.moveableOptions
3838
4275
  });
3839
- services?.editorService.set("stage", stage);
4276
+ services?.editorService.set("stage", vue.markRaw(stage));
3840
4277
  stage?.mount(stageContainer.value);
3841
- stage?.on("select", (el) => emit("select", el));
4278
+ stage?.on("select", (el) => {
4279
+ services?.editorService.select(el.id);
4280
+ });
4281
+ stage?.on("highlight", (el) => {
4282
+ services?.editorService.highlight(el.id);
4283
+ });
3842
4284
  stage?.on("update", (ev) => {
3843
- emit("update", { id: ev.el.id, style: ev.style });
4285
+ services?.editorService.update({ id: ev.el.id, style: ev.style });
3844
4286
  });
3845
4287
  stage?.on("sort", (ev) => {
3846
- emit("sort", ev);
4288
+ services?.editorService.sort(ev.src, ev.dist);
3847
4289
  });
3848
4290
  stage?.on("changeGuides", () => {
3849
4291
  services?.uiService.set("showGuides", true);
3850
4292
  });
3851
- if (!props.node?.id)
4293
+ if (!node.value?.id)
3852
4294
  return;
3853
4295
  stage?.on("runtime-ready", (rt) => {
3854
4296
  runtime = rt;
3855
- props.root && runtime?.updateRootConfig(lodashEs.cloneDeep(vue.toRaw(props.root)));
3856
- props.page?.id && runtime?.updatePageId?.(props.page.id);
4297
+ root.value && runtime?.updateRootConfig(lodashEs.cloneDeep(vue.toRaw(root.value)));
4298
+ page.value?.id && runtime?.updatePageId?.(page.value.id);
3857
4299
  setTimeout(() => {
3858
- props.node && stage?.select(vue.toRaw(props.node.id));
4300
+ node.value && stage?.select(vue.toRaw(node.value.id));
3859
4301
  });
3860
4302
  });
3861
4303
  });
3862
- vue.watch(() => props.zoom, (zoom) => {
3863
- if (!stage || !zoom)
4304
+ vue.watch(zoom, (zoom2) => {
4305
+ if (!stage || !zoom2)
3864
4306
  return;
3865
- stage?.setZoom(zoom);
4307
+ stage.setZoom(zoom2);
4308
+ });
4309
+ vue.watch(root, (root2) => {
4310
+ if (runtime && root2) {
4311
+ runtime.updateRootConfig(lodashEs.cloneDeep(vue.toRaw(root2)));
4312
+ }
3866
4313
  });
3867
- vue.watch(() => props.root, (root) => {
3868
- if (runtime && root) {
3869
- runtime.updateRootConfig(lodashEs.cloneDeep(vue.toRaw(root)));
4314
+ const resizeObserver = new ResizeObserver((entries) => {
4315
+ for (const { contentRect } of entries) {
4316
+ services?.uiService.set("stageContainerRect", {
4317
+ width: contentRect.width,
4318
+ height: contentRect.height
4319
+ });
3870
4320
  }
3871
4321
  });
4322
+ vue.onMounted(() => {
4323
+ stageWrap.value?.container && resizeObserver.observe(stageWrap.value.container);
4324
+ });
3872
4325
  vue.onUnmounted(() => {
3873
4326
  stage?.destroy();
4327
+ resizeObserver.disconnect();
3874
4328
  services?.editorService.set("stage", null);
3875
4329
  });
3876
4330
  return {
3877
- stageStyle,
3878
- ...useMenu(),
3879
- stageContainer
4331
+ stageWrap,
4332
+ stageContainer,
4333
+ stageRect,
4334
+ zoom,
4335
+ ...useMenu()
3880
4336
  };
3881
4337
  }
3882
4338
  });
3883
- const _hoisted_1$1 = { class: "m-editor-stage" };
3884
4339
  function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
3885
4340
  const _component_viewer_menu = vue.resolveComponent("viewer-menu");
3886
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
3887
- vue.createElementVNode("div", {
3888
- class: "m-editor-stage-container",
3889
- ref: "stageContainer",
3890
- style: vue.normalizeStyle(_ctx.stageStyle),
3891
- onContextmenu: _cache[0] || (_cache[0] = (...args) => _ctx.contextmenuHandler && _ctx.contextmenuHandler(...args))
3892
- }, null, 36),
3893
- (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
3894
- vue.createVNode(_component_viewer_menu, {
3895
- ref: "menu",
3896
- style: vue.normalizeStyle(_ctx.menuStyle)
3897
- }, null, 8, ["style"])
3898
- ]))
3899
- ]);
4341
+ const _component_scroll_viewer = vue.resolveComponent("scroll-viewer");
4342
+ return vue.openBlock(), vue.createBlock(_component_scroll_viewer, {
4343
+ class: "m-editor-stage",
4344
+ ref: "stageWrap",
4345
+ width: _ctx.stageRect?.width,
4346
+ height: _ctx.stageRect?.height,
4347
+ zoom: _ctx.zoom
4348
+ }, {
4349
+ default: vue.withCtx(() => [
4350
+ vue.createElementVNode("div", {
4351
+ class: "m-editor-stage-container",
4352
+ ref: "stageContainer",
4353
+ onContextmenu: _cache[0] || (_cache[0] = (...args) => _ctx.contextmenuHandler && _ctx.contextmenuHandler(...args)),
4354
+ style: vue.normalizeStyle(`transform: scale(${_ctx.zoom})`)
4355
+ }, null, 36),
4356
+ (vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
4357
+ vue.createVNode(_component_viewer_menu, {
4358
+ ref: "menu",
4359
+ style: vue.normalizeStyle(_ctx.menuStyle)
4360
+ }, null, 8, ["style"])
4361
+ ]))
4362
+ ]),
4363
+ _: 1
4364
+ }, 8, ["width", "height", "zoom"]);
3900
4365
  }
3901
4366
  var MagicStage = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
3902
4367
 
@@ -3920,32 +4385,48 @@
3920
4385
  },
3921
4386
  setup() {
3922
4387
  const services = vue.inject("services");
4388
+ const workspace = vue.ref();
3923
4389
  const node = vue.computed(() => services?.editorService.get("node"));
3924
- const stage = vue.computed(() => services?.editorService.get("stage"));
3925
- vue.watch([() => node.value?.id, stage], ([id, stage2]) => {
3926
- vue.nextTick(() => {
3927
- id && stage2?.select(id);
4390
+ let keycon;
4391
+ const mouseenterHandler = () => {
4392
+ workspace.value?.focus();
4393
+ };
4394
+ const mouseleaveHandler = () => {
4395
+ workspace.value?.blur();
4396
+ };
4397
+ vue.onMounted(() => {
4398
+ workspace.value?.addEventListener("mouseenter", mouseenterHandler);
4399
+ workspace.value?.addEventListener("mouseleave", mouseleaveHandler);
4400
+ keycon = new KeyController__default["default"](workspace.value);
4401
+ keycon.keyup("delete", () => {
4402
+ node.value && services?.editorService.remove(node.value);
4403
+ }).keyup(["ctrl", "c"], () => {
4404
+ node.value && services?.editorService.copy(node.value);
4405
+ }).keyup(["ctrl", "v"], () => {
4406
+ node.value && services?.editorService.paste();
4407
+ }).keyup(["ctrl", "x"], () => {
4408
+ if (node.value && services) {
4409
+ services.editorService.copy(node.value);
4410
+ services.editorService.remove(node.value);
4411
+ }
3928
4412
  });
3929
4413
  });
4414
+ vue.onUnmounted(() => {
4415
+ workspace.value?.removeEventListener("mouseenter", mouseenterHandler);
4416
+ workspace.value?.removeEventListener("mouseleave", mouseleaveHandler);
4417
+ keycon.destroy();
4418
+ });
3930
4419
  return {
3931
- uiSelectMode: vue.computed(() => services?.uiService.get("uiSelectMode")),
3932
- root: vue.computed(() => services?.editorService.get("root")),
3933
- page: vue.computed(() => services?.editorService.get("page")),
3934
- zoom: vue.computed(() => services?.uiService.get("zoom")),
3935
- node,
3936
- selectHandler(el) {
3937
- services?.editorService.select(el.id);
3938
- },
3939
- updateNodeHandler(node2) {
3940
- services?.editorService.update(node2);
3941
- },
3942
- sortNodeHandler(ev) {
3943
- services?.editorService.sort(ev.src, ev.dist);
3944
- }
4420
+ workspace,
4421
+ page: vue.computed(() => services?.editorService.get("page"))
3945
4422
  };
3946
4423
  }
3947
4424
  });
3948
- const _hoisted_1 = { class: "m-editor-workspace" };
4425
+ const _hoisted_1 = {
4426
+ class: "m-editor-workspace",
4427
+ tabindex: "1",
4428
+ ref: "workspace"
4429
+ };
3949
4430
  function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
3950
4431
  const _component_magic_stage = vue.resolveComponent("magic-stage");
3951
4432
  const _component_page_bar = vue.resolveComponent("page-bar");
@@ -3954,17 +4435,9 @@
3954
4435
  key: _ctx.page?.id,
3955
4436
  "runtime-url": _ctx.runtimeUrl,
3956
4437
  render: _ctx.render,
3957
- "ui-select-mode": _ctx.uiSelectMode,
3958
- root: _ctx.root,
3959
- page: _ctx.page,
3960
- node: _ctx.node,
3961
- zoom: _ctx.zoom,
3962
4438
  "moveable-options": _ctx.moveableOptions,
3963
- "can-select": _ctx.canSelect,
3964
- onSelect: _ctx.selectHandler,
3965
- onUpdate: _ctx.updateNodeHandler,
3966
- onSort: _ctx.sortNodeHandler
3967
- }, null, 8, ["runtime-url", "render", "ui-select-mode", "root", "page", "node", "zoom", "moveable-options", "can-select", "onSelect", "onUpdate", "onSort"])),
4439
+ "can-select": _ctx.canSelect
4440
+ }, null, 8, ["runtime-url", "render", "moveable-options", "can-select"])),
3968
4441
  vue.renderSlot(_ctx.$slots, "workspace-content"),
3969
4442
  vue.createVNode(_component_page_bar, null, {
3970
4443
  "page-bar-title": vue.withCtx(({ page }) => [
@@ -3975,7 +4448,7 @@
3975
4448
  ]),
3976
4449
  _: 3
3977
4450
  })
3978
- ]);
4451
+ ], 512);
3979
4452
  }
3980
4453
  var Workspace = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1]]);
3981
4454
 
@@ -3995,15 +4468,24 @@
3995
4468
  }
3996
4469
  var componentListService = new ComponentList();
3997
4470
 
4471
+ const DEFAULT_LEFT_COLUMN_WIDTH = 310;
4472
+ const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
3998
4473
  const state = vue.reactive({
3999
4474
  uiSelectMode: false,
4000
4475
  showSrc: false,
4001
4476
  zoom: 1,
4002
- stageStyle: {},
4477
+ stageContainerRect: {
4478
+ width: 0,
4479
+ height: 0
4480
+ },
4481
+ stageRect: {
4482
+ width: 375,
4483
+ height: 817
4484
+ },
4003
4485
  columnWidth: {
4004
- left: 310,
4005
- center: globalThis.document.body.clientWidth - 310 - 400,
4006
- right: 400
4486
+ left: DEFAULT_LEFT_COLUMN_WIDTH,
4487
+ center: globalThis.document.body.clientWidth - DEFAULT_LEFT_COLUMN_WIDTH - DEFAULT_RIGHT_COLUMN_WIDTH,
4488
+ right: DEFAULT_RIGHT_COLUMN_WIDTH
4007
4489
  },
4008
4490
  showGuides: true,
4009
4491
  showRule: true
@@ -4023,6 +4505,10 @@
4023
4505
  this.setColumnWidth(value);
4024
4506
  return;
4025
4507
  }
4508
+ if (name === "stageRect") {
4509
+ this.setStageRect(value);
4510
+ return;
4511
+ }
4026
4512
  if (name === "showGuides") {
4027
4513
  mask?.showGuides(value);
4028
4514
  }
@@ -4030,6 +4516,9 @@
4030
4516
  mask?.showRule(value);
4031
4517
  }
4032
4518
  state[name] = value;
4519
+ if (name === "stageContainerRect") {
4520
+ state.zoom = this.calcZoom();
4521
+ }
4033
4522
  }
4034
4523
  get(name) {
4035
4524
  return state[name];
@@ -4052,6 +4541,23 @@
4052
4541
  }
4053
4542
  state.columnWidth = columnWidth;
4054
4543
  }
4544
+ setStageRect(value) {
4545
+ state.stageRect = {
4546
+ ...state.stageRect,
4547
+ ...value
4548
+ };
4549
+ state.zoom = this.calcZoom();
4550
+ }
4551
+ calcZoom() {
4552
+ const { stageRect, stageContainerRect } = state;
4553
+ const { height, width } = stageContainerRect;
4554
+ if (!width || !height)
4555
+ return 1;
4556
+ if (width > stageRect.width && height > stageRect.height) {
4557
+ return 1;
4558
+ }
4559
+ return Math.min((width - 100) / stageRect.width || 1, (height - 100) / stageRect.height || 1);
4560
+ }
4055
4561
  }
4056
4562
  var uiService = new Ui();
4057
4563
 
@@ -4106,7 +4612,7 @@
4106
4612
  canSelect: {
4107
4613
  type: Function
4108
4614
  },
4109
- stageStyle: {
4615
+ stageRect: {
4110
4616
  type: [String, Object]
4111
4617
  }
4112
4618
  },
@@ -4144,7 +4650,7 @@
4144
4650
  vue.watch(() => props.defaultSelected, (defaultSelected) => defaultSelected && editorService.select(defaultSelected), {
4145
4651
  immediate: true
4146
4652
  });
4147
- vue.watch(() => props.stageStyle, (stageStyle) => uiService.set("stageStyle", stageStyle), {
4653
+ vue.watch(() => props.stageRect, (stageRect) => stageRect && uiService.set("stageRect", stageRect), {
4148
4654
  immediate: true
4149
4655
  });
4150
4656
  vue.onUnmounted(() => editorService.destroy());
@@ -4234,6 +4740,7 @@
4234
4740
  exports.ComponentListPanel = ComponentListPanel;
4235
4741
  exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
4236
4742
  exports.Fixed2Other = Fixed2Other;
4743
+ exports.Keys = Keys;
4237
4744
  exports.LayerOffset = LayerOffset;
4238
4745
  exports.LayerPanel = LayerPanel;
4239
4746
  exports.Layout = Layout;
@@ -4243,7 +4750,6 @@
4243
4750
  exports.change2Fixed = change2Fixed;
4244
4751
  exports.debug = debug;
4245
4752
  exports["default"] = index;
4246
- exports.defaults = defaults;
4247
4753
  exports.editorService = editorService;
4248
4754
  exports.error = error;
4249
4755
  exports.eventsService = eventsService;