@tmagic/editor 1.1.0-beta.7 → 1.1.0

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 (63) hide show
  1. package/dist/style.css +50 -0
  2. package/dist/tmagic-editor.mjs +1198 -1027
  3. package/dist/tmagic-editor.mjs.map +1 -1
  4. package/dist/tmagic-editor.umd.js +1201 -1026
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/package.json +10 -10
  7. package/src/Editor.vue +22 -6
  8. package/src/components/ContentMenu.vue +4 -4
  9. package/src/components/Icon.vue +7 -21
  10. package/src/components/ScrollBar.vue +147 -0
  11. package/src/components/ScrollViewer.vue +89 -44
  12. package/src/components/ToolButton.vue +40 -138
  13. package/src/fields/UISelect.vue +2 -2
  14. package/src/index.ts +2 -0
  15. package/src/layouts/NavMenu.vue +156 -23
  16. package/src/layouts/PropsPanel.vue +49 -51
  17. package/src/layouts/sidebar/LayerMenu.vue +3 -3
  18. package/src/layouts/sidebar/LayerPanel.vue +39 -8
  19. package/src/layouts/workspace/PageBar.vue +1 -1
  20. package/src/layouts/workspace/Stage.vue +8 -86
  21. package/src/layouts/workspace/ViewerMenu.vue +10 -13
  22. package/src/layouts/workspace/Workspace.vue +133 -138
  23. package/src/services/componentList.ts +5 -0
  24. package/src/services/editor.ts +201 -112
  25. package/src/services/events.ts +8 -2
  26. package/src/services/props.ts +31 -52
  27. package/src/services/storage.ts +4 -0
  28. package/src/services/ui.ts +32 -30
  29. package/src/theme/component-list-panel.scss +5 -0
  30. package/src/theme/nav-menu.scss +6 -0
  31. package/src/type.ts +28 -11
  32. package/src/utils/editor.ts +17 -10
  33. package/src/utils/index.ts +1 -0
  34. package/src/utils/operator.ts +22 -123
  35. package/src/utils/props.ts +0 -3
  36. package/src/utils/scroll-viewer.ts +90 -158
  37. package/src/utils/stage.ts +91 -0
  38. package/types/Editor.vue.d.ts +17 -8
  39. package/types/components/ContentMenu.vue.d.ts +8 -8
  40. package/types/components/Icon.vue.d.ts +62 -12
  41. package/types/components/ScrollBar.vue.d.ts +83 -0
  42. package/types/components/ScrollViewer.vue.d.ts +131 -19
  43. package/types/components/ToolButton.vue.d.ts +56 -59
  44. package/types/index.d.ts +2 -0
  45. package/types/layouts/NavMenu.vue.d.ts +92 -23
  46. package/types/layouts/PropsPanel.vue.d.ts +25 -208
  47. package/types/layouts/sidebar/LayerMenu.vue.d.ts +7 -7
  48. package/types/layouts/sidebar/LayerPanel.vue.d.ts +17 -15
  49. package/types/layouts/workspace/ViewerMenu.vue.d.ts +3 -3
  50. package/types/layouts/workspace/Workspace.vue.d.ts +54 -4
  51. package/types/services/componentList.d.ts +1 -0
  52. package/types/services/editor.d.ts +10 -17
  53. package/types/services/events.d.ts +1 -0
  54. package/types/services/props.d.ts +41 -9
  55. package/types/services/storage.d.ts +1 -0
  56. package/types/services/ui.d.ts +3 -1
  57. package/types/type.d.ts +25 -11
  58. package/types/utils/editor.d.ts +4 -1
  59. package/types/utils/index.d.ts +1 -0
  60. package/types/utils/operator.d.ts +3 -26
  61. package/types/utils/props.d.ts +0 -1
  62. package/types/utils/scroll-viewer.d.ts +16 -18
  63. package/types/utils/stage.d.ts +3 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0-beta.7",
2
+ "version": "1.1.0",
3
3
  "name": "@tmagic/editor",
4
4
  "sideEffects": [
5
5
  "dist/*",
@@ -44,12 +44,12 @@
44
44
  ],
45
45
  "dependencies": {
46
46
  "@babel/core": "^7.18.0",
47
- "@element-plus/icons-vue": "^2.0.6",
48
- "@tmagic/core": "1.1.0-beta.7",
49
- "@tmagic/form": "1.1.0-beta.7",
50
- "@tmagic/schema": "1.1.0-beta.7",
51
- "@tmagic/stage": "1.1.0-beta.7",
52
- "@tmagic/utils": "1.1.0-beta.7",
47
+ "@element-plus/icons-vue": "^2.0.9",
48
+ "@tmagic/core": "1.1.0",
49
+ "@tmagic/form": "1.1.0",
50
+ "@tmagic/schema": "1.1.0",
51
+ "@tmagic/stage": "1.1.0",
52
+ "@tmagic/utils": "1.1.0",
53
53
  "buffer": "^6.0.3",
54
54
  "color": "^3.1.3",
55
55
  "element-plus": "^2.2.6",
@@ -57,14 +57,14 @@
57
57
  "gesto": "^1.7.0",
58
58
  "keycon": "^1.1.2",
59
59
  "lodash-es": "^4.17.21",
60
- "monaco-editor": "^0.32.1",
60
+ "monaco-editor": "^0.34.0",
61
61
  "serialize-javascript": "^6.0.0",
62
62
  "vue": "^3.2.37"
63
63
  },
64
64
  "peerDependencies": {
65
- "@tmagic/form": "1.1.0-beta.7",
65
+ "@tmagic/form": "1.1.0",
66
66
  "element-plus": "^2.2.6",
67
- "monaco-editor": "^0.32.1",
67
+ "monaco-editor": "^0.34.0",
68
68
  "vue": "^3.2.37"
69
69
  },
70
70
  "devDependencies": {
package/src/Editor.vue CHANGED
@@ -21,6 +21,7 @@
21
21
  <template #workspace>
22
22
  <slot name="workspace" :editorService="editorService">
23
23
  <workspace>
24
+ <template #stage><slot name="stage"></slot></template>
24
25
  <template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
25
26
  <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
26
27
  <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
@@ -30,7 +31,7 @@
30
31
 
31
32
  <template #props-panel>
32
33
  <slot name="props-panel">
33
- <props-panel ref="propsPanel" @mounted="(instance) => $emit('props-panel-mounted', instance)">
34
+ <props-panel @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
34
35
  <template #props-panel-header>
35
36
  <slot name="props-panel-header"></slot>
36
37
  </template>
@@ -49,7 +50,7 @@ import { EventOption } from '@tmagic/core';
49
50
  import type { FormConfig } from '@tmagic/form';
50
51
  import type { MApp, MNode } from '@tmagic/schema';
51
52
  import type StageCore from '@tmagic/stage';
52
- import { CONTAINER_HIGHLIGHT_CLASS, MoveableOptions } from '@tmagic/stage';
53
+ import { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
53
54
 
54
55
  import Framework from './layouts/Framework.vue';
55
56
  import NavMenu from './layouts/NavMenu.vue';
@@ -63,7 +64,7 @@ import historyService from './services/history';
63
64
  import propsService from './services/props';
64
65
  import storageService from './services/storage';
65
66
  import uiService from './services/ui';
66
- import type { ComponentGroup, MenuBarData, MenuItem, Services, SideBarData, StageRect } from './type';
67
+ import type { ComponentGroup, MenuBarData, MenuButton, MenuComponent, Services, SideBarData, StageRect } from './type';
67
68
 
68
69
  export default defineComponent({
69
70
  name: 'm-editor',
@@ -96,12 +97,12 @@ export default defineComponent({
96
97
  },
97
98
 
98
99
  layerContentMenu: {
99
- type: Array as PropType<MenuItem[]>,
100
+ type: Array as PropType<(MenuButton | MenuComponent)[]>,
100
101
  default: () => [],
101
102
  },
102
103
 
103
104
  stageContentMenu: {
104
- type: Array as PropType<MenuItem[]>,
105
+ type: Array as PropType<(MenuButton | MenuComponent)[]>,
105
106
  default: () => [],
106
107
  },
107
108
 
@@ -170,6 +171,11 @@ export default defineComponent({
170
171
  default: 800,
171
172
  },
172
173
 
174
+ containerHighlightType: {
175
+ type: String as PropType<ContainerHighlightType>,
176
+ default: ContainerHighlightType.DEFAULT,
177
+ },
178
+
173
179
  stageRect: {
174
180
  type: [String, Object] as PropType<StageRect>,
175
181
  },
@@ -261,7 +267,16 @@ export default defineComponent({
261
267
  },
262
268
  );
263
269
 
264
- onUnmounted(() => editorService.destroy());
270
+ uiService.initColumnWidth();
271
+
272
+ onUnmounted(() => {
273
+ editorService.destroy();
274
+ historyService.destroy();
275
+ propsService.destroy();
276
+ uiService.destroy();
277
+ componentListService.destroy();
278
+ storageService.destroy();
279
+ });
265
280
 
266
281
  const services: Services = {
267
282
  componentListService,
@@ -289,6 +304,7 @@ export default defineComponent({
289
304
  isContainer: props.isContainer,
290
305
  containerHighlightClassName: props.containerHighlightClassName,
291
306
  containerHighlightDuration: props.containerHighlightDuration,
307
+ containerHighlightType: props.containerHighlightType,
292
308
  }),
293
309
  );
294
310
 
@@ -25,13 +25,13 @@
25
25
  <script lang="ts" setup>
26
26
  import { nextTick, onMounted, onUnmounted, ref } from 'vue';
27
27
 
28
- import { MenuButton, MenuItem } from '../type';
28
+ import { MenuButton, MenuComponent } from '../type';
29
29
 
30
30
  import ToolButton from './ToolButton.vue';
31
31
 
32
32
  const props = withDefaults(
33
33
  defineProps<{
34
- menuData?: MenuItem[];
34
+ menuData?: (MenuButton | MenuComponent)[];
35
35
  isSubMenu?: boolean;
36
36
  }>(),
37
37
  {
@@ -45,7 +45,7 @@ const emit = defineEmits(['hide', 'show']);
45
45
  const menu = ref<HTMLDivElement>();
46
46
  const subMenu = ref<any>();
47
47
  const visible = ref(false);
48
- const subMenuData = ref<MenuItem[]>([]);
48
+ const subMenuData = ref<(MenuButton | MenuComponent)[]>([]);
49
49
  const menuStyle = ref({
50
50
  left: '0',
51
51
  top: '0',
@@ -94,7 +94,7 @@ const show = (e: MouseEvent) => {
94
94
  }, 300);
95
95
  };
96
96
 
97
- const showSubMenu = (item: MenuItem) => {
97
+ const showSubMenu = (item: MenuButton | MenuComponent) => {
98
98
  const menuItem = item as MenuButton;
99
99
  if (typeof item !== 'object' || !menuItem.items?.length) {
100
100
  return;
@@ -1,29 +1,15 @@
1
1
  <template>
2
- <el-icon v-if="!icon"><edit></edit></el-icon>
3
- <img v-else-if="typeof icon === 'string' && icon.startsWith('http')" :src="icon" />
2
+ <el-icon v-if="!icon"><Edit></Edit></el-icon>
3
+ <el-icon v-else-if="typeof icon === 'string' && icon.startsWith('http')"><img :src="icon" /></el-icon>
4
4
  <i v-else-if="typeof icon === 'string'" :class="icon"></i>
5
5
  <el-icon v-else><component :is="toRaw(icon)"></component></el-icon>
6
6
  </template>
7
7
 
8
- <script lang="ts">
9
- import { Component, defineComponent, PropType, toRaw } from 'vue';
8
+ <script lang="ts" setup>
9
+ import { toRaw } from 'vue';
10
10
  import { Edit } from '@element-plus/icons-vue';
11
11
 
12
- export default defineComponent({
13
- name: 'm-icon',
14
-
15
- components: { Edit },
16
-
17
- props: {
18
- icon: {
19
- type: [String, Object] as PropType<string | Component>,
20
- },
21
- },
22
-
23
- setup() {
24
- return {
25
- toRaw,
26
- };
27
- },
28
- });
12
+ defineProps<{
13
+ icon?: any;
14
+ }>();
29
15
  </script>
@@ -0,0 +1,147 @@
1
+ <template>
2
+ <div ref="bar" class="m-editor-scroll-bar" :class="isHorizontal ? 'horizontal' : 'vertical'">
3
+ <div ref="thumb" class="m-editor-scroll-bar-thumb" :style="thumbStyle"></div>
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ import { computed, onMounted, onUnmounted, ref } from 'vue';
9
+ import Gesto from 'gesto';
10
+
11
+ const props = defineProps<{
12
+ size: number;
13
+ scrollSize: number;
14
+ isHorizontal?: boolean;
15
+ pos: number;
16
+ }>();
17
+
18
+ const emit = defineEmits(['scroll']);
19
+
20
+ const bar = ref<HTMLDivElement>();
21
+ const thumb = ref<HTMLDivElement>();
22
+
23
+ const thumbSize = computed(() => props.size * (props.size / props.scrollSize));
24
+ const thumbPos = computed(() => (props.pos / props.scrollSize) * props.size);
25
+
26
+ const thumbStyle = computed(() => ({
27
+ [props.isHorizontal ? 'width' : 'height']: `${thumbSize.value}px`,
28
+ transform: `translate${props.isHorizontal ? 'X' : 'Y'}(${thumbPos.value}px)`,
29
+ }));
30
+
31
+ let gesto: Gesto;
32
+
33
+ onMounted(() => {
34
+ if (!thumb.value) return;
35
+ const thumbEl = thumb.value;
36
+ gesto = new Gesto(thumbEl, {
37
+ container: window,
38
+ });
39
+
40
+ gesto
41
+ .on('dragStart', (e) => {
42
+ e.inputEvent.stopPropagation();
43
+ e.inputEvent.preventDefault();
44
+ })
45
+ .on('drag', (e) => {
46
+ scrollBy(getDelta(e));
47
+ });
48
+
49
+ bar.value?.addEventListener('wheel', wheelHandler, false);
50
+ });
51
+
52
+ onUnmounted(() => {
53
+ if (gesto) gesto.off();
54
+ bar.value?.removeEventListener('wheel', wheelHandler, false);
55
+ });
56
+
57
+ const wheelHandler = (e: WheelEvent) => {
58
+ const delta = props.isHorizontal ? e.deltaX : e.deltaY;
59
+ if (delta) {
60
+ e.preventDefault();
61
+ }
62
+ scrollBy(delta);
63
+ };
64
+
65
+ const getDelta = (e: any) => {
66
+ const ratio = (props.isHorizontal ? e.deltaX : e.deltaY) / props.size;
67
+ return props.scrollSize * ratio;
68
+ };
69
+
70
+ const scrollBy = (delta: number) => {
71
+ if (delta < 0) {
72
+ if (props.pos <= 0) {
73
+ emit('scroll', 0);
74
+ } else {
75
+ emit('scroll', -Math.min(-delta, props.pos));
76
+ }
77
+ } else {
78
+ const leftPos = props.size - (thumbSize.value + thumbPos.value);
79
+ if (leftPos <= 0) {
80
+ emit('scroll', 0);
81
+ } else {
82
+ emit('scroll', Math.min(delta, leftPos));
83
+ }
84
+ }
85
+ };
86
+ </script>
87
+
88
+ <style lang="scss">
89
+ .m-editor-scroll-bar {
90
+ position: absolute;
91
+ background-color: transparent;
92
+ opacity: 0.3;
93
+ transition: background-color 0.2s linear, opacity 0.2s linear;
94
+
95
+ .m-editor-scroll-bar-thumb {
96
+ background-color: #aaa;
97
+ border-radius: 6px;
98
+ position: absolute;
99
+ }
100
+
101
+ &.horizontal {
102
+ width: 100%;
103
+ height: 15px;
104
+ bottom: 0;
105
+
106
+ .m-editor-scroll-bar-thumb {
107
+ height: 6px;
108
+ transition: background-color 0.2s linear, height 0.2s ease-in-out;
109
+ bottom: 2px;
110
+ }
111
+ }
112
+
113
+ &.vertical {
114
+ height: 100%;
115
+ width: 15px;
116
+ right: 5px;
117
+
118
+ .m-editor-scroll-bar-thumb {
119
+ width: 6px;
120
+ transition: background-color 0.2s linear, width 0.2s ease-in-out;
121
+ right: 2px;
122
+ }
123
+ }
124
+
125
+ &:hover,
126
+ &:focus {
127
+ background-color: #eee;
128
+ opacity: 0.9;
129
+
130
+ .m-editor-scroll-bar-thumb {
131
+ background-color: #999;
132
+ }
133
+
134
+ &.horizontal {
135
+ .m-editor-scroll-bar-thumb {
136
+ height: 11px;
137
+ }
138
+ }
139
+
140
+ &.vertical {
141
+ .m-editor-scroll-bar-thumb {
142
+ width: 11px;
143
+ }
144
+ }
145
+ }
146
+ }
147
+ </style>
@@ -3,64 +3,109 @@
3
3
  <div ref="el" :style="style">
4
4
  <slot></slot>
5
5
  </div>
6
+
7
+ <ScrollBar
8
+ v-if="scrollHeight > wrapHeight"
9
+ :scroll-size="scrollHeight"
10
+ :size="wrapHeight"
11
+ :pos="vOffset"
12
+ @scroll="vScrollHandler"
13
+ ></ScrollBar>
14
+ <ScrollBar
15
+ v-if="scrollWidth > wrapWidth"
16
+ :is-horizontal="true"
17
+ :scroll-size="scrollWidth"
18
+ :pos="hOffset"
19
+ :size="wrapWidth"
20
+ @scroll="hScrollHandler"
21
+ ></ScrollBar>
6
22
  </div>
7
23
  </template>
8
24
 
9
- <script lang="ts">
10
- import { computed, defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
25
+ <script lang="ts" setup>
26
+ import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
11
27
 
28
+ import { ScrollViewerEvent } from '../type';
12
29
  import { ScrollViewer } from '../utils/scroll-viewer';
13
30
 
14
- export default defineComponent({
15
- name: 'm-editor-scroll-viewer',
31
+ import ScrollBar from './ScrollBar.vue';
16
32
 
17
- props: {
18
- width: Number,
19
- height: Number,
20
- zoom: {
21
- type: Number,
22
- default: 1,
23
- },
33
+ const props = withDefaults(
34
+ defineProps<{
35
+ width?: number;
36
+ height?: number;
37
+ wrapWidth?: number;
38
+ wrapHeight?: number;
39
+ zoom?: number;
40
+ }>(),
41
+ {
42
+ width: 0,
43
+ height: 0,
44
+ wrapWidth: 0,
45
+ wrapHeight: 0,
46
+ zoom: 1,
24
47
  },
48
+ );
25
49
 
26
- setup(props) {
27
- const container = ref<HTMLDivElement>();
28
- const el = ref<HTMLDivElement>();
29
- let scrollViewer: ScrollViewer;
30
-
31
- onMounted(() => {
32
- if (!container.value || !el.value) return;
33
- scrollViewer = new ScrollViewer({
34
- container: container.value,
35
- target: el.value,
36
- zoom: props.zoom,
37
- });
38
- });
39
-
40
- onUnmounted(() => {
41
- scrollViewer.destroy();
42
- });
43
-
44
- watch(
45
- () => props.zoom,
46
- () => {
47
- scrollViewer.setZoom(props.zoom);
48
- },
49
- );
50
-
51
- return {
52
- container,
53
- el,
54
-
55
- style: computed(
56
- () => `
50
+ const container = ref<HTMLDivElement>();
51
+ const el = ref<HTMLDivElement>();
52
+ const style = computed(
53
+ () => `
57
54
  width: ${props.width}px;
58
55
  height: ${props.height}px;
59
56
  position: absolute;
60
57
  margin-top: 30px;
61
58
  `,
62
- ),
63
- };
59
+ );
60
+
61
+ const scrollWidth = ref(0);
62
+ const scrollHeight = ref(0);
63
+
64
+ let scrollViewer: ScrollViewer;
65
+
66
+ onMounted(() => {
67
+ if (!container.value || !el.value) return;
68
+ scrollViewer = new ScrollViewer({
69
+ container: container.value,
70
+ target: el.value,
71
+ zoom: props.zoom,
72
+ });
73
+
74
+ scrollViewer.on('scroll', (data: ScrollViewerEvent) => {
75
+ hOffset.value = data.scrollLeft;
76
+ vOffset.value = data.scrollTop;
77
+ scrollWidth.value = data.scrollWidth;
78
+ scrollHeight.value = data.scrollHeight;
79
+ });
80
+ });
81
+
82
+ onUnmounted(() => {
83
+ scrollViewer.destroy();
84
+ });
85
+
86
+ watch(
87
+ () => props.zoom,
88
+ () => {
89
+ scrollViewer.setZoom(props.zoom);
64
90
  },
91
+ );
92
+
93
+ const vOffset = ref(0);
94
+ const vScrollHandler = (delta: number) => {
95
+ vOffset.value += delta;
96
+ scrollViewer.scrollTo({
97
+ top: vOffset.value,
98
+ });
99
+ };
100
+ const hOffset = ref(0);
101
+ const hScrollHandler = (delta: number) => {
102
+ hOffset.value += delta;
103
+ scrollViewer.scrollTo({
104
+ left: hOffset.value,
105
+ });
106
+ };
107
+
108
+ defineExpose({
109
+ container,
65
110
  });
66
111
  </script>