@tmagic/editor 1.8.0-beta.24 → 1.8.0-beta.26

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 (113) hide show
  1. package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +10 -16
  2. package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +4 -4
  3. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +5 -8
  4. package/dist/es/components/ViewForm.vue_vue_type_script_setup_true_lang.js +3 -5
  5. package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +3 -11
  6. package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +29 -124
  7. package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +5 -6
  8. package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +3 -2
  9. package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  10. package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +7 -6
  11. package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +6 -10
  12. package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +5 -7
  13. package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +1 -4
  14. package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +4 -6
  15. package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  16. package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +9 -137
  17. package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +51 -326
  18. package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +2 -4
  19. package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +3 -34
  20. package/dist/es/fields/StyleSetter/configs.js +663 -0
  21. package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +5 -108
  22. package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +3 -9
  23. package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +6 -103
  24. package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +5 -265
  25. package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +5 -85
  26. package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +3 -22
  27. package/dist/es/fields/configs/codeSelect.js +98 -0
  28. package/dist/es/fields/configs/displayConds.js +158 -0
  29. package/dist/es/fields/configs/eventSelect.js +225 -0
  30. package/dist/es/fields/configs/stickyAddButton.js +20 -0
  31. package/dist/es/fields/headless-validation.js +139 -0
  32. package/dist/es/headless.js +2 -0
  33. package/dist/es/hooks/use-compare-form.js +6 -23
  34. package/dist/es/hooks/use-form-context.js +19 -0
  35. package/dist/es/index.js +3 -2
  36. package/dist/es/initService.js +17 -1
  37. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +1 -7
  38. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +1 -11
  39. package/dist/es/layouts/history-list/useHistoryRevert.js +3 -11
  40. package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +10 -23
  41. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +3 -13
  42. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  43. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
  44. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  45. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
  46. package/dist/es/plugin.js +33 -32
  47. package/dist/es/style.css +120 -60
  48. package/dist/es/utils/data-source/index.js +2 -1
  49. package/dist/es/utils/props.js +1 -4
  50. package/dist/es/utils/type-match-rules.js +23 -22
  51. package/dist/style.css +120 -60
  52. package/dist/themes/magic-admin.css +132 -67
  53. package/dist/tmagic-editor-headless.umd.cjs +10867 -0
  54. package/dist/tmagic-editor.umd.cjs +2151 -2034
  55. package/package.json +12 -7
  56. package/src/Editor.vue +12 -16
  57. package/src/components/CodeParams.vue +10 -4
  58. package/src/components/CompareForm.vue +4 -5
  59. package/src/components/ViewForm.vue +2 -3
  60. package/src/editorProps.ts +1 -2
  61. package/src/fields/Code.vue +2 -10
  62. package/src/fields/CodeSelect.vue +20 -116
  63. package/src/fields/CodeSelectCol.vue +3 -5
  64. package/src/fields/CondOpSelect.vue +3 -2
  65. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +1 -1
  66. package/src/fields/DataSourceFieldSelect/Index.vue +7 -6
  67. package/src/fields/DataSourceFields.vue +0 -7
  68. package/src/fields/DataSourceMethodSelect.vue +2 -5
  69. package/src/fields/DataSourceMethods.vue +1 -6
  70. package/src/fields/DataSourceMocks.vue +1 -10
  71. package/src/fields/DataSourceSelect.vue +1 -1
  72. package/src/fields/DisplayConds.vue +17 -153
  73. package/src/fields/EventSelect.vue +28 -375
  74. package/src/fields/KeyValue.vue +3 -4
  75. package/src/fields/StyleSetter/components/Border.vue +4 -38
  76. package/src/fields/StyleSetter/configs.ts +690 -0
  77. package/src/fields/StyleSetter/pro/Background.vue +4 -104
  78. package/src/fields/StyleSetter/pro/Border.vue +3 -12
  79. package/src/fields/StyleSetter/pro/Font.vue +5 -124
  80. package/src/fields/StyleSetter/pro/Layout.vue +4 -219
  81. package/src/fields/StyleSetter/pro/Position.vue +6 -110
  82. package/src/fields/StyleSetter/pro/Transform.vue +4 -30
  83. package/src/fields/configs/codeSelect.ts +127 -0
  84. package/src/fields/configs/displayConds.ts +184 -0
  85. package/src/fields/configs/eventSelect.ts +309 -0
  86. package/src/fields/configs/stickyAddButton.ts +31 -0
  87. package/src/fields/headless-validation.ts +177 -0
  88. package/src/headless.ts +33 -0
  89. package/src/hooks/use-compare-form.ts +7 -25
  90. package/src/hooks/use-form-context.ts +40 -0
  91. package/src/index.ts +2 -0
  92. package/src/initService.ts +23 -1
  93. package/src/layouts/history-list/HistoryDiffDialog.vue +0 -10
  94. package/src/layouts/history-list/HistoryListPanel.vue +1 -13
  95. package/src/layouts/history-list/useHistoryRevert.ts +7 -13
  96. package/src/layouts/props-panel/FormPanel.vue +17 -28
  97. package/src/layouts/props-panel/PropsPanel.vue +1 -4
  98. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
  99. package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
  100. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
  101. package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
  102. package/src/plugin.ts +32 -33
  103. package/src/theme/code-block.scss +0 -37
  104. package/src/theme/display-conds.scss +4 -0
  105. package/src/theme/event.scss +22 -45
  106. package/src/theme/props-panel.scss +17 -3
  107. package/src/theme/themes/magic-admin/index.scss +12 -1
  108. package/src/type.ts +10 -29
  109. package/src/utils/data-source/index.ts +1 -0
  110. package/src/utils/props.ts +1 -4
  111. package/src/utils/type-match-rules.ts +37 -31
  112. package/types/headless.d.ts +18 -0
  113. package/types/index.d.ts +155 -180
@@ -13,7 +13,7 @@
13
13
  :init-values="values"
14
14
  :config="config"
15
15
  :type-match-valid="true"
16
- :extend-state="extendState"
16
+ :context="formContext"
17
17
  :validate-on-init="true"
18
18
  @change="submit"
19
19
  @error="errorHandler"
@@ -45,17 +45,18 @@
45
45
  </template>
46
46
 
47
47
  <script setup lang="ts">
48
- import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef, watchEffect } from 'vue';
48
+ import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
49
49
  import { Document as DocumentIcon } from '@element-plus/icons-vue';
50
50
 
51
51
  import { TMagicButton, tMagicMessage, TMagicScrollbar } from '@tmagic/design';
52
- import type { ContainerChangeEventData, FormConfig, FormState, FormValue } from '@tmagic/form';
52
+ import type { ContainerChangeEventData, FormConfig, FormValue } from '@tmagic/form';
53
53
  import { MForm, validateForm } from '@tmagic/form';
54
54
  import { filterXSS } from '@tmagic/utils';
55
55
 
56
56
  import MIcon from '@editor/components/Icon.vue';
57
57
  import { ENABLE_PROPS_FORM_VALIDATE } from '@editor/editorProps';
58
58
  import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
59
+ import { useEditorFormContext } from '@editor/hooks/use-form-context';
59
60
  import { useServices } from '@editor/hooks/use-services';
60
61
 
61
62
  import CodeEditor from '../CodeEditor.vue';
@@ -74,8 +75,7 @@ const props = defineProps<{
74
75
  disabledShowSrc?: boolean;
75
76
  labelWidth?: string;
76
77
  codeValueKey?: string;
77
- labelPosition?: string;
78
- extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
78
+ labelPosition?: 'top' | 'left' | 'right';
79
79
  }>();
80
80
 
81
81
  const emit = defineEmits<{
@@ -89,23 +89,17 @@ const emit = defineEmits<{
89
89
  const enablePropsFormValidate = inject(ENABLE_PROPS_FORM_VALIDATE, false);
90
90
 
91
91
  const services = useServices();
92
- const { editorService, uiService } = services;
92
+ const { uiService } = services;
93
93
 
94
94
  const codeOptions = inject('codeOptions', {});
95
95
 
96
96
  const showSrc = ref(false);
97
97
  const propsPanelSize = computed(() => uiService.get('propsPanelSize') || 'small');
98
98
  const { height: editorContentHeight } = useEditorContentHeight();
99
- const stage = computed(() => editorService.get('stage'));
100
99
 
101
- const configFormRef = useTemplateRef<InstanceType<typeof MForm>>('configForm');
100
+ const formContext = useEditorFormContext(() => services);
102
101
 
103
- watchEffect(() => {
104
- if (configFormRef.value) {
105
- configFormRef.value.formState.stage = stage.value;
106
- configFormRef.value.formState.services = services;
107
- }
108
- });
102
+ const configFormRef = useTemplateRef<InstanceType<typeof MForm>>('configForm');
109
103
 
110
104
  const internalInstance = getCurrentInstance();
111
105
  onMounted(() => {
@@ -158,23 +152,17 @@ const saveCode = async (values: any) => {
158
152
  return;
159
153
  }
160
154
 
161
- // 启用校验联动:源码编辑器保存的值未经过表单交互,这里另建一个独立的 MForm 实例对最新配置
162
- // 做一次静默校验(不复用、也不污染页面上正在展示的表单),并将校验结果(错误信息)随提交
155
+ // 启用校验联动:源码编辑器保存的值未经过表单交互,这里对最新配置做一次无渲染的静默校验
156
+ // (不挂载任何组件,也不影响页面上正在展示的表单),并将校验结果(错误信息)随提交
163
157
  // 一并抛给上层记录,使源码保存的错误状态与表单编辑保持一致。
158
+ //
159
+ // 配置里的 display / rules 回调会从 formState 上读 services,因此必须带上 context。
164
160
  try {
165
161
  const error = await validateForm({
166
162
  config: props.config,
167
163
  typeMatchValid: true,
168
164
  initValues: newValues,
169
- // 将当前组件实例的 provides(含 Editor 顶层的 services / codeOptions 等组件级 provide)
170
- // 合入 appContext,使临时 MForm 中的编辑器字段组件(DataSourceInput 等)能正常 inject
171
- appContext: internalInstance?.appContext ? { ...internalInstance?.appContext, provides: { services } } : null,
172
- extendState: (state) => {
173
- if (configFormRef.value?.formState) {
174
- return { ...(configFormRef.value?.formState || {}) };
175
- }
176
- return props.extendState?.(state) || {};
177
- },
165
+ context: formContext.value,
178
166
  });
179
167
 
180
168
  if (error) {
@@ -187,9 +175,10 @@ const saveCode = async (values: any) => {
187
175
 
188
176
  emit('submit', newValues, undefined, error ? new Error(error) : undefined);
189
177
  } catch (e: any) {
190
- console.log('validateForm error', e);
191
- // 静默校验本身出现异常(如初始化超时)时,退回到不携带错误信息的提交,避免阻塞源码保存
192
- emit('submit', newValues);
178
+ console.error('validateForm error', e);
179
+ // 嵌套配置 / initValue 等机制故障不得当成「校验通过」,
180
+ // 把 error 交给上层记录,同时仍提交源码,避免阻塞保存。
181
+ emit('submit', newValues, undefined, e instanceof Error ? e : new Error(String(e)));
193
182
  }
194
183
  };
195
184
 
@@ -8,7 +8,6 @@
8
8
  :config="curFormConfig"
9
9
  :values="values"
10
10
  :disabledShowSrc="disabledShowSrc"
11
- :extendState="extendState"
12
11
  @submit="(v, eventData, error) => submit(v, eventData, error, 'props')"
13
12
  @submit-error="errorHandler"
14
13
  @form-error="errorHandler"
@@ -26,7 +25,6 @@
26
25
  :config="styleFormConfig"
27
26
  :values="values"
28
27
  :disabledShowSrc="disabledShowSrc"
29
- :extendState="extendState"
30
28
  @submit="(v, eventData, error) => submit(v, eventData, error, 'style')"
31
29
  @submit-error="errorHandler"
32
30
  @form-error="errorHandler"
@@ -61,7 +59,7 @@ import type { OnDrag } from 'gesto';
61
59
 
62
60
  import { type MNode } from '@tmagic/core';
63
61
  import { TMagicButton } from '@tmagic/design';
64
- import type { ContainerChangeEventData, FormState, FormValue } from '@tmagic/form';
62
+ import type { ContainerChangeEventData, FormValue } from '@tmagic/form';
65
63
  import { setValueByKeyPath } from '@tmagic/utils';
66
64
 
67
65
  import MIcon from '@editor/components/Icon.vue';
@@ -84,7 +82,6 @@ defineOptions({
84
82
 
85
83
  defineProps<{
86
84
  disabledShowSrc?: boolean;
87
- extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
88
85
  }>();
89
86
 
90
87
  const emit = defineEmits<{
@@ -82,7 +82,7 @@ const props = defineProps<{
82
82
  customContentMenu: CustomContentMenuFunction;
83
83
  }>();
84
84
 
85
- const eventBus = inject<EventBus>('eventBus');
85
+ const eventBus = inject<EventBus | null>('eventBus', null);
86
86
 
87
87
  const { codeBlockService } = useServices();
88
88
 
@@ -6,7 +6,7 @@ import ContentMenu from '@editor/components/ContentMenu.vue';
6
6
  import type { ContentMenuTarget, EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
7
7
 
8
8
  export const useContentMenu = (deleteCode: (id: string) => void) => {
9
- const eventBus = inject<EventBus>('eventBus');
9
+ const eventBus = inject<EventBus | null>('eventBus', null);
10
10
  const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
11
11
 
12
12
  let selectId = '';
@@ -75,7 +75,7 @@ const props = defineProps<{
75
75
  customContentMenu: CustomContentMenuFunction;
76
76
  }>();
77
77
 
78
- const eventBus = inject<EventBus>('eventBus');
78
+ const eventBus = inject<EventBus | null>('eventBus', null);
79
79
  const { dataSourceService } = useServices();
80
80
 
81
81
  const { editDialog, dataSourceValues, dialogTitle, editable, editHandler, submitDataSourceHandler } =
@@ -6,7 +6,7 @@ import ContentMenu from '@editor/components/ContentMenu.vue';
6
6
  import type { ContentMenuTarget, EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
7
7
 
8
8
  export const useContentMenu = () => {
9
- const eventBus = inject<EventBus>('eventBus');
9
+ const eventBus = inject<EventBus | null>('eventBus', null);
10
10
  const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
11
11
 
12
12
  let selectId = '';
package/src/plugin.ts CHANGED
@@ -20,8 +20,8 @@ import { type App } from 'vue';
20
20
 
21
21
  import type { DesignPluginOptions } from '@tmagic/design';
22
22
  import designPlugin from '@tmagic/design';
23
- import type { FormInstallOptions } from '@tmagic/form';
24
- import formPlugin, { registerSilentLeafFieldTypes, registerTypeMatchRules } from '@tmagic/form';
23
+ import type { FieldOptions, FormInstallOptions } from '@tmagic/form';
24
+ import formPlugin, { mergeFieldOptions } from '@tmagic/form';
25
25
  import tablePlugin from '@tmagic/table';
26
26
 
27
27
  import Code from './fields/Code.vue';
@@ -38,13 +38,13 @@ import DataSourceMocks from './fields/DataSourceMocks.vue';
38
38
  import DataSourceSelect from './fields/DataSourceSelect.vue';
39
39
  import DisplayConds from './fields/DisplayConds.vue';
40
40
  import EventSelect from './fields/EventSelect.vue';
41
+ import { editorFields } from './fields/headless-validation';
41
42
  import KeyValue from './fields/KeyValue.vue';
42
43
  import PageFragmentSelect from './fields/PageFragmentSelect.vue';
43
44
  import StyleSetter from './fields/StyleSetter/Index.vue';
44
45
  import uiSelect from './fields/UISelect.vue';
45
46
  import CodeEditor from './layouts/CodeEditor.vue';
46
47
  import { setEditorConfig } from './utils/config';
47
- import { editorTypeMatchRules } from './utils/type-match-rules';
48
48
  import Editor from './Editor.vue';
49
49
  import type { EditorInstallOptions } from './type';
50
50
 
@@ -60,44 +60,43 @@ const defaultInstallOpt: EditorInstallOptions = {
60
60
  flat: false,
61
61
  };
62
62
 
63
+ const editorFieldVue: Record<string, Pick<FieldOptions, 'component' | 'container'>> = {
64
+ 'vs-code': { component: Code },
65
+ 'ui-select': { component: uiSelect },
66
+ 'cond-op-select': { component: CondOpSelect },
67
+ 'page-fragment-select': { component: PageFragmentSelect },
68
+ 'data-source-select': { component: DataSourceSelect },
69
+ 'data-source-input': { component: DataSourceInput },
70
+ 'code-link': { component: CodeLink },
71
+ 'key-value': { component: KeyValue },
72
+ 'code-select-col': { component: CodeSelectCol },
73
+ 'data-source-fields': { component: DataSourceFields },
74
+ 'data-source-mocks': { component: DataSourceMocks },
75
+ 'data-source-methods': { component: DataSourceMethods },
76
+ 'data-source-method-select': { component: DataSourceMethodSelect },
77
+ 'data-source-field-select': { component: DataSourceFieldSelect },
78
+ 'code-select': { component: CodeSelect },
79
+ 'display-conds': { component: DisplayConds },
80
+ 'event-select': { component: EventSelect },
81
+ 'style-setter': { container: StyleSetter },
82
+ };
83
+
63
84
  export default {
64
85
  install: (app: App, opt?: Partial<EditorInstallOptions | DesignPluginOptions | FormInstallOptions>): void => {
65
- const option = Object.assign(defaultInstallOpt, opt || {});
86
+ const incoming = opt || {};
87
+ const option = { ...defaultInstallOpt, ...incoming };
88
+ const formOpt = incoming as FormInstallOptions;
66
89
 
67
- app.use(designPlugin, opt || {});
68
- app.use(formPlugin, opt || {});
90
+ app.use(designPlugin, incoming);
91
+ app.use(formPlugin, {
92
+ ...formOpt,
93
+ fields: mergeFieldOptions(editorFields, editorFieldVue, formOpt.fields),
94
+ });
69
95
  app.use(tablePlugin);
70
- registerTypeMatchRules(editorTypeMatchRules);
71
- registerSilentLeafFieldTypes([
72
- 'vs-code',
73
- 'ui-select',
74
- 'cond-op-select',
75
- 'page-fragment-select',
76
- 'data-source-select',
77
- 'data-source-input',
78
- ]);
79
96
 
80
97
  app.config.globalProperties.$TMAGIC_EDITOR = option;
81
98
  setEditorConfig(option);
82
99
  app.component(`${Editor.name || 'MEditor'}`, Editor);
83
100
  app.component('magic-code-editor', CodeEditor);
84
- app.component('m-fields-ui-select', uiSelect);
85
- app.component('m-fields-code-link', CodeLink);
86
- app.component('m-fields-vs-code', Code);
87
- app.component('m-fields-code-select', CodeSelect);
88
- app.component('m-fields-code-select-col', CodeSelectCol);
89
- app.component('m-fields-event-select', EventSelect);
90
- app.component('m-fields-data-source-fields', DataSourceFields);
91
- app.component('m-fields-data-source-mocks', DataSourceMocks);
92
- app.component('m-fields-key-value', KeyValue);
93
- app.component('m-fields-data-source-input', DataSourceInput);
94
- app.component('m-fields-data-source-select', DataSourceSelect);
95
- app.component('m-fields-data-source-methods', DataSourceMethods);
96
- app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
97
- app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
98
- app.component('m-fields-page-fragment-select', PageFragmentSelect);
99
- app.component('m-fields-display-conds', DisplayConds);
100
- app.component('m-fields-cond-op-select', CondOpSelect);
101
- app.component('m-form-style-setter', StyleSetter);
102
101
  },
103
102
  };
@@ -1,40 +1,3 @@
1
1
  .m-fields-code-select {
2
2
  width: 100%;
3
- > .el-card.tmagic-design-card--flat {
4
- background-color: transparent;
5
- margin-bottom: 10px;
6
- > .el-card__body {
7
- padding-left: 0;
8
- .code-select-content {
9
- > .m-fields-group-list {
10
- > .tmagic-design-card--flat.el-card {
11
- padding-left: 16px;
12
- padding-right: 16px;
13
- margin-bottom: 10px;
14
- border: 0 !important;
15
- }
16
- }
17
- }
18
- }
19
- }
20
- .el-card__body {
21
- .tmagic-design-form-item {
22
- margin-bottom: 16px;
23
- }
24
- }
25
- .code-select-content {
26
- > .m-fields-group-list {
27
- > .tmagic-design-card--flat {
28
- > .el-card__header {
29
- padding: 16px 0;
30
- }
31
- }
32
- }
33
- }
34
- .create-button {
35
- &.fullWidth {
36
- width: 100%;
37
- margin: 0 0 16px 0;
38
- }
39
- }
40
3
  }
@@ -1,3 +1,7 @@
1
+ .m-fields-display-conds {
2
+ width: 100%;
3
+ }
4
+
1
5
  .m-container-text.display-conds-title {
2
6
  .tmagic-design-form-item {
3
7
  .el-form-item__label {
@@ -1,49 +1,45 @@
1
1
  .m-fields-event-select {
2
2
  width: 100%;
3
+
3
4
  .fullWidth {
4
5
  width: 100%;
5
6
  box-sizing: border-box;
6
- &.create-button {
7
- width: 100%;
8
- }
9
7
  &.m-container-ui-event {
10
8
  width: calc(100% - 32px);
11
9
  }
12
10
  }
11
+
13
12
  .event-select-container {
14
13
  padding: 0 16px;
15
- > .el-card.tmagic-design-card--flat {
16
- > .el-card__header {
14
+
15
+ > .m-fields-group-list
16
+ > .m-fields-group-list-item.tmagic-design-card--flat {
17
+ > .el-card__header,
18
+ > .t-card__header {
17
19
  border-bottom: 1px solid #ebeef5;
18
20
  }
19
- > .el-card__body {
21
+
22
+ > .el-card__body,
23
+ > .t-card__body {
20
24
  padding-bottom: 16px;
21
- .m-fields-group-list-footer {
22
- div {
23
- justify-content: flex-start !important;
24
- }
25
- }
26
- .el-card.tmagic-design-card--flat {
27
- > .el-card__header {
25
+
26
+ .el-card.tmagic-design-card--flat,
27
+ .t-card.tmagic-design-card--flat {
28
+ > .el-card__header,
29
+ > .t-card__header {
28
30
  padding: 16px 0;
29
31
  }
30
32
  }
31
33
  }
32
34
  }
33
35
  }
36
+
34
37
  .event-select-code {
35
38
  margin-left: 20px;
36
39
  width: auto;
37
40
  }
38
-
39
- .m-form-panel {
40
- margin: 10px 0px;
41
- }
42
-
43
- .el-card.is-always-shadow {
44
- box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.12);
45
- }
46
41
  }
42
+
47
43
  .m-fields-code-select-col,
48
44
  .m-fields-data-source-method-select {
49
45
  width: 100%;
@@ -63,10 +59,6 @@
63
59
  }
64
60
  }
65
61
 
66
- .event-select-container {
67
- padding: 0 16px;
68
- }
69
-
70
62
  .event-select-header {
71
63
  display: flex;
72
64
  align-items: center;
@@ -79,28 +71,13 @@
79
71
  line-height: 24px;
80
72
  }
81
73
  }
74
+
82
75
  .event-item-header {
83
- position: relative;
84
76
  width: 100%;
85
- display: flex;
86
- align-items: center;
87
- justify-content: space-between;
88
- .event-item-title {
89
- color: #0f1113;
90
- font-size: 16px;
91
- font-weight: 500;
92
- line-height: 24px;
93
- margin-bottom: 8px;
94
- }
95
- .event-item-delete-button {
96
- color: #0f1113;
77
+ .tmagic-design-form-item {
78
+ margin-bottom: 0;
97
79
  }
98
-
99
- .el-form-item {
100
- .el-form-item {
101
- &.is-error {
102
- margin-bottom: 18px;
103
- }
104
- }
80
+ .el-form-item .el-form-item.is-error {
81
+ margin-bottom: 18px;
105
82
  }
106
83
  }
@@ -125,14 +125,28 @@
125
125
  .m-editor-props-form-panel-form {
126
126
  padding-right: 10px;
127
127
  padding-left: 10px;
128
+ // 吸顶标题避开绝对定位的 tabs header
129
+ --m-group-list-header-sticky-top: var(
130
+ --el-tabs-header-height,
131
+ var(--td-comp-size-xxl, 48px)
132
+ );
128
133
 
129
134
  > .m-container-tab {
130
135
  > .tmagic-design-tabs {
131
- > .el-tabs__content {
132
- margin-top: var(--el-tabs-header-height);
136
+ > .el-tabs__content,
137
+ > .t-tabs__content {
138
+ margin-top: var(--el-tabs-header-height, var(--td-comp-size-xxl, 48px));
133
139
  padding-top: 15px;
140
+ // 允许吸底按钮相对属性面板滚动容器定位(tabs 默认 overflow:hidden 会截断 sticky)
141
+ overflow: visible;
142
+
143
+ > .el-tab-pane,
144
+ > .t-tab-panel {
145
+ overflow: visible;
146
+ }
134
147
  }
135
- > .el-tabs__header.is-top {
148
+ > .el-tabs__header.is-top,
149
+ > .t-tabs__header {
136
150
  position: absolute;
137
151
  top: 0;
138
152
  width: 100%;
@@ -137,7 +137,8 @@
137
137
  .m-editor-props-form-panel-form {
138
138
  > .m-container-tab {
139
139
  > .tmagic-design-tabs {
140
- > .el-tabs__content {
140
+ > .el-tabs__content,
141
+ > .t-tabs__content {
141
142
  background-color: #fafafa;
142
143
  border-radius: 8px;
143
144
  padding-left: 16px;
@@ -146,6 +147,16 @@
146
147
  }
147
148
  }
148
149
  }
150
+
151
+ .m-fields-group-list-footer.is-sticky-full {
152
+ --m-group-list-footer-bg: #fafafa;
153
+ background-color: #fafafa;
154
+ }
155
+
156
+ .m-fields-group-list-item .m-fields-group-list-footer.is-sticky-full {
157
+ --m-group-list-footer-bg: #fff;
158
+ background-color: #fff;
159
+ }
149
160
  }
150
161
 
151
162
  .m-editor.m-theme--magic-admin {
package/src/type.ts CHANGED
@@ -34,7 +34,7 @@ import type {
34
34
  MPageFragment,
35
35
  } from '@tmagic/core';
36
36
  import type { FieldSize } from '@tmagic/design';
37
- import type { ChangeRecord, FormConfig, FormState, TableColumnConfig, TypeFunction } from '@tmagic/form';
37
+ import type { ChangeRecord, FormConfig, TableColumnConfig, TypeFunction } from '@tmagic/form';
38
38
  import type StageCore from '@tmagic/stage';
39
39
  import type {
40
40
  CanDropIn,
@@ -172,6 +172,15 @@ export interface Services {
172
172
  }
173
173
  // #endregion Services
174
174
 
175
+ declare module '@tmagic/form-schema' {
176
+ interface FormContext {
177
+ /** 编辑器服务集合(由 Editor / FormPanel provide) */
178
+ services?: Services;
179
+ /** 当前画布 Stage 实例(由 Editor / FormPanel provide) */
180
+ stage?: any;
181
+ }
182
+ }
183
+
175
184
  export interface StageOptions {
176
185
  runtimeUrl?: string;
177
186
  autoScrollIntoView?: boolean;
@@ -598,18 +607,6 @@ export interface CompareFormBaseProps {
598
607
  * 避免 dialog / 面板使用方需要自行处理滚动。可传任意 CSS 长度,例如 `60vh` / `400px` / `100%`。
599
608
  */
600
609
  height?: string;
601
- /**
602
- * 用户自定义注入到 MForm.formState 的扩展字段,与 Editor 顶层的 `extendFormState`、
603
- * PropsPanel 的 `extend-state` 语义一致。表单 item 的 `display` / `disabled` 等
604
- * filterFunction 经常依赖这里注入的字段(如 stage、自定义业务上下文等),
605
- * 因此在对比 / 展示场景下也需要透传,避免出现 `formState.xxx is undefined` 的运行时错误。
606
- */
607
- extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
608
- /**
609
- * 外部透传的基础 formState(通常来自 PropsPanel 主属性表单)。
610
- * 组件会提取其中的扩展字段覆盖到自己的 formState,保证 filterFunction 上下文一致。
611
- */
612
- baseFormState?: FormState;
613
610
  /**
614
611
  * 表单内组件的尺寸(透传给 MForm 的 `size`),可选 'large' | 'default' | 'small'。
615
612
  * 缺省时使用 MForm 内置默认尺寸。
@@ -1558,17 +1555,6 @@ export interface UseHistoryRevertOptions {
1558
1555
  * (`getCurrentInstance()?.appContext`)。业务方若在组件 setup 之外调用,需手动传入(如 `editorApp._context`)。
1559
1556
  */
1560
1557
  appContext?: AppContext | null;
1561
- /**
1562
- * 透传给差异确认弹窗的 `extendState`(即 Editor 的 `extendFormState`),
1563
- * 使对比表单中依赖业务上下文的 `display` / `disabled` 等 filterFunction 正常工作。
1564
- */
1565
- extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
1566
- /**
1567
- * 返回 PropsPanel 主属性表单(FormPanel -> MForm)的 formState。
1568
- * 仅页面历史「查看差异 / 回滚确认」场景会使用该 formState 覆盖 CompareForm 中同名扩展字段,
1569
- * 以保证两处 filterFunction 读取到一致的运行态上下文。
1570
- */
1571
- getPropsPanelFormState?: () => FormState | undefined;
1572
1558
  /**
1573
1559
  * 内置页面 / 数据源 / 代码块的差异 / 回滚确认弹窗默认宽度(透传给 TMagicDialog 的 `width`),
1574
1560
  * 如 `'1200px'` / `'80%'`。缺省时使用弹窗内置默认宽度(900px)。
@@ -1590,11 +1576,6 @@ export interface CustomDiffFormOptions {
1590
1576
  loadConfig?: CompareFormLoadConfig;
1591
1577
  /** 需要走 self diff 的字段类型(如模块的 mod-cond)。 */
1592
1578
  selfDiffFieldTypes?: string[];
1593
- /**
1594
- * 可选:外部提供的 formState(通常来自 PropsPanel 主表单),
1595
- * 对比弹窗会用它覆盖 CompareForm 中同名扩展字段,避免上下文不一致。
1596
- */
1597
- compareFormState?: FormState;
1598
1579
  /**
1599
1580
  * 差异 / 确认回滚弹窗宽度(透传给 HistoryDiffDialog 的 TMagicDialog `width`),
1600
1581
  * 如 `'1200px'` / `'80%'`。缺省时使用弹窗内置默认宽度(900px)。
@@ -37,6 +37,7 @@ const dataSourceFormConfig: TabConfig = {
37
37
  name: 'events',
38
38
  src: 'datasource',
39
39
  type: 'event-select',
40
+ defaultValue: [],
40
41
  },
41
42
  ],
42
43
  },
@@ -151,6 +151,7 @@ export const eventTabConfig: TabPaneConfig = {
151
151
  src: 'component',
152
152
  labelWidth: '100px',
153
153
  type: 'event-select',
154
+ defaultValue: [],
154
155
  rules: [{ typeMatch: true }],
155
156
  },
156
157
  ],
@@ -163,7 +164,6 @@ export const advancedTabConfig: TabPaneConfig = {
163
164
  name: NODE_DISABLE_CODE_BLOCK_KEY,
164
165
  text: '禁用代码块',
165
166
  type: 'switch',
166
- labelPosition: 'left',
167
167
  defaultValue: false,
168
168
  extra: '开启后,配置的代码块将不会被执行',
169
169
  },
@@ -171,7 +171,6 @@ export const advancedTabConfig: TabPaneConfig = {
171
171
  name: NODE_DISABLE_DATA_SOURCE_KEY,
172
172
  text: '禁用数据源',
173
173
  type: 'switch',
174
- labelPosition: 'left',
175
174
  defaultValue: false,
176
175
  extra: '开启后,组件内配置的数据源相关配置将不会被编译,显隐条件将失效',
177
176
  },
@@ -257,8 +256,6 @@ export const displayTabConfig: TabPaneConfig<DisplayCondsConfig> = {
257
256
  type: 'display-conds',
258
257
  name: NODE_CONDS_KEY,
259
258
  titlePrefix: '条件组',
260
- fixed: 'right',
261
- operateColWidth: 112,
262
259
  defaultValue: [],
263
260
  rules: [{ typeMatch: true }],
264
261
  },