@tmagic/editor 1.1.0-beta.6 → 1.1.0-beta.9

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.1.0-beta.6",
2
+ "version": "1.1.0-beta.9",
3
3
  "name": "@tmagic/editor",
4
4
  "sideEffects": [
5
5
  "dist/*",
@@ -45,11 +45,11 @@
45
45
  "dependencies": {
46
46
  "@babel/core": "^7.18.0",
47
47
  "@element-plus/icons-vue": "^2.0.6",
48
- "@tmagic/core": "1.1.0-beta.6",
49
- "@tmagic/form": "1.1.0-beta.6",
50
- "@tmagic/schema": "1.1.0-beta.6",
51
- "@tmagic/stage": "1.1.0-beta.6",
52
- "@tmagic/utils": "1.1.0-beta.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",
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.6",
65
+ "@tmagic/form": "1.1.0-beta.9",
66
66
  "element-plus": "^2.2.6",
67
67
  "monaco-editor": "^0.32.1",
68
68
  "vue": "^3.2.37"
package/src/Editor.vue CHANGED
@@ -30,7 +30,7 @@
30
30
 
31
31
  <template #props-panel>
32
32
  <slot name="props-panel">
33
- <props-panel ref="propsPanel" @mounted="(instance) => $emit('props-panel-mounted', instance)">
33
+ <props-panel ref="propsPanel" @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
34
34
  <template #props-panel-header>
35
35
  <slot name="props-panel-header"></slot>
36
36
  </template>
@@ -49,7 +49,7 @@ import { EventOption } from '@tmagic/core';
49
49
  import type { FormConfig } from '@tmagic/form';
50
50
  import type { MApp, MNode } from '@tmagic/schema';
51
51
  import type StageCore from '@tmagic/stage';
52
- import { CONTAINER_HIGHLIGHT_CLASS, MoveableOptions } from '@tmagic/stage';
52
+ import { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
53
53
 
54
54
  import Framework from './layouts/Framework.vue';
55
55
  import NavMenu from './layouts/NavMenu.vue';
@@ -170,6 +170,11 @@ export default defineComponent({
170
170
  default: 800,
171
171
  },
172
172
 
173
+ containerHighlightType: {
174
+ type: String as PropType<ContainerHighlightType>,
175
+ default: ContainerHighlightType.DEFAULT,
176
+ },
177
+
173
178
  stageRect: {
174
179
  type: [String, Object] as PropType<StageRect>,
175
180
  },
@@ -289,6 +294,7 @@ export default defineComponent({
289
294
  isContainer: props.isContainer,
290
295
  containerHighlightClassName: props.containerHighlightClassName,
291
296
  containerHighlightDuration: props.containerHighlightDuration,
297
+ containerHighlightType: props.containerHighlightType,
292
298
  }),
293
299
  );
294
300
 
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <el-icon v-if="!icon"><edit></edit></el-icon>
3
- <img v-else-if="typeof icon === 'string' && icon.startsWith('http')" :src="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>
@@ -21,7 +21,6 @@ import { FormState } from '@tmagic/form';
21
21
  import { Services } from '../type';
22
22
 
23
23
  const props = defineProps<{
24
- labelWidth: string;
25
24
  config: any;
26
25
  model: any;
27
26
  prop: string;
package/src/index.ts CHANGED
@@ -58,7 +58,7 @@ export default {
58
58
  setConfig(option);
59
59
 
60
60
  app.component(Editor.name, Editor);
61
- app.component(uiSelect.name, uiSelect);
61
+ app.component('m-fields-ui-select', uiSelect);
62
62
  app.component(CodeLink.name, CodeLink);
63
63
  app.component(Code.name, Code);
64
64
  app.component(CodeEditor.name, CodeEditor);
@@ -1,191 +1,73 @@
1
1
  <template>
2
- <div class="m-editor-page-bar" ref="pageBar">
3
- <div id="m-editor-page-bar-add-icon" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="addPage">
4
- <el-icon><plus></plus></el-icon>
5
- </div>
2
+ <PageBarScrollContainer>
6
3
  <div
7
- v-if="scrollState.canScroll"
8
- class="m-editor-page-bar-item m-editor-page-bar-item-icon"
9
- @click="scrollState.scroll('left')"
4
+ v-for="item in (root && root.items) || []"
5
+ class="m-editor-page-bar-item"
6
+ :key="item.key"
7
+ :class="{ active: page?.id === item.id }"
8
+ @click="switchPage(item)"
10
9
  >
11
- <el-icon><arrow-left-bold></arrow-left-bold></el-icon>
12
- </div>
13
- <div
14
- v-if="root"
15
- class="m-editor-page-bar-items"
16
- ref="itemsContainer"
17
- :style="`width: ${scrollState.itemsContainerWidth}px`"
18
- >
19
- <div
20
- v-for="item in root.items"
21
- :key="item.key"
22
- class="m-editor-page-bar-item"
23
- :class="{ active: page?.id === item.id }"
24
- @click="switchPage(item)"
25
- >
26
- <div class="m-editor-page-bar-title">
27
- <slot name="page-bar-title" :page="item">
28
- <el-tooltip effect="dark" placement="top-start" :content="item.name">
29
- <span>{{ item.name }}</span>
30
- </el-tooltip>
10
+ <div class="m-editor-page-bar-title">
11
+ <slot name="page-bar-title" :page="item">
12
+ <el-tooltip effect="dark" placement="top-start" :content="item.name">
13
+ <span>{{ item.name }}</span>
14
+ </el-tooltip>
15
+ </slot>
16
+ </div>
17
+
18
+ <el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
19
+ <div>
20
+ <slot name="page-bar-popover" :page="item">
21
+ <tool-button
22
+ :data="{
23
+ type: 'button',
24
+ text: '复制',
25
+ icon: DocumentCopy,
26
+ handler: () => copy(item),
27
+ }"
28
+ ></tool-button>
29
+ <tool-button
30
+ :data="{
31
+ type: 'button',
32
+ text: '删除',
33
+ icon: Delete,
34
+ handler: () => remove(item),
35
+ }"
36
+ ></tool-button>
31
37
  </slot>
32
38
  </div>
33
-
34
- <el-popover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
35
- <div>
36
- <slot name="page-bar-popover" :page="item">
37
- <tool-button
38
- :data="{
39
- type: 'button',
40
- text: '复制',
41
- icon: DocumentCopy,
42
- handler: () => copy(item),
43
- }"
44
- ></tool-button>
45
- <tool-button
46
- :data="{
47
- type: 'button',
48
- text: '删除',
49
- icon: Delete,
50
- handler: () => remove(item),
51
- }"
52
- ></tool-button>
53
- </slot>
54
- </div>
55
- <template #reference>
56
- <el-icon class="m-editor-page-bar-menu-icon">
57
- <caret-bottom></caret-bottom>
58
- </el-icon>
59
- </template>
60
- </el-popover>
61
- </div>
39
+ <template #reference>
40
+ <el-icon class="m-editor-page-bar-menu-icon">
41
+ <caret-bottom></caret-bottom>
42
+ </el-icon>
43
+ </template>
44
+ </el-popover>
62
45
  </div>
63
- <div
64
- v-if="scrollState.canScroll"
65
- class="m-editor-page-bar-item m-editor-page-bar-item-icon"
66
- @click="scrollState.scroll('right')"
67
- >
68
- <el-icon><arrow-right-bold></arrow-right-bold></el-icon>
69
- </div>
70
- </div>
46
+ </PageBarScrollContainer>
71
47
  </template>
72
48
 
73
49
  <script lang="ts" setup>
74
- import { computed, ComputedRef, inject, onMounted, onUnmounted, ref, toRaw, watch } from 'vue';
75
- import { ArrowLeftBold, ArrowRightBold, CaretBottom, Delete, DocumentCopy, Plus } from '@element-plus/icons-vue';
50
+ import { computed, inject } from 'vue';
51
+ import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
76
52
 
77
53
  import type { MApp, MPage } from '@tmagic/schema';
78
- import { NodeType } from '@tmagic/schema';
79
54
 
80
55
  import ToolButton from '../../components/ToolButton.vue';
81
56
  import type { Services } from '../../type';
82
- import { generatePageNameByApp } from '../../utils/editor';
83
-
84
- const useScroll = (root: ComputedRef<MApp | undefined>) => {
85
- const pageBar = ref<HTMLDivElement>();
86
- const itemsContainer = ref<HTMLDivElement>();
87
-
88
- const pageBarWidth = ref(0);
89
- const canScroll = ref(false);
90
-
91
- const itemsContainerWidth = computed(() => pageBarWidth.value - 105);
92
-
93
- let translateLeft = 0;
94
- const resizeObserver = new ResizeObserver((entries) => {
95
- for (const { contentRect } of entries) {
96
- const { width } = contentRect;
97
- pageBarWidth.value = width || 0;
98
-
99
- setCanScroll();
100
- }
101
- });
102
57
 
103
- const setCanScroll = () => {
104
- if (itemsContainer.value) {
105
- canScroll.value = itemsContainer.value.scrollWidth > pageBarWidth.value - 105;
106
- }
107
- };
108
-
109
- const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
110
- if (!itemsContainer.value) return;
111
-
112
- const maxScrollLeft = itemsContainer.value.scrollWidth - itemsContainerWidth.value;
113
-
114
- if (type === 'left') {
115
- translateLeft += 100;
116
-
117
- if (translateLeft > 0) {
118
- translateLeft = 0;
119
- }
120
- } else if (type === 'right') {
121
- translateLeft -= 100;
122
-
123
- if (-translateLeft > maxScrollLeft) {
124
- translateLeft = -maxScrollLeft;
125
- }
126
- } else if (type === 'start') {
127
- translateLeft = 0;
128
- } else if (type === 'end') {
129
- translateLeft = -maxScrollLeft;
130
- }
131
-
132
- itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
133
- };
134
-
135
- onMounted(() => {
136
- pageBar.value && resizeObserver.observe(pageBar.value);
137
- });
138
-
139
- onUnmounted(() => {
140
- resizeObserver.disconnect();
141
- });
142
-
143
- watch(
144
- () => root.value?.items.length,
145
- (length = 0, preLength = 0) => {
146
- setTimeout(() => {
147
- setCanScroll();
148
- if (length < preLength) {
149
- scroll('start');
150
- } else {
151
- scroll('end');
152
- }
153
- });
154
- },
155
- );
156
-
157
- return {
158
- pageBar,
159
- itemsContainer,
160
- canScroll,
161
-
162
- itemsContainerWidth,
163
-
164
- scroll,
165
- };
166
- };
58
+ import PageBarScrollContainer from './PageBarScrollContainer.vue';
167
59
 
168
60
  const services = inject<Services>('services');
169
61
  const editorService = services?.editorService;
170
62
 
171
63
  const root = computed(() => editorService?.get<MApp>('root'));
172
64
 
173
- const scrollState = useScroll(root);
174
65
  const page = computed(() => editorService?.get('page'));
175
66
 
176
67
  const switchPage = (page: MPage) => {
177
68
  editorService?.select(page);
178
69
  };
179
70
 
180
- const addPage = () => {
181
- if (!editorService) return;
182
- const pageConfig = {
183
- type: NodeType.PAGE,
184
- name: generatePageNameByApp(toRaw(editorService.get('root'))),
185
- };
186
- editorService.add(pageConfig);
187
- };
188
-
189
71
  const copy = (node: MPage) => {
190
72
  node && editorService?.copy(node);
191
73
  editorService?.paste({
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <div class="m-editor-page-bar" ref="pageBar">
3
+ <div id="m-editor-page-bar-add-icon" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="addPage">
4
+ <el-icon><plus></plus></el-icon>
5
+ </div>
6
+ <div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('left')">
7
+ <el-icon><arrow-left-bold></arrow-left-bold></el-icon>
8
+ </div>
9
+ <div v-if="root" class="m-editor-page-bar-items" ref="itemsContainer" :style="`width: ${itemsContainerWidth}px`">
10
+ <slot></slot>
11
+ </div>
12
+ <div v-if="canScroll" class="m-editor-page-bar-item m-editor-page-bar-item-icon" @click="scroll('right')">
13
+ <el-icon><arrow-right-bold></arrow-right-bold></el-icon>
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { computed, inject, onMounted, onUnmounted, ref, toRaw, watch } from 'vue';
20
+ import { ArrowLeftBold, ArrowRightBold, Plus } from '@element-plus/icons-vue';
21
+
22
+ import { MApp, NodeType } from '@tmagic/schema';
23
+
24
+ import type { Services } from '../../type';
25
+ import { generatePageNameByApp } from '../../utils/editor';
26
+
27
+ const services = inject<Services>('services');
28
+ const editorService = services?.editorService;
29
+
30
+ const pageBar = ref<HTMLDivElement>();
31
+ const itemsContainer = ref<HTMLDivElement>();
32
+ const pageBarWidth = ref(0);
33
+ const canScroll = ref(false);
34
+
35
+ const itemsContainerWidth = computed(() => pageBarWidth.value - 105);
36
+
37
+ let translateLeft = 0;
38
+ const resizeObserver = new ResizeObserver((entries) => {
39
+ for (const { contentRect } of entries) {
40
+ const { width } = contentRect;
41
+ pageBarWidth.value = width || 0;
42
+
43
+ setCanScroll();
44
+ }
45
+ });
46
+
47
+ const setCanScroll = () => {
48
+ if (itemsContainer.value) {
49
+ canScroll.value = itemsContainer.value.scrollWidth > pageBarWidth.value - 105;
50
+ }
51
+ };
52
+
53
+ const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
54
+ if (!itemsContainer.value) return;
55
+
56
+ const maxScrollLeft = itemsContainer.value.scrollWidth - itemsContainerWidth.value;
57
+
58
+ if (type === 'left') {
59
+ translateLeft += 100;
60
+
61
+ if (translateLeft > 0) {
62
+ translateLeft = 0;
63
+ }
64
+ } else if (type === 'right') {
65
+ translateLeft -= 100;
66
+
67
+ if (-translateLeft > maxScrollLeft) {
68
+ translateLeft = -maxScrollLeft;
69
+ }
70
+ } else if (type === 'start') {
71
+ translateLeft = 0;
72
+ } else if (type === 'end') {
73
+ translateLeft = -maxScrollLeft;
74
+ }
75
+
76
+ itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
77
+ };
78
+
79
+ onMounted(() => {
80
+ pageBar.value && resizeObserver.observe(pageBar.value);
81
+ });
82
+
83
+ onUnmounted(() => {
84
+ resizeObserver.disconnect();
85
+ });
86
+
87
+ const root = computed(() => editorService?.get<MApp>('root'));
88
+
89
+ watch(
90
+ () => root.value?.items.length,
91
+ (length = 0, preLength = 0) => {
92
+ setTimeout(() => {
93
+ setCanScroll();
94
+ if (length < preLength) {
95
+ scroll('start');
96
+ } else {
97
+ scroll('end');
98
+ }
99
+ });
100
+ },
101
+ );
102
+
103
+ const addPage = () => {
104
+ if (!editorService) return;
105
+ const pageConfig = {
106
+ type: NodeType.PAGE,
107
+ name: generatePageNameByApp(toRaw(editorService.get('root'))),
108
+ };
109
+ editorService.add(pageConfig);
110
+ };
111
+ </script>
@@ -81,6 +81,7 @@ watchEffect(() => {
81
81
  isContainer: stageOptions.isContainer,
82
82
  containerHighlightClassName: stageOptions.containerHighlightClassName,
83
83
  containerHighlightDuration: stageOptions.containerHighlightDuration,
84
+ containerHighlightType: stageOptions.containerHighlightType,
84
85
  canSelect: (el, event, stop) => {
85
86
  const elCanSelect = stageOptions.canSelect(el);
86
87
  // 在组件联动过程中不能再往下选择,返回并触发 ui-select
@@ -118,10 +119,13 @@ watchEffect(() => {
118
119
 
119
120
  stage?.on('update', (ev: UpdateEventData) => {
120
121
  if (ev.parentEl) {
121
- services?.editorService.moveToContainer({ id: ev.el.id, style: ev.style }, ev.parentEl.id);
122
+ for (const data of ev.data) {
123
+ services?.editorService.moveToContainer({ id: data.el.id, style: data.style }, ev.parentEl.id);
124
+ }
122
125
  return;
123
126
  }
124
- services?.editorService.update({ id: ev.el.id, style: ev.style });
127
+
128
+ services?.editorService.update(ev.data.map((data) => ({ id: data.el.id, style: data.style })));
125
129
  });
126
130
 
127
131
  stage?.on('sort', (ev: SortEventData) => {
@@ -3,7 +3,7 @@
3
3
  </template>
4
4
 
5
5
  <script lang="ts" setup>
6
- import { computed, inject, markRaw, onMounted, reactive, ref, watch } from 'vue';
6
+ import { computed, inject, markRaw, reactive, ref, watch } from 'vue';
7
7
  import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons-vue';
8
8
 
9
9
  import { MNode, NodeType } from '@tmagic/schema';
@@ -34,10 +34,10 @@ const menuData = reactive<MenuItem[]>([
34
34
  {
35
35
  type: 'button',
36
36
  text: '水平居中',
37
- display: () => canCenter.value && !props.isMultiSelect,
37
+ display: () => canCenter.value,
38
38
  handler: () => {
39
- if (!node.value) return;
40
- editorService?.alignCenter(node.value);
39
+ if (!nodes.value) return;
40
+ editorService?.alignCenter(nodes.value);
41
41
  },
42
42
  },
43
43
  {
@@ -133,11 +133,6 @@ const menuData = reactive<MenuItem[]>([
133
133
  ...stageContentMenu,
134
134
  ]);
135
135
 
136
- onMounted(async () => {
137
- const data = await storageService.getItem(COPY_STORAGE_KEY);
138
- canPaste.value = data !== 'undefined' && !!data;
139
- });
140
-
141
136
  watch(
142
137
  parent,
143
138
  async () => {
@@ -152,8 +147,10 @@ watch(
152
147
  { immediate: true },
153
148
  );
154
149
 
155
- const show = (e: MouseEvent) => {
150
+ const show = async (e: MouseEvent) => {
156
151
  menu.value?.show(e);
152
+ const data = await storageService.getItem(COPY_STORAGE_KEY);
153
+ canPaste.value = data !== 'undefined' && !!data;
157
154
  };
158
155
 
159
156
  defineExpose({ show });
@@ -72,7 +72,7 @@ export default defineComponent({
72
72
  })
73
73
  .keydown([ctrl, 'v'], (e) => {
74
74
  e.inputEvent.preventDefault();
75
- nodes.value && services?.editorService.paste();
75
+ nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
76
76
  })
77
77
  .keydown([ctrl, 'x'], (e) => {
78
78
  e.inputEvent.preventDefault();