@tmagic/editor 1.1.0-beta.9 → 1.1.2

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 (70) hide show
  1. package/dist/style.css +53 -4
  2. package/dist/tmagic-editor.mjs +1134 -928
  3. package/dist/tmagic-editor.mjs.map +1 -1
  4. package/dist/tmagic-editor.umd.js +1138 -929
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/package.json +10 -10
  7. package/src/Editor.vue +28 -8
  8. package/src/components/ContentMenu.vue +4 -4
  9. package/src/components/Icon.vue +11 -23
  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 -2
  15. package/src/layouts/NavMenu.vue +156 -23
  16. package/src/layouts/PropsPanel.vue +49 -51
  17. package/src/layouts/sidebar/ComponentListPanel.vue +78 -90
  18. package/src/layouts/sidebar/LayerMenu.vue +3 -3
  19. package/src/layouts/sidebar/LayerPanel.vue +39 -8
  20. package/src/layouts/sidebar/Sidebar.vue +4 -0
  21. package/src/layouts/sidebar/TabPane.vue +12 -0
  22. package/src/layouts/workspace/PageBar.vue +2 -2
  23. package/src/layouts/workspace/PageBarScrollContainer.vue +13 -3
  24. package/src/layouts/workspace/Stage.vue +10 -92
  25. package/src/layouts/workspace/ViewerMenu.vue +3 -3
  26. package/src/layouts/workspace/Workspace.vue +133 -138
  27. package/src/services/componentList.ts +5 -0
  28. package/src/services/editor.ts +57 -20
  29. package/src/services/events.ts +8 -2
  30. package/src/services/props.ts +31 -52
  31. package/src/services/storage.ts +4 -0
  32. package/src/services/ui.ts +33 -30
  33. package/src/theme/component-list-panel.scss +0 -5
  34. package/src/theme/content-menu.scss +4 -0
  35. package/src/theme/icon.scss +6 -0
  36. package/src/theme/index.scss +1 -0
  37. package/src/theme/nav-menu.scss +6 -0
  38. package/src/type.ts +28 -10
  39. package/src/utils/index.ts +1 -0
  40. package/src/utils/operator.ts +3 -3
  41. package/src/utils/props.ts +0 -3
  42. package/src/utils/scroll-viewer.ts +90 -158
  43. package/src/utils/stage.ts +91 -0
  44. package/types/Editor.vue.d.ts +7 -7
  45. package/types/components/ContentMenu.vue.d.ts +8 -8
  46. package/types/components/Icon.vue.d.ts +62 -12
  47. package/types/components/ScrollBar.vue.d.ts +83 -0
  48. package/types/components/ScrollViewer.vue.d.ts +131 -19
  49. package/types/components/ToolButton.vue.d.ts +56 -59
  50. package/types/index.d.ts +2 -1
  51. package/types/layouts/NavMenu.vue.d.ts +92 -23
  52. package/types/layouts/PropsPanel.vue.d.ts +25 -208
  53. package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +50 -12
  54. package/types/layouts/sidebar/LayerMenu.vue.d.ts +7 -7
  55. package/types/layouts/sidebar/LayerPanel.vue.d.ts +17 -15
  56. package/types/layouts/workspace/Workspace.vue.d.ts +54 -4
  57. package/types/services/componentList.d.ts +1 -0
  58. package/types/services/editor.d.ts +1 -0
  59. package/types/services/events.d.ts +1 -0
  60. package/types/services/props.d.ts +41 -9
  61. package/types/services/storage.d.ts +1 -0
  62. package/types/services/ui.d.ts +4 -1
  63. package/types/type.d.ts +25 -10
  64. package/types/utils/index.d.ts +1 -0
  65. package/types/utils/operator.d.ts +1 -1
  66. package/types/utils/props.d.ts +0 -1
  67. package/types/utils/scroll-viewer.d.ts +16 -18
  68. package/types/utils/stage.d.ts +3 -0
  69. package/src/utils/polyfills.ts +0 -8
  70. package/types/utils/polyfills.d.ts +0 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0-beta.9",
2
+ "version": "1.1.2",
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.9",
49
- "@tmagic/form": "1.1.0-beta.9",
50
- "@tmagic/schema": "1.1.0-beta.9",
51
- "@tmagic/stage": "1.1.0-beta.9",
52
- "@tmagic/utils": "1.1.0-beta.9",
47
+ "@element-plus/icons-vue": "^2.0.9",
48
+ "@tmagic/core": "1.1.2",
49
+ "@tmagic/form": "1.1.2",
50
+ "@tmagic/schema": "1.1.2",
51
+ "@tmagic/stage": "1.1.2",
52
+ "@tmagic/utils": "1.1.2",
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.9",
65
+ "@tmagic/form": "1.1.2",
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
@@ -14,6 +14,10 @@
14
14
  <template #component-list-panel-header>
15
15
  <slot name="component-list-panel-header"></slot>
16
16
  </template>
17
+
18
+ <template #component-list-item="{ component }">
19
+ <slot name="component-list-item" :component="component"></slot>
20
+ </template>
17
21
  </sidebar>
18
22
  </slot>
19
23
  </template>
@@ -21,6 +25,7 @@
21
25
  <template #workspace>
22
26
  <slot name="workspace" :editorService="editorService">
23
27
  <workspace>
28
+ <template #stage><slot name="stage"></slot></template>
24
29
  <template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
25
30
  <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
26
31
  <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
@@ -30,7 +35,7 @@
30
35
 
31
36
  <template #props-panel>
32
37
  <slot name="props-panel">
33
- <props-panel ref="propsPanel" @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
38
+ <props-panel @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
34
39
  <template #props-panel-header>
35
40
  <slot name="props-panel-header"></slot>
36
41
  </template>
@@ -63,7 +68,7 @@ import historyService from './services/history';
63
68
  import propsService from './services/props';
64
69
  import storageService from './services/storage';
65
70
  import uiService from './services/ui';
66
- import type { ComponentGroup, MenuBarData, MenuItem, Services, SideBarData, StageRect } from './type';
71
+ import type { ComponentGroup, MenuBarData, MenuButton, MenuComponent, Services, SideBarData, StageRect } from './type';
67
72
 
68
73
  export default defineComponent({
69
74
  name: 'm-editor',
@@ -96,12 +101,12 @@ export default defineComponent({
96
101
  },
97
102
 
98
103
  layerContentMenu: {
99
- type: Array as PropType<MenuItem[]>,
104
+ type: Array as PropType<(MenuButton | MenuComponent)[]>,
100
105
  default: () => [],
101
106
  },
102
107
 
103
108
  stageContentMenu: {
104
- type: Array as PropType<MenuItem[]>,
109
+ type: Array as PropType<(MenuButton | MenuComponent)[]>,
105
110
  default: () => [],
106
111
  },
107
112
 
@@ -192,9 +197,15 @@ export default defineComponent({
192
197
  emits: ['props-panel-mounted', 'update:modelValue'],
193
198
 
194
199
  setup(props, { emit }) {
195
- editorService.on('root-change', () => {
196
- const node = editorService.get<MNode | null>('node') || props.defaultSelected;
197
- node && editorService.select(node);
200
+ editorService.on('root-change', (value) => {
201
+ const node = editorService.get<MNode | null>('node');
202
+ const nodeId = node?.id || props.defaultSelected;
203
+ if (nodeId && node !== value) {
204
+ editorService.select(nodeId);
205
+ } else {
206
+ editorService.set('nodes', [value]);
207
+ }
208
+
198
209
  emit('update:modelValue', toRaw(editorService.get('root')));
199
210
  });
200
211
 
@@ -266,7 +277,16 @@ export default defineComponent({
266
277
  },
267
278
  );
268
279
 
269
- onUnmounted(() => editorService.destroy());
280
+ uiService.initColumnWidth();
281
+
282
+ onUnmounted(() => {
283
+ editorService.destroy();
284
+ historyService.destroy();
285
+ propsService.destroy();
286
+ uiService.destroy();
287
+ componentListService.destroy();
288
+ storageService.destroy();
289
+ });
270
290
 
271
291
  const services: Services = {
272
292
  componentListService,
@@ -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,17 @@
1
1
  <template>
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
- <i v-else-if="typeof icon === 'string'" :class="icon"></i>
5
- <el-icon v-else><component :is="toRaw(icon)"></component></el-icon>
2
+ <el-icon v-if="!icon" class="magic-editor-icon"><Edit></Edit></el-icon>
3
+ <el-icon v-else-if="typeof icon === 'string' && icon.startsWith('http')" class="magic-editor-icon"
4
+ ><img :src="icon"
5
+ /></el-icon>
6
+ <i v-else-if="typeof icon === 'string'" class="magic-editor-icon" :class="icon"></i>
7
+ <el-icon v-else class="magic-editor-icon"><component :is="toRaw(icon)"></component></el-icon>
6
8
  </template>
7
9
 
8
- <script lang="ts">
9
- import { Component, defineComponent, PropType, toRaw } from 'vue';
10
+ <script lang="ts" setup>
11
+ import { toRaw } from 'vue';
10
12
  import { Edit } from '@element-plus/icons-vue';
11
13
 
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
- });
14
+ defineProps<{
15
+ icon?: any;
16
+ }>();
29
17
  </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>