@tmagic/editor 1.1.0-beta.12 → 1.1.0-beta.13

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 (40) hide show
  1. package/dist/style.css +46 -0
  2. package/dist/tmagic-editor.mjs +781 -688
  3. package/dist/tmagic-editor.mjs.map +1 -1
  4. package/dist/tmagic-editor.umd.js +783 -686
  5. package/dist/tmagic-editor.umd.js.map +1 -1
  6. package/package.json +8 -8
  7. package/src/Editor.vue +3 -3
  8. package/src/components/ContentMenu.vue +4 -4
  9. package/src/components/Icon.vue +6 -20
  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/index.ts +2 -0
  14. package/src/layouts/NavMenu.vue +156 -23
  15. package/src/layouts/sidebar/LayerMenu.vue +3 -3
  16. package/src/layouts/workspace/Stage.vue +8 -90
  17. package/src/layouts/workspace/ViewerMenu.vue +3 -3
  18. package/src/layouts/workspace/Workspace.vue +131 -138
  19. package/src/services/ui.ts +16 -20
  20. package/src/theme/nav-menu.scss +6 -0
  21. package/src/type.ts +26 -10
  22. package/src/utils/index.ts +1 -0
  23. package/src/utils/scroll-viewer.ts +90 -158
  24. package/src/utils/stage.ts +91 -0
  25. package/types/Editor.vue.d.ts +7 -7
  26. package/types/components/ContentMenu.vue.d.ts +8 -8
  27. package/types/components/Icon.vue.d.ts +62 -12
  28. package/types/components/ScrollBar.vue.d.ts +83 -0
  29. package/types/components/ScrollViewer.vue.d.ts +131 -19
  30. package/types/components/ToolButton.vue.d.ts +56 -59
  31. package/types/index.d.ts +2 -0
  32. package/types/layouts/NavMenu.vue.d.ts +92 -23
  33. package/types/layouts/sidebar/LayerMenu.vue.d.ts +7 -7
  34. package/types/layouts/sidebar/LayerPanel.vue.d.ts +12 -12
  35. package/types/layouts/workspace/Workspace.vue.d.ts +54 -4
  36. package/types/services/ui.d.ts +1 -1
  37. package/types/type.d.ts +23 -10
  38. package/types/utils/index.d.ts +1 -0
  39. package/types/utils/scroll-viewer.d.ts +16 -18
  40. package/types/utils/stage.d.ts +3 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.0-beta.12",
2
+ "version": "1.1.0-beta.13",
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.12",
49
- "@tmagic/form": "1.1.0-beta.12",
50
- "@tmagic/schema": "1.1.0-beta.12",
51
- "@tmagic/stage": "1.1.0-beta.12",
52
- "@tmagic/utils": "1.1.0-beta.12",
47
+ "@element-plus/icons-vue": "^2.0.9",
48
+ "@tmagic/core": "1.1.0-beta.13",
49
+ "@tmagic/form": "1.1.0-beta.13",
50
+ "@tmagic/schema": "1.1.0-beta.13",
51
+ "@tmagic/stage": "1.1.0-beta.13",
52
+ "@tmagic/utils": "1.1.0-beta.13",
53
53
  "buffer": "^6.0.3",
54
54
  "color": "^3.1.3",
55
55
  "element-plus": "^2.2.6",
@@ -62,7 +62,7 @@
62
62
  "vue": "^3.2.37"
63
63
  },
64
64
  "peerDependencies": {
65
- "@tmagic/form": "1.1.0-beta.12",
65
+ "@tmagic/form": "1.1.0-beta.13",
66
66
  "element-plus": "^2.2.6",
67
67
  "monaco-editor": "^0.34.0",
68
68
  "vue": "^3.2.37"
package/src/Editor.vue CHANGED
@@ -64,7 +64,7 @@ import historyService from './services/history';
64
64
  import propsService from './services/props';
65
65
  import storageService from './services/storage';
66
66
  import uiService from './services/ui';
67
- import type { ComponentGroup, MenuBarData, MenuItem, Services, SideBarData, StageRect } from './type';
67
+ import type { ComponentGroup, MenuBarData, MenuButton, MenuComponent, Services, SideBarData, StageRect } from './type';
68
68
 
69
69
  export default defineComponent({
70
70
  name: 'm-editor',
@@ -97,12 +97,12 @@ export default defineComponent({
97
97
  },
98
98
 
99
99
  layerContentMenu: {
100
- type: Array as PropType<MenuItem[]>,
100
+ type: Array as PropType<(MenuButton | MenuComponent)[]>,
101
101
  default: () => [],
102
102
  },
103
103
 
104
104
  stageContentMenu: {
105
- type: Array as PropType<MenuItem[]>,
105
+ type: Array as PropType<(MenuButton | MenuComponent)[]>,
106
106
  default: () => [],
107
107
  },
108
108
 
@@ -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>
2
+ <el-icon v-if="!icon"><Edit></Edit></el-icon>
3
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>
@@ -2,169 +2,80 @@
2
2
  <div
3
3
  v-if="display"
4
4
  class="menu-item"
5
- :class="item.type"
6
- @click="clickHandler(item, $event)"
7
- @mousedown="mousedownHandler(item, $event)"
8
- @mouseup="mouseupHandler(item, $event)"
5
+ :class="`${data.type} ${data.className || ''}`"
6
+ @click="clickHandler(data, $event)"
7
+ @mousedown="mousedownHandler(data, $event)"
8
+ @mouseup="mouseupHandler(data, $event)"
9
9
  >
10
- <el-divider v-if="item.type === 'divider'" :direction="item.direction || 'vertical'"></el-divider>
11
- <div v-else-if="item.type === 'text'" class="menu-item-text">{{ item.text }}</div>
10
+ <el-divider v-if="data.type === 'divider'" :direction="data.direction || 'vertical'"></el-divider>
11
+ <div v-else-if="data.type === 'text'" class="menu-item-text">{{ data.text }}</div>
12
12
 
13
- <template v-else-if="item.type === 'zoom'">
14
- <tool-button
15
- :data="{ type: 'button', icon: ZoomOut, handler: zoomOutHandler, tooltip: '缩小' }"
16
- :event-type="eventType"
17
- ></tool-button>
18
- <span class="menu-item-text" style="margin: 0 5px">{{ parseInt(`${zoom * 100}`, 10) }}%</span>
19
- <tool-button
20
- :data="{ type: 'button', icon: ZoomIn, handler: zoomInHandler, tooltip: '放大' }"
21
- :event-type="eventType"
22
- ></tool-button>
23
- </template>
24
-
25
- <template v-else-if="item.type === 'button'">
26
- <el-tooltip v-if="item.tooltip" effect="dark" placement="bottom-start" :content="item.tooltip">
13
+ <template v-else-if="data.type === 'button'">
14
+ <el-tooltip v-if="data.tooltip" effect="dark" placement="bottom-start" :content="data.tooltip">
27
15
  <el-button size="small" text :disabled="disabled"
28
- ><m-icon v-if="item.icon" :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
16
+ ><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></el-button
29
17
  >
30
18
  </el-tooltip>
31
19
  <el-button v-else size="small" text :disabled="disabled"
32
- ><m-icon v-if="item.icon" :icon="item.icon"></m-icon><span>{{ item.text }}</span></el-button
20
+ ><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></el-button
33
21
  >
34
22
  </template>
35
23
 
36
- <el-dropdown v-else-if="item.type === 'dropdown'" trigger="click" :disabled="disabled" @command="dropdownHandler">
24
+ <el-dropdown v-else-if="data.type === 'dropdown'" trigger="click" :disabled="disabled" @command="dropdownHandler">
37
25
  <span class="el-dropdown-link menubar-menu-button">
38
- {{ item.text }}<el-icon class="el-icon--right"><arrow-down></arrow-down></el-icon>
26
+ {{ data.text }}<el-icon class="el-icon--right"><ArrowDown></ArrowDown></el-icon>
39
27
  </span>
40
28
  <template #dropdown>
41
- <el-dropdown-menu v-if="item.items && item.items.length">
42
- <el-dropdown-item v-for="(subItem, index) in item.items" :key="index" :command="{ item, subItem }">{{
29
+ <el-dropdown-menu v-if="data.items && data.items.length">
30
+ <el-dropdown-item v-for="(subItem, index) in data.items" :key="index" :command="{ data, subItem }">{{
43
31
  subItem.text
44
32
  }}</el-dropdown-item>
45
33
  </el-dropdown-menu>
46
34
  </template>
47
35
  </el-dropdown>
48
36
 
49
- <component v-else-if="item.type === 'component'" v-bind="item.props || {}" :is="item.component"></component>
37
+ <component v-else-if="data.type === 'component'" v-bind="data.props || {}" :is="data.component"></component>
50
38
  </div>
51
39
  </template>
52
40
 
53
41
  <script lang="ts" setup>
54
- import { computed, inject, markRaw, PropType } from 'vue';
55
- import { ArrowDown, Back, Delete, Grid, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
56
-
57
- import { NodeType } from '@tmagic/schema';
42
+ import { computed, inject } from 'vue';
43
+ import { ArrowDown } from '@element-plus/icons-vue';
58
44
 
59
45
  import MIcon from '../components/Icon.vue';
60
- import type { MenuButton, MenuComponent, MenuItem, Services } from '../type';
61
-
62
- const props = defineProps({
63
- data: {
64
- type: [Object, String] as PropType<MenuItem | string>,
65
- require: true,
66
- default: () => ({
46
+ import type { MenuButton, MenuComponent, Services } from '../type';
47
+
48
+ const props = withDefaults(
49
+ defineProps<{
50
+ data?: MenuButton | MenuComponent;
51
+ eventType?: 'mousedown' | 'mouseup' | 'click';
52
+ }>(),
53
+ {
54
+ data: () => ({
67
55
  type: 'text',
68
56
  display: false,
69
57
  }),
58
+ eventType: 'click',
70
59
  },
71
-
72
- eventType: {
73
- type: String as PropType<'mousedown' | 'mouseup' | 'click'>,
74
- default: 'click',
75
- },
76
- });
77
-
60
+ );
78
61
  const services = inject<Services>('services');
79
- const uiService = services?.uiService;
80
-
81
- const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
82
- const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides') ?? true);
83
- const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
84
62
 
85
- const zoomInHandler = () => uiService?.zoom(0.1);
86
- const zoomOutHandler = () => uiService?.zoom(-0.1);
87
-
88
- const item = computed((): MenuButton | MenuComponent => {
89
- if (typeof props.data !== 'string') {
90
- return props.data;
91
- }
92
- switch (props.data) {
93
- case '/':
94
- return {
95
- type: 'divider',
96
- };
97
- case 'zoom':
98
- return {
99
- type: 'zoom',
100
- };
101
- case 'delete':
102
- return {
103
- type: 'button',
104
- icon: markRaw(Delete),
105
- tooltip: '刪除',
106
- disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
107
- handler: () => services?.editorService.remove(services?.editorService.get('node')),
108
- };
109
- case 'undo':
110
- return {
111
- type: 'button',
112
- icon: markRaw(Back),
113
- tooltip: '后退',
114
- disabled: () => !services?.historyService.state.canUndo,
115
- handler: () => services?.editorService.undo(),
116
- };
117
- case 'redo':
118
- return {
119
- type: 'button',
120
- icon: markRaw(Right),
121
- tooltip: '前进',
122
- disabled: () => !services?.historyService.state.canRedo,
123
- handler: () => services?.editorService.redo(),
124
- };
125
- case 'zoom-in':
126
- return {
127
- type: 'button',
128
- icon: markRaw(ZoomIn),
129
- tooltip: '放大',
130
- handler: zoomInHandler,
131
- };
132
- case 'zoom-out':
133
- return {
134
- type: 'button',
135
- icon: markRaw(ZoomOut),
136
- tooltip: '縮小',
137
- handler: zoomOutHandler,
138
- };
139
- case 'rule':
140
- return {
141
- type: 'button',
142
- icon: markRaw(ScaleToOriginal),
143
- tooltip: showRule.value ? '隐藏标尺' : '显示标尺',
144
- handler: () => uiService?.set('showRule', !showRule.value),
145
- };
146
- case 'guides':
147
- return {
148
- type: 'button',
149
- icon: markRaw(Grid),
150
- tooltip: showGuides.value ? '隐藏参考线' : '显示参考线',
151
- handler: () => uiService?.set('showGuides', !showGuides.value),
152
- };
153
- default:
154
- return {
155
- type: 'text',
156
- text: props.data,
157
- };
63
+ const disabled = computed(() => {
64
+ if (typeof props.data === 'string') return false;
65
+ if (props.data.type === 'component') return false;
66
+ if (typeof props.data.disabled === 'function') {
67
+ return props.data.disabled(services);
158
68
  }
69
+ return props.data.disabled;
159
70
  });
160
71
 
161
- const disabled = computed(() => {
162
- if (typeof item.value === 'string') return false;
163
- if (item.value.type === 'component') return false;
164
- if (typeof item.value.disabled === 'function') {
165
- return item.value.disabled(services);
72
+ const display = computed(() => {
73
+ if (!props.data) return false;
74
+ if (typeof props.data === 'string') return true;
75
+ if (typeof props.data.display === 'function') {
76
+ return props.data.display(services);
166
77
  }
167
- return item.value.disabled;
78
+ return props.data.display ?? true;
168
79
  });
169
80
 
170
81
  const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
@@ -174,15 +85,6 @@ const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
174
85
  }
175
86
  };
176
87
 
177
- const display = computed(() => {
178
- if (!item.value) return false;
179
- if (typeof item.value === 'string') return true;
180
- if (typeof item.value.display === 'function') {
181
- return item.value.display(services);
182
- }
183
- return item.value.display ?? true;
184
- });
185
-
186
88
  const dropdownHandler = (command: any) => {
187
89
  if (command.item.handler) {
188
90
  command.item.handler(services);
package/src/index.ts CHANGED
@@ -44,6 +44,8 @@ export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPa
44
44
  export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
45
45
  export { default as PropsPanel } from './layouts/PropsPanel.vue';
46
46
  export { default as ToolButton } from './components/ToolButton.vue';
47
+ export { default as ContentMenu } from './components/ContentMenu.vue';
48
+ export { default as Icon } from './components/Icon.vue';
47
49
 
48
50
  const defaultInstallOpt: InstallOptions = {
49
51
  // @todo, 自定义图片上传方法等编辑器依赖的外部选项