@tmagic/editor 1.3.0-alpha.4 → 1.3.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.0-alpha.4",
2
+ "version": "1.3.0-alpha.6",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -46,13 +46,13 @@
46
46
  "dependencies": {
47
47
  "@babel/core": "^7.18.0",
48
48
  "@element-plus/icons-vue": "^2.0.9",
49
- "@tmagic/core": "1.3.0-alpha.4",
50
- "@tmagic/design": "1.3.0-alpha.4",
51
- "@tmagic/form": "1.3.0-alpha.4",
52
- "@tmagic/schema": "1.3.0-alpha.4",
53
- "@tmagic/stage": "1.3.0-alpha.4",
54
- "@tmagic/table": "1.3.0-alpha.4",
55
- "@tmagic/utils": "1.3.0-alpha.4",
49
+ "@tmagic/core": "1.3.0-alpha.6",
50
+ "@tmagic/design": "1.3.0-alpha.6",
51
+ "@tmagic/form": "1.3.0-alpha.6",
52
+ "@tmagic/schema": "1.3.0-alpha.6",
53
+ "@tmagic/stage": "1.3.0-alpha.6",
54
+ "@tmagic/table": "1.3.0-alpha.6",
55
+ "@tmagic/utils": "1.3.0-alpha.6",
56
56
  "buffer": "^6.0.3",
57
57
  "color": "^3.1.3",
58
58
  "events": "^3.3.0",
@@ -64,8 +64,8 @@
64
64
  "vue": "^3.3.4"
65
65
  },
66
66
  "peerDependencies": {
67
- "@tmagic/design": "1.3.0-alpha.4",
68
- "@tmagic/form": "1.3.0-alpha.4",
67
+ "@tmagic/design": "1.3.0-alpha.6",
68
+ "@tmagic/form": "1.3.0-alpha.6",
69
69
  "monaco-editor": "^0.34.0",
70
70
  "vue": "^3.3.4"
71
71
  },
package/src/Editor.vue CHANGED
@@ -1,9 +1,19 @@
1
1
  <template>
2
- <Framework :code-options="codeOptions">
2
+ <Framework>
3
+ <template #header>
4
+ <slot name="header"></slot>
5
+ </template>
6
+
3
7
  <template #nav>
4
8
  <slot name="nav" :editorService="editorService"><TMagicNavMenu :data="menu"></TMagicNavMenu></slot>
5
9
  </template>
6
10
 
11
+ <template #content-before>
12
+ <slot name="content-before"></slot>
13
+ </template>
14
+
15
+ <template #src-code><slot name="src-code" :editorService="editorService"></slot></template>
16
+
7
17
  <template #sidebar>
8
18
  <slot name="sidebar" :editorService="editorService">
9
19
  <Sidebar :data="sidebar" :layer-content-menu="layerContentMenu">
@@ -60,6 +70,14 @@
60
70
  </template>
61
71
 
62
72
  <template #empty><slot name="empty" :editorService="editorService"></slot></template>
73
+
74
+ <template #content-after>
75
+ <slot name="content-after"></slot>
76
+ </template>
77
+
78
+ <template #footer>
79
+ <slot name="footer"></slot>
80
+ </template>
63
81
  </Framework>
64
82
  </template>
65
83
 
@@ -78,6 +96,7 @@ import depService from './services/dep';
78
96
  import editorService from './services/editor';
79
97
  import eventsService from './services/events';
80
98
  import historyService from './services/history';
99
+ import keybindingService from './services/keybinding';
81
100
  import propsService from './services/props';
82
101
  import storageService from './services/storage';
83
102
  import uiService from './services/ui';
@@ -112,6 +131,7 @@ export default defineComponent({
112
131
  codeBlockService,
113
132
  depService,
114
133
  dataSourceService,
134
+ keybindingService,
115
135
  };
116
136
 
117
137
  initServiceEvents(props, emit, services);
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <span ref="target" class="m-editor-resizer">
2
+ <span ref="target" class="m-editor-resizer" :class="{ 'm-editor-resizer-draging': isDraging }">
3
3
  <slot></slot>
4
4
  </span>
5
5
  </template>
@@ -15,6 +15,7 @@ defineOptions({
15
15
  const emit = defineEmits(['change']);
16
16
 
17
17
  const target = ref<HTMLSpanElement>();
18
+ const isDraging = ref(false);
18
19
 
19
20
  let getso: Gesto;
20
21
 
@@ -23,14 +24,22 @@ onMounted(() => {
23
24
  getso = new Gesto(target.value, {
24
25
  container: window,
25
26
  pinchOutside: true,
26
- }).on('drag', (e) => {
27
- if (!target.value) return;
28
-
29
- emit('change', e.deltaX);
30
- });
27
+ })
28
+ .on('drag', (e) => {
29
+ if (!target.value) return;
30
+
31
+ emit('change', e.deltaX);
32
+ })
33
+ .on('dragStart', () => {
34
+ isDraging.value = true;
35
+ })
36
+ .on('dragEnd', () => {
37
+ isDraging.value = false;
38
+ });
31
39
  });
32
40
 
33
41
  onUnmounted(() => {
34
42
  getso?.unset();
43
+ isDraging.value = false;
35
44
  });
36
45
  </script>
@@ -23,7 +23,7 @@
23
23
  <script lang="ts" setup>
24
24
  import { computed, onMounted, onUnmounted, ref } from 'vue';
25
25
 
26
- import Resizer from '@editor/layouts/Resizer.vue';
26
+ import Resizer from './Resizer.vue';
27
27
 
28
28
  defineOptions({
29
29
  name: 'MEditorLayout',
package/src/index.ts CHANGED
@@ -60,7 +60,8 @@ export { default as PropsPanel } from './layouts/PropsPanel.vue';
60
60
  export { default as ToolButton } from './components/ToolButton.vue';
61
61
  export { default as ContentMenu } from './components/ContentMenu.vue';
62
62
  export { default as Icon } from './components/Icon.vue';
63
- export { default as LayoutContainer } from './components/Layout.vue';
63
+ export { default as LayoutContainer } from './components/SplitView.vue';
64
+ export { default as SplitView } from './components/SplitView.vue';
64
65
 
65
66
  const defaultInstallOpt: InstallOptions = {
66
67
  // @todo, 自定义图片上传方法等编辑器依赖的外部选项
@@ -14,8 +14,8 @@ defineOptions({
14
14
 
15
15
  const props = withDefaults(
16
16
  defineProps<{
17
- initValues?: string | Object;
18
- modifiedValues?: string | Object;
17
+ initValues?: string | Record<string | number, any> | null;
18
+ modifiedValues?: string | Record<string | number, any> | null;
19
19
  type?: 'diff';
20
20
  language?: string;
21
21
  options?: {
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <div class="m-editor">
3
- <slot name="nav" class="m-editor-nav-menu"></slot>
3
+ <slot name="header"></slot>
4
4
 
5
- <magic-code-editor
6
- v-if="showSrc"
7
- class="m-editor-content"
8
- :init-values="root"
9
- :options="codeOptions"
10
- @save="saveCode"
11
- ></magic-code-editor>
5
+ <slot name="nav"></slot>
6
+
7
+ <slot name="content-before"></slot>
12
8
 
13
- <Layout
9
+ <slot name="src-code" v-if="showSrc">
10
+ <CodeEditor class="m-editor-content" :init-values="root" :options="codeOptions" @save="saveCode"></CodeEditor>
11
+ </slot>
12
+
13
+ <SplitView
14
14
  v-else
15
15
  class="m-editor-content"
16
16
  left-class="m-editor-framework-left"
@@ -38,7 +38,10 @@
38
38
  <slot name="props-panel"></slot>
39
39
  </TMagicScrollbar>
40
40
  </template>
41
- </Layout>
41
+ </SplitView>
42
+
43
+ <slot name="content-after"></slot>
44
+ <slot name="footer"></slot>
42
45
  </div>
43
46
  </template>
44
47
 
@@ -47,10 +50,11 @@ import { computed, inject, ref, watch } from 'vue';
47
50
 
48
51
  import { TMagicScrollbar } from '@tmagic/design';
49
52
 
50
- import Layout from '@editor/components/Layout.vue';
53
+ import SplitView from '@editor/components/SplitView.vue';
51
54
  import type { GetColumnWidth, Services } from '@editor/type';
52
55
 
53
56
  import AddPageBox from './AddPageBox.vue';
57
+ import CodeEditor from './CodeEditor.vue';
54
58
 
55
59
  defineOptions({
56
60
  name: 'MEditorFramework',
@@ -59,15 +63,7 @@ defineOptions({
59
63
  const DEFAULT_LEFT_COLUMN_WIDTH = 310;
60
64
  const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
61
65
 
62
- withDefaults(
63
- defineProps<{
64
- codeOptions?: Record<string, any>;
65
- }>(),
66
- {
67
- codeOptions: () => ({}),
68
- },
69
- );
70
-
66
+ const codeOptions = inject('codeOptions', {});
71
67
  const { editorService, uiService } = inject<Services>('services') || {};
72
68
 
73
69
  const root = computed(() => editorService?.get('root'));
@@ -10,6 +10,7 @@
10
10
  ref="tree"
11
11
  node-key="id"
12
12
  empty-text="页面空荡荡的"
13
+ tabindex="-1"
13
14
  draggable
14
15
  :default-expanded-keys="expandedKeys"
15
16
  :default-checked-keys="checkedKeys"
@@ -75,6 +76,7 @@ defineProps<{
75
76
  const throttleTime = 150;
76
77
  const services = inject<Services>('services');
77
78
  const editorService = services?.editorService;
79
+ const keybindingService = services?.keybindingService;
78
80
 
79
81
  const tree = ref<InstanceType<typeof TMagicTree>>();
80
82
  const menu = ref<InstanceType<typeof LayerMenu>>();
@@ -246,27 +248,40 @@ const windowBlurHandler = () => {
246
248
  isCtrlKeyDown.value = false;
247
249
  };
248
250
 
251
+ const globalKeyupHandler = () => {
252
+ if (document.activeElement !== tree.value?.$el) {
253
+ isCtrlKeyDown.value = false;
254
+ }
255
+ };
256
+
249
257
  let keycon: KeyController;
250
258
 
251
259
  onMounted(() => {
252
260
  editorService?.on('remove', editorServiceRemoveHandler);
253
261
 
254
- keycon = new KeyController();
255
- const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
256
- const ctrl = isMac ? 'meta' : 'ctrl';
257
-
258
- keycon
259
- .keydown((e) => {
260
- if (e.key !== ctrl) {
262
+ if (tree.value?.$el) {
263
+ // 如果是在树上按下ctrl,那么在树外松开ctrl时,也要触发松开事件
264
+ keybindingService?.on('keyup', globalKeyupHandler);
265
+
266
+ keycon = new KeyController(tree.value.$el);
267
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
268
+ const ctrl = isMac ? 'meta' : 'ctrl';
269
+
270
+ keycon
271
+ .keydown((e) => {
272
+ if (e.key !== ctrl) {
273
+ isCtrlKeyDown.value = false;
274
+ }
275
+ })
276
+ .keydown(ctrl, () => {
277
+ isCtrlKeyDown.value = true;
278
+ })
279
+ .keyup(ctrl, () => {
261
280
  isCtrlKeyDown.value = false;
262
- }
263
- })
264
- .keydown(ctrl, () => {
265
- isCtrlKeyDown.value = true;
266
- })
267
- .keyup(ctrl, () => {
268
- isCtrlKeyDown.value = false;
269
- });
281
+ });
282
+
283
+ tree.value.$el.addEventListener('blur', windowBlurHandler);
284
+ }
270
285
 
271
286
  globalThis.addEventListener('blur', windowBlurHandler);
272
287
  });
@@ -275,7 +290,9 @@ onUnmounted(() => {
275
290
  keycon.destroy();
276
291
 
277
292
  editorService?.off('remove', editorServiceRemoveHandler);
293
+ keybindingService?.off('keyup', globalKeyupHandler);
278
294
  globalThis.removeEventListener('blur', windowBlurHandler);
295
+ tree.value?.$el.removeEventListener('blur', windowBlurHandler);
279
296
  });
280
297
 
281
298
  // 鼠标在组件树移动触发高亮
@@ -10,7 +10,7 @@
10
10
  :size="size"
11
11
  :before-close="handleClose"
12
12
  >
13
- <Layout v-model:left="left" :min-left="45" class="code-editor-layout">
13
+ <SplitView v-model:left="left" :min-left="45" class="code-editor-layout">
14
14
  <!-- 右侧区域 -->
15
15
  <template #center>
16
16
  <div v-if="!isEmpty(codeConfig)" class="m-editor-code-block-editor-panel">
@@ -28,7 +28,7 @@
28
28
  ></FunctionEditor>
29
29
  </div>
30
30
  </template>
31
- </Layout>
31
+ </SplitView>
32
32
  </TMagicDrawer>
33
33
  </template>
34
34
 
@@ -41,7 +41,7 @@ import { ColumnConfig } from '@tmagic/form';
41
41
  import { CodeBlockContent } from '@tmagic/schema';
42
42
 
43
43
  import FunctionEditor from '@editor/components/FunctionEditor.vue';
44
- import Layout from '@editor/components/Layout.vue';
44
+ import SplitView from '@editor/components/SplitView.vue';
45
45
  import type { ListState, Services } from '@editor/type';
46
46
  import { serializeConfig } from '@editor/utils/editor';
47
47
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="m-editor-workspace" tabindex="-1" ref="workspace">
2
+ <div class="m-editor-workspace" tabindex="-1">
3
3
  <Breadcrumb></Breadcrumb>
4
4
 
5
5
  <slot name="stage">
@@ -16,10 +16,7 @@
16
16
  </template>
17
17
 
18
18
  <script lang="ts" setup>
19
- import { computed, inject, onMounted, onUnmounted, ref } from 'vue';
20
- import KeyController from 'keycon';
21
-
22
- import { isPage } from '@tmagic/utils';
19
+ import { computed, inject } from 'vue';
23
20
 
24
21
  import type { MenuButton, MenuComponent, Services } from '@editor/type';
25
22
 
@@ -36,132 +33,6 @@ defineProps<{
36
33
  }>();
37
34
 
38
35
  const services = inject<Services>('services');
39
- const workspace = ref<HTMLDivElement>();
40
- const nodes = computed(() => services?.editorService.get('nodes'));
41
- const page = computed(() => services?.editorService.get('page'));
42
-
43
- const mouseenterHandler = () => {
44
- workspace.value?.focus();
45
- };
46
-
47
- const mouseleaveHandler = () => {
48
- workspace.value?.blur();
49
- };
50
-
51
- let keycon: KeyController;
52
-
53
- onMounted(() => {
54
- workspace.value?.addEventListener('mouseenter', mouseenterHandler);
55
- workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
56
-
57
- keycon = new KeyController(workspace.value);
58
36
 
59
- const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
60
-
61
- const ctrl = isMac ? 'meta' : 'ctrl';
62
-
63
- keycon
64
- .keyup('delete', (e) => {
65
- e.inputEvent.preventDefault();
66
- if (!nodes.value || isPage(nodes.value[0])) return;
67
- services?.editorService.remove(nodes.value);
68
- })
69
- .keyup('backspace', (e) => {
70
- e.inputEvent.preventDefault();
71
- if (!nodes.value || isPage(nodes.value[0])) return;
72
- services?.editorService.remove(nodes.value);
73
- })
74
- .keydown([ctrl, 'c'], (e) => {
75
- e.inputEvent.preventDefault();
76
- nodes.value && services?.editorService.copy(nodes.value);
77
- })
78
- .keydown([ctrl, 'v'], (e) => {
79
- e.inputEvent.preventDefault();
80
- nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
81
- })
82
- .keydown([ctrl, 'x'], (e) => {
83
- e.inputEvent.preventDefault();
84
- if (!nodes.value || isPage(nodes.value[0])) return;
85
- services?.editorService.copy(nodes.value);
86
- services?.editorService.remove(nodes.value);
87
- })
88
- .keydown([ctrl, 'z'], (e) => {
89
- e.inputEvent.preventDefault();
90
- services?.editorService.undo();
91
- })
92
- .keydown([ctrl, 'shift', 'z'], (e) => {
93
- e.inputEvent.preventDefault();
94
- services?.editorService.redo();
95
- })
96
- .keydown('up', (e) => {
97
- e.inputEvent.preventDefault();
98
- services?.editorService.move(0, -1);
99
- })
100
- .keydown('down', (e) => {
101
- e.inputEvent.preventDefault();
102
- services?.editorService.move(0, 1);
103
- })
104
- .keydown('left', (e) => {
105
- e.inputEvent.preventDefault();
106
- services?.editorService.move(-1, 0);
107
- })
108
- .keydown('right', (e) => {
109
- e.inputEvent.preventDefault();
110
- services?.editorService.move(1, 0);
111
- })
112
- .keydown([ctrl, 'up'], (e) => {
113
- e.inputEvent.preventDefault();
114
- services?.editorService.move(0, -10);
115
- })
116
- .keydown([ctrl, 'down'], (e) => {
117
- e.inputEvent.preventDefault();
118
- services?.editorService.move(0, 10);
119
- })
120
- .keydown([ctrl, 'left'], (e) => {
121
- e.inputEvent.preventDefault();
122
- services?.editorService.move(-10, 0);
123
- })
124
- .keydown([ctrl, 'right'], (e) => {
125
- e.inputEvent.preventDefault();
126
- services?.editorService.move(10, 0);
127
- })
128
- .keydown('tab', (e) => {
129
- e.inputEvent.preventDefault();
130
- services?.editorService.selectNextNode();
131
- })
132
- .keydown([ctrl, 'tab'], (e) => {
133
- e.inputEvent.preventDefault();
134
- services?.editorService.selectNextPage();
135
- })
136
- .keydown([ctrl, '='], (e) => {
137
- e.inputEvent.preventDefault();
138
- services?.uiService.zoom(0.1);
139
- })
140
- .keydown([ctrl, 'numpadplus'], (e) => {
141
- e.inputEvent.preventDefault();
142
- services?.uiService.zoom(0.1);
143
- })
144
- .keydown([ctrl, '-'], (e) => {
145
- e.inputEvent.preventDefault();
146
- services?.uiService.zoom(-0.1);
147
- })
148
- .keydown([ctrl, 'numpad-'], (e) => {
149
- e.inputEvent.preventDefault();
150
- services?.uiService.zoom(-0.1);
151
- })
152
- .keydown([ctrl, '0'], async (e) => {
153
- e.inputEvent.preventDefault();
154
- services?.uiService.set('zoom', await services.uiService.calcZoom());
155
- })
156
- .keydown([ctrl, '1'], (e) => {
157
- e.inputEvent.preventDefault();
158
- services?.uiService.set('zoom', 1);
159
- });
160
- });
161
-
162
- onUnmounted(() => {
163
- workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
164
- workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
165
- keycon.destroy();
166
- });
37
+ const page = computed(() => services?.editorService.get('page'));
167
38
  </script>