@tmagic/editor 1.5.1 → 1.5.3

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 (61) hide show
  1. package/dist/{tmagic-editor.css → style.css} +366 -6
  2. package/dist/tmagic-editor.js +1422 -510
  3. package/dist/tmagic-editor.umd.cjs +1437 -524
  4. package/package.json +7 -7
  5. package/src/components/SplitView.vue +1 -1
  6. package/src/fields/DataSourceFieldSelect/Index.vue +6 -6
  7. package/src/fields/DisplayConds.vue +2 -1
  8. package/src/fields/StyleSetter/Index.vue +69 -0
  9. package/src/fields/StyleSetter/components/BackgroundPosition.vue +71 -0
  10. package/src/fields/StyleSetter/components/Border.vue +104 -0
  11. package/src/fields/StyleSetter/components/Box.vue +73 -0
  12. package/src/fields/StyleSetter/components/Position.vue +54 -0
  13. package/src/fields/StyleSetter/icons/background-position/LeftBottom.vue +7 -0
  14. package/src/fields/StyleSetter/icons/background-position/LeftCenter.vue +7 -0
  15. package/src/fields/StyleSetter/icons/background-position/LeftTop.vue +12 -0
  16. package/src/fields/StyleSetter/icons/background-position/index.ts +3 -0
  17. package/src/fields/StyleSetter/icons/background-repeat/NoRepeat.vue +8 -0
  18. package/src/fields/StyleSetter/icons/background-repeat/Repeat.vue +31 -0
  19. package/src/fields/StyleSetter/icons/background-repeat/RepeatX.vue +8 -0
  20. package/src/fields/StyleSetter/icons/background-repeat/RepeatY.vue +8 -0
  21. package/src/fields/StyleSetter/icons/background-repeat/index.ts +4 -0
  22. package/src/fields/StyleSetter/icons/display/Block.vue +7 -0
  23. package/src/fields/StyleSetter/icons/display/Flex.vue +7 -0
  24. package/src/fields/StyleSetter/icons/display/Inline.vue +7 -0
  25. package/src/fields/StyleSetter/icons/display/InlineBlock.vue +7 -0
  26. package/src/fields/StyleSetter/icons/display/None.vue +7 -0
  27. package/src/fields/StyleSetter/icons/display/index.ts +5 -0
  28. package/src/fields/StyleSetter/icons/flex-direction/Column.vue +7 -0
  29. package/src/fields/StyleSetter/icons/flex-direction/ColumnReverse.vue +7 -0
  30. package/src/fields/StyleSetter/icons/flex-direction/Row.vue +7 -0
  31. package/src/fields/StyleSetter/icons/flex-direction/RowReverse.vue +7 -0
  32. package/src/fields/StyleSetter/icons/flex-direction/index.ts +4 -0
  33. package/src/fields/StyleSetter/icons/justify-content/Center.vue +5 -0
  34. package/src/fields/StyleSetter/icons/justify-content/FlexEnd.vue +5 -0
  35. package/src/fields/StyleSetter/icons/justify-content/FlexStart.vue +5 -0
  36. package/src/fields/StyleSetter/icons/justify-content/SpaceAround.vue +7 -0
  37. package/src/fields/StyleSetter/icons/justify-content/SpaceBetween.vue +5 -0
  38. package/src/fields/StyleSetter/icons/justify-content/index.ts +5 -0
  39. package/src/fields/StyleSetter/icons/text-align/Center.vue +7 -0
  40. package/src/fields/StyleSetter/icons/text-align/Left.vue +7 -0
  41. package/src/fields/StyleSetter/icons/text-align/Right.vue +7 -0
  42. package/src/fields/StyleSetter/icons/text-align/index.ts +3 -0
  43. package/src/fields/StyleSetter/pro/Background.vue +78 -0
  44. package/src/fields/StyleSetter/pro/Border.vue +35 -0
  45. package/src/fields/StyleSetter/pro/Font.vue +90 -0
  46. package/src/fields/StyleSetter/pro/Layout.vue +164 -0
  47. package/src/fields/StyleSetter/pro/Position.vue +48 -0
  48. package/src/fields/StyleSetter/pro/index.ts +5 -0
  49. package/src/index.ts +3 -0
  50. package/src/layouts/props-panel/FormPanel.vue +1 -1
  51. package/src/layouts/props-panel/PropsPanel.vue +32 -2
  52. package/src/services/editor.ts +2 -2
  53. package/src/theme/props-panel.scss +13 -0
  54. package/src/theme/resizer.scss +2 -2
  55. package/src/theme/style-setter/background.scss +113 -0
  56. package/src/theme/style-setter/border.scss +53 -0
  57. package/src/theme/style-setter/index.scss +28 -0
  58. package/src/theme/style-setter/layout.scss +199 -0
  59. package/src/theme/theme.scss +1 -0
  60. package/src/utils/props.ts +52 -297
  61. package/types/index.d.ts +425 -110
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path
4
+ d="M704 128v768h320V128H704zM384 128v768h256V128h-256zM192 256l-192 256 192 256 0.032-192H320v-128H192V256z"
5
+ ></path>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,4 @@
1
+ export { default as FlexDirectionColumn } from './Column.vue';
2
+ export { default as FlexDirectionColumnReverse } from './ColumnReverse.vue';
3
+ export { default as FlexDirectionRow } from './Row.vue';
4
+ export { default as FlexDirectionRowReverse } from './RowReverse.vue';
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path d="M480 1024V0h64v1024h-64z m128-64V64h320v896H608zM96 960V64h320v896H96z"></path>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path d="M416 160H96v704h320V160z m384 0H480v704h320V160z m128-160h-64v1024h64V0z"></path>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path d="M608 160h320v704H608V160zM224 160h320v704H224V160zM96 0h64v1024H96V0z"></path>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path
4
+ d="M320 864H192v160H128v-160H0V160h128V0h64v160h128v704z m704 0h-128v160h-64v-160h-128V160h128V0h64v160h128v704z"
5
+ ></path>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path d="M64 1024H0V0h64v1024z m384-160H128V160h320v704z m448 0H576V160h320v704z m128 160h-64V0h64v1024z"></path>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ export { default as JustifyContentCenter } from './Center.vue';
2
+ export { default as JustifyContentFlexEnd } from './FlexEnd.vue';
3
+ export { default as JustifyContentFlexStart } from './FlexStart.vue';
4
+ export { default as JustifyContentSpaceAround } from './SpaceAround.vue';
5
+ export { default as JustifyContentSpaceBetween } from './SpaceBetween.vue';
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path
4
+ d="M128 810.666667h768v85.333333H128z m128-170.666667h512v85.333333H256z m-128-170.666667h768v85.333334H128z m0-341.333333h768v85.333333H128z m128 170.666667h512v85.333333H256z"
5
+ ></path>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path
4
+ d="M128 810.666667h768v85.333333H128z m0-170.666667h512v85.333333H128z m0-170.666667h768v85.333334H128z m0-341.333333h768v85.333333H128z m0 170.666667h512v85.333333H128z"
5
+ ></path>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
3
+ <path
4
+ d="M128 128h768v85.333333H128z m0 682.666667h768v85.333333H128z m213.333333-170.666667h554.666667v85.333333H341.333333z m-213.333333-170.666667h768v85.333334H128z m213.333333-170.666666h554.666667v85.333333H341.333333z"
5
+ ></path>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,3 @@
1
+ export { default as AlignLeft } from './Left.vue';
2
+ export { default as AlignCenter } from './Center.vue';
3
+ export { default as AlignRight } from './Right.vue';
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <MContainer :config="config" :model="values" @change="change"></MContainer>
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import { markRaw } from 'vue';
7
+
8
+ import { ContainerChangeEventData, MContainer } from '@tmagic/form';
9
+ import type { StyleSchema } from '@tmagic/schema';
10
+
11
+ import BackgroundPosition from '../components/BackgroundPosition.vue';
12
+ import { BackgroundNoRepeat, BackgroundRepeat, BackgroundRepeatX, BackgroundRepeatY } from '../icons/background-repeat';
13
+
14
+ defineProps<{ values: Partial<StyleSchema> }>();
15
+
16
+ const emit = defineEmits<{
17
+ change: [v: StyleSchema, eventData: ContainerChangeEventData];
18
+ }>();
19
+
20
+ const config = {
21
+ items: [
22
+ {
23
+ name: 'backgroundColor',
24
+ text: '背景色',
25
+ labelWidth: '68px',
26
+ type: 'data-source-field-select',
27
+ fieldConfig: {
28
+ type: 'colorPicker',
29
+ },
30
+ },
31
+ {
32
+ name: 'backgroundImage',
33
+ text: '背景图',
34
+ labelWidth: '68px',
35
+ type: 'data-source-field-select',
36
+ fieldConfig: {
37
+ type: 'img-upload',
38
+ },
39
+ },
40
+ {
41
+ name: 'backgroundSize',
42
+ text: '背景尺寸',
43
+ type: 'radioGroup',
44
+ childType: 'button',
45
+ labelWidth: '68px',
46
+ options: [
47
+ { value: 'auto', text: '默认', tooltip: '默认 auto' },
48
+ { value: 'contain', text: '等比填充', tooltip: '等比填充 contain' },
49
+ { value: 'cover', text: '等比覆盖', tooltip: '等比覆盖 cover' },
50
+ ],
51
+ },
52
+ {
53
+ name: 'backgroundRepeat',
54
+ text: '重复显示',
55
+ type: 'radioGroup',
56
+ childType: 'button',
57
+ labelWidth: '68px',
58
+ options: [
59
+ { value: 'repeat', icon: markRaw(BackgroundRepeat), tooltip: '垂直和水平方向重复 repeat' },
60
+ { value: 'repeat-x', icon: markRaw(BackgroundRepeatX), tooltip: '水平方向重复 repeat-x' },
61
+ { value: 'repeat-y', icon: markRaw(BackgroundRepeatY), tooltip: '垂直方向重复 repeat-y' },
62
+ { value: 'no-repeat', icon: markRaw(BackgroundNoRepeat), tooltip: '不重复 no-repeat' },
63
+ ],
64
+ },
65
+ {
66
+ name: 'backgroundPosition',
67
+ text: '背景定位',
68
+ type: 'component',
69
+ component: BackgroundPosition,
70
+ labelWidth: '68px',
71
+ },
72
+ ],
73
+ };
74
+
75
+ const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
76
+ emit('change', value, eventData);
77
+ };
78
+ </script>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <MContainer :config="config" :model="values" @change="change"></MContainer>
3
+ <Border :model="values" @change="change"></Border>
4
+ </template>
5
+
6
+ <script lang="ts" setup>
7
+ import { type ContainerChangeEventData, MContainer } from '@tmagic/form';
8
+ import type { StyleSchema } from '@tmagic/schema';
9
+
10
+ import Border from '../components/Border.vue';
11
+
12
+ defineProps<{ values: Partial<StyleSchema> }>();
13
+
14
+ const emit = defineEmits<{
15
+ change: [v: StyleSchema, eventData: ContainerChangeEventData];
16
+ }>();
17
+
18
+ const config = {
19
+ items: [
20
+ {
21
+ labelWidth: '68px',
22
+ name: 'borderRadius',
23
+ text: '圆角',
24
+ type: 'data-source-field-select',
25
+ fieldConfig: {
26
+ type: 'text',
27
+ },
28
+ },
29
+ ],
30
+ };
31
+
32
+ const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
33
+ emit('change', value, eventData);
34
+ };
35
+ </script>
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <MContainer :config="config" :model="values" @change="change"></MContainer>
3
+ </template>
4
+
5
+ <script lang="ts" setup>
6
+ import { markRaw } from 'vue';
7
+
8
+ import { ContainerChangeEventData, MContainer } from '@tmagic/form';
9
+ import type { StyleSchema } from '@tmagic/schema';
10
+
11
+ import { AlignCenter, AlignLeft, AlignRight } from '../icons/text-align';
12
+
13
+ defineProps<{ values: Partial<StyleSchema> }>();
14
+
15
+ const emit = defineEmits<{
16
+ change: [v: StyleSchema, eventData: ContainerChangeEventData];
17
+ }>();
18
+
19
+ const config = {
20
+ items: [
21
+ {
22
+ type: 'row',
23
+ items: [
24
+ {
25
+ labelWidth: '68px',
26
+ name: 'fontSize',
27
+ text: '字号',
28
+ type: 'data-source-field-select',
29
+ fieldConfig: {
30
+ type: 'text',
31
+ },
32
+ },
33
+ {
34
+ labelWidth: '68px',
35
+ name: 'lineHeight',
36
+ text: '行高',
37
+ type: 'data-source-field-select',
38
+ fieldConfig: {
39
+ type: 'text',
40
+ },
41
+ },
42
+ ],
43
+ },
44
+ {
45
+ name: 'fontWeight',
46
+ text: '字重',
47
+ labelWidth: '68px',
48
+ type: 'data-source-field-select',
49
+ fieldConfig: {
50
+ type: 'select',
51
+ options: ['normal', 'bold']
52
+ .concat(
53
+ Array(7)
54
+ .fill(1)
55
+ .map((x, i) => `${i + 1}00`),
56
+ )
57
+ .map((item) => ({
58
+ value: item,
59
+ text: item,
60
+ })),
61
+ },
62
+ },
63
+ {
64
+ labelWidth: '68px',
65
+ name: 'color',
66
+ text: '颜色',
67
+ type: 'data-source-field-select',
68
+ fieldConfig: {
69
+ type: 'colorPicker',
70
+ },
71
+ },
72
+ {
73
+ name: 'textAlign',
74
+ text: '对齐',
75
+ type: 'radioGroup',
76
+ childType: 'button',
77
+ labelWidth: '68px',
78
+ options: [
79
+ { value: 'left', icon: markRaw(AlignLeft), tooltip: '左对齐 row' },
80
+ { value: 'center', icon: markRaw(AlignCenter), tooltip: '居中对齐 center' },
81
+ { value: 'right', icon: markRaw(AlignRight), tooltip: '右对齐 right' },
82
+ ],
83
+ },
84
+ ],
85
+ };
86
+
87
+ const change = (value: StyleSchema, eventData: ContainerChangeEventData) => {
88
+ emit('change', value, eventData);
89
+ };
90
+ </script>
@@ -0,0 +1,164 @@
1
+ <template>
2
+ <MContainer :config="config" :model="values" @change="change"></MContainer>
3
+ <Box :model="values" @change="change"></Box>
4
+ </template>
5
+
6
+ <script lang="ts" setup>
7
+ import { markRaw } from 'vue';
8
+
9
+ import type { ContainerChangeEventData, FormState } from '@tmagic/form';
10
+ import { MContainer } from '@tmagic/form';
11
+ import type { StyleSchema } from '@tmagic/schema';
12
+
13
+ import Box from '../components/Box.vue';
14
+ import { DisplayBlock, DisplayFlex, DisplayInline, DisplayInlineBlock, DisplayNone } from '../icons/display';
15
+ import {
16
+ FlexDirectionColumn,
17
+ FlexDirectionColumnReverse,
18
+ FlexDirectionRow,
19
+ FlexDirectionRowReverse,
20
+ } from '../icons/flex-direction';
21
+ import {
22
+ JustifyContentCenter,
23
+ JustifyContentFlexEnd,
24
+ JustifyContentFlexStart,
25
+ JustifyContentSpaceAround,
26
+ JustifyContentSpaceBetween,
27
+ } from '../icons/justify-content';
28
+
29
+ defineProps<{
30
+ values: Partial<StyleSchema>;
31
+ }>();
32
+
33
+ const emit = defineEmits<{
34
+ change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
35
+ }>();
36
+
37
+ const config = {
38
+ items: [
39
+ {
40
+ name: 'display',
41
+ text: '模式',
42
+ type: 'radioGroup',
43
+ childType: 'button',
44
+ labelWidth: '68px',
45
+ options: [
46
+ { value: 'inline', icon: markRaw(DisplayInline), tooltip: '内联布局 inline' },
47
+ { value: 'flex', icon: markRaw(DisplayFlex), tooltip: '弹性布局 flex' },
48
+ { value: 'block', icon: markRaw(DisplayBlock), tooltip: '块级布局 block' },
49
+ { value: 'inline-block', icon: markRaw(DisplayInlineBlock), tooltip: '内联块布局 inline-block' },
50
+ { value: 'none', icon: markRaw(DisplayNone), tooltip: '隐藏 none' },
51
+ ],
52
+ },
53
+ {
54
+ name: 'flexDirection',
55
+ text: '主轴方向',
56
+ type: 'radioGroup',
57
+ childType: 'button',
58
+ labelWidth: '68px',
59
+ options: [
60
+ { value: 'row', icon: markRaw(FlexDirectionRow), tooltip: '水平方向 起点在左侧 row' },
61
+ { value: 'row-reverse', icon: markRaw(FlexDirectionRowReverse), tooltip: '水平方向 起点在右侧 row-reverse' },
62
+ { value: 'column', icon: markRaw(FlexDirectionColumn), tooltip: '垂直方向 起点在上沿 column' },
63
+ {
64
+ value: 'column-reverse',
65
+ icon: markRaw(FlexDirectionColumnReverse),
66
+ tooltip: '垂直方向 起点在下沿 column-reverse',
67
+ },
68
+ ],
69
+ display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
70
+ },
71
+ {
72
+ name: 'justifyContent',
73
+ text: '主轴对齐',
74
+ type: 'radioGroup',
75
+ childType: 'button',
76
+ labelWidth: '68px',
77
+ options: [
78
+ { value: 'flex-start', icon: markRaw(JustifyContentFlexStart), tooltip: '左对齐 flex-start' },
79
+ { value: 'flex-end', icon: markRaw(JustifyContentFlexEnd), tooltip: '右对齐 flex-end' },
80
+ { value: 'center', icon: markRaw(JustifyContentCenter), tooltip: '居中 center' },
81
+ { value: 'space-between', icon: markRaw(JustifyContentSpaceBetween), tooltip: '两端对齐 space-between' },
82
+ { value: 'space-around', icon: markRaw(JustifyContentSpaceAround), tooltip: '横向平分 space-around' },
83
+ ],
84
+ display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
85
+ },
86
+ {
87
+ name: 'alignItems',
88
+ text: '辅轴对齐',
89
+ type: 'radioGroup',
90
+ childType: 'button',
91
+ labelWidth: '68px',
92
+ options: [
93
+ { value: 'flex-start', icon: markRaw(JustifyContentFlexStart), tooltip: '左对齐 flex-start' },
94
+ { value: 'flex-end', icon: markRaw(JustifyContentFlexEnd), tooltip: '右对齐 flex-end' },
95
+ { value: 'center', icon: markRaw(JustifyContentCenter), tooltip: '居中 center' },
96
+ { value: 'space-between', icon: markRaw(JustifyContentSpaceBetween), tooltip: '两端对齐 space-between' },
97
+ { value: 'space-around', icon: markRaw(JustifyContentSpaceAround), tooltip: '横向平分 space-around' },
98
+ ],
99
+ display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
100
+ },
101
+ {
102
+ name: 'flexWrap',
103
+ text: '换行',
104
+ type: 'radioGroup',
105
+ childType: 'button',
106
+ labelWidth: '68px',
107
+ options: [
108
+ { value: 'nowrap', text: '不换行', tooltip: '不换行 nowrap' },
109
+ { value: 'wrap', text: '正换行', tooltip: '第一行在上方 wrap' },
110
+ { value: 'wrap-reverse', text: '逆换行', tooltip: '第一行在下方 wrap-reverse' },
111
+ ],
112
+ display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.display === 'flex',
113
+ },
114
+ {
115
+ type: 'row',
116
+ items: [
117
+ {
118
+ name: 'width',
119
+ text: '宽度',
120
+ labelWidth: '68px',
121
+ type: 'data-source-field-select',
122
+ fieldConfig: {
123
+ type: 'text',
124
+ },
125
+ },
126
+ {
127
+ name: 'height',
128
+ text: '宽度',
129
+ labelWidth: '68px',
130
+ type: 'data-source-field-select',
131
+ fieldConfig: {
132
+ type: 'text',
133
+ },
134
+ },
135
+ ],
136
+ },
137
+ {
138
+ type: 'data-source-field-select',
139
+ text: 'overflow',
140
+ name: 'overflow',
141
+ checkStrictly: false,
142
+ dataSourceFieldType: ['string'],
143
+ fieldConfig: {
144
+ type: 'select',
145
+ clearable: true,
146
+ allowCreate: true,
147
+ options: [
148
+ { text: 'visible', value: 'visible' },
149
+ { text: 'hidden', value: 'hidden' },
150
+ { text: 'clip', value: 'clip' },
151
+ { text: 'scroll', value: 'scroll' },
152
+ { text: 'auto', value: 'auto' },
153
+ { text: 'overlay', value: 'overlay' },
154
+ { text: 'initial', value: 'initial' },
155
+ ],
156
+ },
157
+ },
158
+ ],
159
+ };
160
+
161
+ const change = (value: string | StyleSchema, eventData: ContainerChangeEventData) => {
162
+ emit('change', value, eventData);
163
+ };
164
+ </script>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <MContainer :config="config" :model="values" @change="change"></MContainer>
3
+ <Position v-show="values['position'] !== 'static'" :model="values" @change="change"></Position>
4
+ </template>
5
+
6
+ <script lang="ts" setup>
7
+ import { ContainerChangeEventData, MContainer } from '@tmagic/form';
8
+ import type { StyleSchema } from '@tmagic/schema';
9
+
10
+ import Position from '../components/Position.vue';
11
+
12
+ defineProps<{ values: Partial<StyleSchema> }>();
13
+
14
+ const emit = defineEmits<{
15
+ change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
16
+ }>();
17
+
18
+ const config = {
19
+ items: [
20
+ {
21
+ name: 'position',
22
+ text: '定位',
23
+ labelWidth: '68px',
24
+ type: 'data-source-field-select',
25
+ fieldConfig: {
26
+ type: 'select',
27
+ options: ['static', 'relative', 'absolute', 'fixed', 'sticky'].map((item) => ({
28
+ value: item,
29
+ text: item,
30
+ })),
31
+ },
32
+ },
33
+ {
34
+ labelWidth: '68px',
35
+ name: 'zIndex',
36
+ text: 'zIndex',
37
+ type: 'data-source-field-select',
38
+ fieldConfig: {
39
+ type: 'text',
40
+ },
41
+ },
42
+ ],
43
+ };
44
+
45
+ const change = (value: string | StyleSchema, eventData: ContainerChangeEventData) => {
46
+ emit('change', value, eventData);
47
+ };
48
+ </script>
@@ -0,0 +1,5 @@
1
+ export { default as Background } from './Background.vue';
2
+ export { default as Font } from './Font.vue';
3
+ export { default as Layout } from './Layout.vue';
4
+ export { default as Position } from './Position.vue';
5
+ export { default as Border } from './Border.vue';
package/src/index.ts CHANGED
@@ -39,6 +39,7 @@ import DisplayConds from './fields/DisplayConds.vue';
39
39
  import EventSelect from './fields/EventSelect.vue';
40
40
  import KeyValue from './fields/KeyValue.vue';
41
41
  import PageFragmentSelect from './fields/PageFragmentSelect.vue';
42
+ import StyleSetter from './fields/StyleSetter/Index.vue';
42
43
  import uiSelect from './fields/UISelect.vue';
43
44
  import CodeEditor from './layouts/CodeEditor.vue';
44
45
  import { setEditorConfig } from './utils/config';
@@ -106,6 +107,7 @@ export { default as TreeNode } from './components/TreeNode.vue';
106
107
  export { default as PageFragmentSelect } from './fields/PageFragmentSelect.vue';
107
108
  export { default as DisplayConds } from './fields/DisplayConds.vue';
108
109
  export { default as CondOpSelect } from './fields/CondOpSelect.vue';
110
+ export { default as StyleSetter } from './fields/StyleSetter/Index.vue';
109
111
 
110
112
  const defaultInstallOpt: EditorInstallOptions = {
111
113
  // eslint-disable-next-line no-eval
@@ -143,5 +145,6 @@ export default {
143
145
  app.component('m-fields-page-fragment-select', PageFragmentSelect);
144
146
  app.component('m-fields-display-conds', DisplayConds);
145
147
  app.component('m-fields-cond-op-select', CondOpSelect);
148
+ app.component('m-form-style-setter', StyleSetter);
146
149
  },
147
150
  };
@@ -99,7 +99,7 @@ watchEffect(() => {
99
99
 
100
100
  const internalInstance = getCurrentInstance();
101
101
  onMounted(() => {
102
- emit('mounted', internalInstance);
102
+ emit('mounted', internalInstance?.proxy);
103
103
  });
104
104
 
105
105
  const submit = async (v: FormValue, eventData: ContainerChangeEventData) => {
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="m-editor-props-panel" v-show="nodes.length === 1">
2
+ <div ref="propsPanel" class="m-editor-props-panel" v-show="nodes.length === 1">
3
3
  <slot name="props-panel-header"></slot>
4
4
  <FormPanel
5
5
  ref="propertyFormPanel"
@@ -15,6 +15,8 @@
15
15
  @mounted="mountedHandler"
16
16
  ></FormPanel>
17
17
 
18
+ <Resizer v-if="showStylePanel" @change="widthChange"></Resizer>
19
+
18
20
  <FormPanel
19
21
  v-if="showStylePanel"
20
22
  class="m-editor-props-style-panel"
@@ -53,12 +55,14 @@
53
55
  <script lang="ts" setup>
54
56
  import { computed, inject, onBeforeUnmount, ref, useTemplateRef, watchEffect } from 'vue';
55
57
  import { Close, Sugar } from '@element-plus/icons-vue';
58
+ import type { OnDrag } from 'gesto';
56
59
 
57
60
  import type { MNode } from '@tmagic/core';
58
61
  import { TMagicButton } from '@tmagic/design';
59
62
  import type { ContainerChangeEventData, FormState, FormValue } from '@tmagic/form';
60
63
 
61
64
  import MIcon from '@editor/components/Icon.vue';
65
+ import Resizer from '@editor/components/Resizer.vue';
62
66
  import type { PropsPanelSlots, Services } from '@editor/type';
63
67
  import { styleTabConfig } from '@editor/utils';
64
68
 
@@ -120,7 +124,21 @@ const submit = async (v: MNode, eventData?: ContainerChangeEventData) => {
120
124
  if (!v.id) {
121
125
  v.id = values.value.id;
122
126
  }
123
- services?.editorService.update(v, { changeRecords: eventData?.changeRecords });
127
+
128
+ const newValue: MNode = {
129
+ ...v,
130
+ style: {},
131
+ };
132
+
133
+ if (v.style) {
134
+ Object.entries(v.style).forEach(([key, value]) => {
135
+ if (value !== '' && newValue.style) {
136
+ newValue.style[key] = value;
137
+ }
138
+ });
139
+ }
140
+
141
+ services?.editorService.update(newValue, { changeRecords: eventData?.changeRecords });
124
142
  } catch (e: any) {
125
143
  emit('submit-error', e);
126
144
  }
@@ -134,6 +152,18 @@ const mountedHandler = (e: InstanceType<typeof FormPanel>) => {
134
152
  emit('mounted', e);
135
153
  };
136
154
 
155
+ const propsPanelEl = useTemplateRef('propsPanel');
156
+ const widthChange = ({ deltaX }: OnDrag) => {
157
+ if (!propsPanelEl.value) {
158
+ return;
159
+ }
160
+
161
+ const width = globalThis.parseFloat(
162
+ getComputedStyle(propsPanelEl.value).getPropertyValue('--props-style-panel-width'),
163
+ );
164
+ propsPanelEl.value.style.setProperty('--props-style-panel-width', `${width - deltaX}px`);
165
+ };
166
+
137
167
  const { showStylePanel, showStylePanelHandler, closeStylePanelHandler } = useStylePanel(services);
138
168
 
139
169
  const propertyFormPanelRef = useTemplateRef<InstanceType<typeof FormPanel>>('propertyFormPanel');
@@ -527,8 +527,8 @@ class Editor extends BaseService {
527
527
 
528
528
  let newConfig = await this.toggleFixedPosition(toRaw(config), node, root);
529
529
 
530
- newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue, key) => {
531
- if (typeof srcValue === 'undefined' && Object.hasOwn(newConfig, key)) {
530
+ newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue, key, object: any, source: any) => {
531
+ if (typeof srcValue === 'undefined' && Object.hasOwn(source, key)) {
532
532
  return '';
533
533
  }
534
534
 
@@ -72,6 +72,11 @@
72
72
  align-items: center;
73
73
  border-bottom: 2px solid $border-color;
74
74
  }
75
+
76
+ .tmagic-design-form {
77
+ padding-right: 10px;
78
+ padding-left: 10px;
79
+ }
75
80
  }
76
81
 
77
82
  .m-editor-props-panel-src-icon {
@@ -95,6 +100,14 @@
95
100
  z-index: 10;
96
101
  }
97
102
 
103
+ .m-editor-resizer {
104
+ position: absolute;
105
+ display: block;
106
+ top: 0;
107
+ right: var(--props-style-panel-width);
108
+ z-index: 13;
109
+ }
110
+
98
111
  &.small {
99
112
  .el-form-item__label {
100
113
  font-size: 12px;
@@ -1,6 +1,6 @@
1
1
  .m-editor-resizer {
2
- border-left: 1px solid transparent;
3
- border-right: 1px solid transparent;
2
+ border-left: 2px solid transparent;
3
+ border-right: 2px solid transparent;
4
4
  width: 8px;
5
5
  margin: 0 -5px;
6
6
  height: 100%;