@tmagic/editor 1.8.0-beta.10 → 1.8.0-beta.12

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 (111) hide show
  1. package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +7 -4
  2. package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +4 -0
  3. package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +2 -1
  4. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +5 -2
  5. package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +60 -14
  6. package/dist/es/components/ScrollBar.js +0 -1
  7. package/dist/es/editorProps.js +6 -1
  8. package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +15 -3
  9. package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +2 -17
  10. package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +2 -1
  11. package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +7 -0
  12. package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +5 -17
  13. package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +4 -0
  14. package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +29 -3
  15. package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +50 -88
  16. package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +2 -5
  17. package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +48 -23
  18. package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +6 -3
  19. package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +28 -22
  20. package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +28 -22
  21. package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +28 -22
  22. package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +6 -3
  23. package/dist/es/fields/UISelect.js +0 -1
  24. package/dist/es/index.js +9 -6
  25. package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +21 -6
  26. package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +9 -6
  27. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +14 -4
  28. package/dist/es/layouts/history-list/composables.js +1 -1
  29. package/dist/es/layouts/history-list/useHistoryRevert.js +17 -6
  30. package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +44 -5
  31. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +15 -8
  32. package/dist/es/layouts/props-panel/use-style-panel.js +3 -2
  33. package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +15 -31
  34. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  35. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +18 -3
  36. package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +4 -0
  37. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  38. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +18 -3
  39. package/dist/es/layouts/sidebar/layer/LayerNodeContent.js +5 -0
  40. package/dist/es/layouts/sidebar/layer/LayerNodeContent.vue_vue_type_script_setup_true_lang.js +46 -0
  41. package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +2 -1
  42. package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +8 -2
  43. package/dist/es/plugin.js +3 -1
  44. package/dist/es/services/editor.js +104 -5
  45. package/dist/es/services/props.js +2 -1
  46. package/dist/es/services/storage.js +1 -1
  47. package/dist/es/services/ui.js +3 -0
  48. package/dist/es/style.css +104 -55
  49. package/dist/es/utils/data-source/index.js +30 -11
  50. package/dist/es/utils/event.js +123 -0
  51. package/dist/es/utils/monaco-editor.js +22 -6
  52. package/dist/es/utils/props.js +94 -8
  53. package/dist/es/utils/type-match-rules.js +360 -0
  54. package/dist/style.css +104 -55
  55. package/dist/tmagic-editor.umd.cjs +16923 -15771
  56. package/package.json +8 -8
  57. package/src/Editor.vue +3 -1
  58. package/src/components/CodeBlockEditor.vue +3 -0
  59. package/src/components/CompareForm.vue +7 -0
  60. package/src/components/FloatingBox.vue +77 -8
  61. package/src/components/ScrollBar.vue +0 -67
  62. package/src/editorProps.ts +13 -0
  63. package/src/fields/CodeSelect.vue +4 -1
  64. package/src/fields/CondOpSelect.vue +2 -24
  65. package/src/fields/DataSourceFields.vue +5 -0
  66. package/src/fields/DataSourceInput.vue +7 -25
  67. package/src/fields/DataSourceMocks.vue +3 -0
  68. package/src/fields/DisplayConds.vue +14 -0
  69. package/src/fields/EventSelect.vue +84 -129
  70. package/src/fields/StyleSetter/Index.vue +2 -8
  71. package/src/fields/StyleSetter/pro/Background.vue +94 -55
  72. package/src/fields/StyleSetter/pro/Border.vue +9 -11
  73. package/src/fields/StyleSetter/pro/Font.vue +66 -64
  74. package/src/fields/StyleSetter/pro/Layout.vue +140 -138
  75. package/src/fields/StyleSetter/pro/Position.vue +69 -67
  76. package/src/fields/StyleSetter/pro/Transform.vue +23 -25
  77. package/src/fields/UISelect.vue +0 -12
  78. package/src/index.ts +1 -0
  79. package/src/layouts/CodeEditor.vue +32 -6
  80. package/src/layouts/Framework.vue +7 -6
  81. package/src/layouts/history-list/HistoryDiffDialog.vue +23 -5
  82. package/src/layouts/history-list/useHistoryRevert.ts +25 -5
  83. package/src/layouts/props-panel/FormPanel.vue +66 -5
  84. package/src/layouts/props-panel/PropsPanel.vue +20 -6
  85. package/src/layouts/props-panel/use-style-panel.ts +4 -3
  86. package/src/layouts/sidebar/Sidebar.vue +2 -0
  87. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +4 -1
  88. package/src/layouts/sidebar/code-block/useContentMenu.ts +13 -1
  89. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +3 -0
  90. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +2 -2
  91. package/src/layouts/sidebar/data-source/useContentMenu.ts +13 -1
  92. package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
  93. package/src/layouts/sidebar/layer/LayerPanel.vue +4 -1
  94. package/src/layouts/workspace/viewer/NodeListMenu.vue +4 -1
  95. package/src/plugin.ts +3 -1
  96. package/src/services/editor.ts +168 -3
  97. package/src/services/ui.ts +6 -0
  98. package/src/theme/event.scss +8 -0
  99. package/src/theme/floating-box.scss +9 -1
  100. package/src/theme/layer-node-content.scss +14 -0
  101. package/src/theme/scroll-bar.scss +64 -0
  102. package/src/theme/theme.scss +3 -0
  103. package/src/theme/ui-select.scss +9 -0
  104. package/src/type.ts +72 -2
  105. package/src/utils/data-source/index.ts +30 -12
  106. package/src/utils/event.ts +224 -0
  107. package/src/utils/index.ts +2 -0
  108. package/src/utils/monaco-editor.ts +27 -0
  109. package/src/utils/props.ts +160 -2
  110. package/src/utils/type-match-rules.ts +678 -0
  111. package/types/index.d.ts +391 -85
package/dist/es/style.css CHANGED
@@ -1,55 +1,4 @@
1
- @charset "UTF-8";.m-editor-scroll-bar {
2
- position: absolute;
3
- background-color: transparent;
4
- opacity: 0.3;
5
- transition: background-color 0.2s linear, opacity 0.2s linear;
6
- }
7
- .m-editor-scroll-bar .m-editor-scroll-bar-thumb {
8
- background-color: #aaa;
9
- border-radius: 6px;
10
- position: absolute;
11
- }
12
- .m-editor-scroll-bar.horizontal {
13
- width: 100%;
14
- height: 15px;
15
- bottom: 0;
16
- }
17
- .m-editor-scroll-bar.horizontal .m-editor-scroll-bar-thumb {
18
- height: 6px;
19
- transition: background-color 0.2s linear, height 0.2s ease-in-out;
20
- bottom: 2px;
21
- }
22
- .m-editor-scroll-bar.vertical {
23
- height: 100%;
24
- width: 15px;
25
- right: 5px;
26
- }
27
- .m-editor-scroll-bar.vertical .m-editor-scroll-bar-thumb {
28
- width: 6px;
29
- transition: background-color 0.2s linear, width 0.2s ease-in-out;
30
- right: 2px;
31
- }
32
- .m-editor-scroll-bar:hover, .m-editor-scroll-bar:focus {
33
- background-color: #eee;
34
- opacity: 0.9;
35
- }
36
- .m-editor-scroll-bar:hover .m-editor-scroll-bar-thumb, .m-editor-scroll-bar:focus .m-editor-scroll-bar-thumb {
37
- background-color: #999;
38
- }
39
- .m-editor-scroll-bar:hover.horizontal .m-editor-scroll-bar-thumb, .m-editor-scroll-bar:focus.horizontal .m-editor-scroll-bar-thumb {
40
- height: 11px;
41
- }
42
- .m-editor-scroll-bar:hover.vertical .m-editor-scroll-bar-thumb, .m-editor-scroll-bar:focus.vertical .m-editor-scroll-bar-thumb {
43
- width: 11px;
44
- }.m-fields-ui-select {
45
- cursor: pointer;
46
- }
47
- .m-fields-ui-select i {
48
- margin-right: 3px;
49
- }
50
- .m-fields-ui-select span {
51
- color: #2882e0;
52
- }
1
+ @charset "UTF-8";
53
2
  .tmagic-design-popper {
54
3
  min-width: 150px;
55
4
  line-height: 1.4;
@@ -115,6 +64,22 @@
115
64
  color: #999;
116
65
  }
117
66
 
67
+ .tmagic-table-sub-actions {
68
+ display: flex;
69
+ flex-direction: column;
70
+ gap: 4px;
71
+ align-items: flex-start;
72
+ }
73
+ .tmagic-table-sub-actions .sub-action-btn {
74
+ width: 100%;
75
+ }
76
+ .tmagic-table-sub-actions .tmagic-design-button + .tmagic-design-button {
77
+ margin-left: 0;
78
+ }
79
+ .tmagic-table-sub-actions .tmagic-design-button {
80
+ justify-content: flex-start;
81
+ }
82
+
118
83
  .tmagic-design-form-inline .m-form-container {
119
84
  display: inline-flex;
120
85
  }
@@ -139,7 +104,7 @@
139
104
  .m-form-dialog .m-dialog-body {
140
105
  padding: 0 20px;
141
106
  }
142
- .m-form-dialog .el-table .m-form-item .el-form-item {
107
+ .m-form-dialog .el-table .m-form-item .el-form-item:not(.is-error) {
143
108
  margin-bottom: 0;
144
109
  }
145
110
 
@@ -363,6 +328,10 @@ fieldset.m-fieldset .m-form-tip {
363
328
  width: 95vw !important;
364
329
  }
365
330
 
331
+ .el-form-item .m-fields-table .el-form-item.is-error {
332
+ margin-bottom: 18px;
333
+ }
334
+
366
335
  .m-fields-table {
367
336
  width: 100%;
368
337
  }
@@ -385,7 +354,7 @@ fieldset.m-fieldset .m-form-tip {
385
354
  .m-fields-table .el-table__expanded-cell .m-form-tip {
386
355
  margin-left: 80px;
387
356
  }
388
- .m-fields-table .el-form-item {
357
+ .m-fields-table .el-form-item:not(.is-error) {
389
358
  margin-bottom: 0;
390
359
  }
391
360
  .m-fields-table .tmagic-form-table-drag-target {
@@ -1808,6 +1777,10 @@ fieldset.m-fieldset .m-form-tip {
1808
1777
  margin-right: 5px;
1809
1778
  }
1810
1779
 
1780
+ .el-form-item .el-form-item.is-error {
1781
+ margin-bottom: 18px;
1782
+ }
1783
+
1811
1784
  .m-editor-layout {
1812
1785
  width: 100%;
1813
1786
  display: flex;
@@ -2020,13 +1993,21 @@ fieldset.m-fieldset .m-form-tip {
2020
1993
  .m-editor-float-box .m-editor-float-box-body {
2021
1994
  overflow: auto;
2022
1995
  flex: 1;
2023
- padding: 0 16px;
2024
1996
  }
2025
1997
 
2026
1998
  .m-editor-floating-box-moveable {
2027
1999
  opacity: 0;
2028
2000
  }
2029
2001
 
2002
+ .m-editor-float-box-drag-mask {
2003
+ position: fixed;
2004
+ top: 0;
2005
+ left: 0;
2006
+ width: 100%;
2007
+ height: 100%;
2008
+ background-color: transparent;
2009
+ }
2010
+
2030
2011
  .m-fields-page-fragment-select {
2031
2012
  width: 100%;
2032
2013
  }
@@ -2076,6 +2057,74 @@ fieldset.m-fieldset .m-form-tip {
2076
2057
  padding: 5px 8px;
2077
2058
  }
2078
2059
 
2060
+ .m-editor-scroll-bar {
2061
+ position: absolute;
2062
+ background-color: transparent;
2063
+ opacity: 0.3;
2064
+ transition: background-color 0.2s linear, opacity 0.2s linear;
2065
+ }
2066
+ .m-editor-scroll-bar .m-editor-scroll-bar-thumb {
2067
+ background-color: #aaa;
2068
+ border-radius: 6px;
2069
+ position: absolute;
2070
+ }
2071
+ .m-editor-scroll-bar.horizontal {
2072
+ width: 100%;
2073
+ height: 15px;
2074
+ bottom: 0;
2075
+ }
2076
+ .m-editor-scroll-bar.horizontal .m-editor-scroll-bar-thumb {
2077
+ height: 6px;
2078
+ transition: background-color 0.2s linear, height 0.2s ease-in-out;
2079
+ bottom: 2px;
2080
+ }
2081
+ .m-editor-scroll-bar.vertical {
2082
+ height: 100%;
2083
+ width: 15px;
2084
+ right: 5px;
2085
+ }
2086
+ .m-editor-scroll-bar.vertical .m-editor-scroll-bar-thumb {
2087
+ width: 6px;
2088
+ transition: background-color 0.2s linear, width 0.2s ease-in-out;
2089
+ right: 2px;
2090
+ }
2091
+ .m-editor-scroll-bar:hover, .m-editor-scroll-bar:focus {
2092
+ background-color: #eee;
2093
+ opacity: 0.9;
2094
+ }
2095
+ .m-editor-scroll-bar:hover .m-editor-scroll-bar-thumb, .m-editor-scroll-bar:focus .m-editor-scroll-bar-thumb {
2096
+ background-color: #999;
2097
+ }
2098
+ .m-editor-scroll-bar:hover.horizontal .m-editor-scroll-bar-thumb, .m-editor-scroll-bar:focus.horizontal .m-editor-scroll-bar-thumb {
2099
+ height: 11px;
2100
+ }
2101
+ .m-editor-scroll-bar:hover.vertical .m-editor-scroll-bar-thumb, .m-editor-scroll-bar:focus.vertical .m-editor-scroll-bar-thumb {
2102
+ width: 11px;
2103
+ }
2104
+
2105
+ .m-fields-ui-select {
2106
+ cursor: pointer;
2107
+ }
2108
+ .m-fields-ui-select i {
2109
+ margin-right: 3px;
2110
+ }
2111
+ .m-fields-ui-select span {
2112
+ color: #2882e0;
2113
+ }
2114
+
2115
+ .m-editor-layer-node-content {
2116
+ display: inline-flex;
2117
+ align-items: center;
2118
+ }
2119
+ .m-editor-layer-node-content.is-invalid .m-editor-layer-node-label {
2120
+ color: var(--el-color-danger, #f56c6c);
2121
+ }
2122
+ .m-editor-layer-node-content .m-editor-layer-node-error-icon {
2123
+ margin-left: 4px;
2124
+ color: var(--el-color-danger, #f56c6c);
2125
+ cursor: help;
2126
+ }
2127
+
2079
2128
  .border-box-container {
2080
2129
  display: flex;
2081
2130
  }
@@ -188,17 +188,36 @@ var getCascaderOptionsFromFields = (fields = [], dataSourceFieldType = ["any"])
188
188
  }
189
189
  return result;
190
190
  };
191
- var getFieldType = (ds, fieldNames) => {
192
- let fields = ds?.fields;
193
- let type = "";
194
- for (const fieldName of fieldNames) {
195
- if (!fields?.length) return "";
196
- const field = fields.find((f) => f.name === fieldName);
197
- if (!field) return "";
198
- type = field.type || "";
199
- fields = field.fields;
191
+ /**
192
+ * 按字段名路径下钻 DataSchema。
193
+ * @param skipNumberIndices 为 true 时跳过数字段(模板路径中的数组下标,如 arr[0].x)
194
+ */
195
+ var resolveFieldByPath = (fields, fieldNames, options = {}) => {
196
+ let currentFields = fields || [];
197
+ let field;
198
+ for (const name of fieldNames) {
199
+ if (options.skipNumberIndices && isNumber(name)) continue;
200
+ if (!currentFields.length) return {
201
+ ok: false,
202
+ fields: currentFields
203
+ };
204
+ field = currentFields.find((item) => item.name === name);
205
+ if (!field) return {
206
+ ok: false,
207
+ fields: currentFields
208
+ };
209
+ currentFields = field.fields || [];
200
210
  }
201
- return type;
211
+ return {
212
+ field,
213
+ ok: true,
214
+ fields: currentFields
215
+ };
216
+ };
217
+ var getFieldType = (ds, fieldNames) => {
218
+ const { ok, field } = resolveFieldByPath(ds?.fields, fieldNames);
219
+ if (!ok) return "";
220
+ return field?.type || "";
202
221
  };
203
222
  //#endregion
204
- export { getCascaderOptionsFromFields, getDisplayField, getFieldType, getFormConfig, getFormValue };
223
+ export { getCascaderOptionsFromFields, getDisplayField, getFieldType, getFormConfig, getFormValue, resolveFieldByPath };
@@ -0,0 +1,123 @@
1
+ import editor_default from "../services/editor.js";
2
+ import { getCascaderOptionsFromFields } from "./data-source/index.js";
3
+ import dataSource_default from "../services/dataSource.js";
4
+ import events_default from "../services/events.js";
5
+ import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, traverseNode } from "@tmagic/utils";
6
+ //#region packages/editor/src/utils/event.ts
7
+ var EVENT_NAME_VALUE_SEPARATOR = ".";
8
+ /** 与 EventSelect 中 checkStrictly 一致:component 为 false,其余为 true */
9
+ var isEventNameCheckStrictly = (src) => src !== "component";
10
+ /** 将动作 method 值规范为与 collectEventNameOptionValues 一致的字符串(cascader 无 valueSeparator 时存数组) */
11
+ var normalizeCompActionValue = (value) => {
12
+ if (Array.isArray(value)) return value.map((item) => `${item}`).join(".");
13
+ if (value === null || value === void 0 || value === "") return "";
14
+ return `${value}`;
15
+ };
16
+ /**
17
+ * 组装事件名称下拉/级联 options,与 EventSelect 默认 eventNameConfig.options 逻辑一致。
18
+ */
19
+ var getEventNameOptions = (src, formValue = {}) => {
20
+ if (!formValue.type) return [];
21
+ if (src === "component") {
22
+ let events = events_default.getEvent(formValue.type) || [];
23
+ if (formValue.type === "page-fragment-container" && formValue.pageFragmentId) {
24
+ const pageFragment = editor_default.get("root")?.items?.find((page) => page.id === formValue.pageFragmentId);
25
+ if (!pageFragment) return [];
26
+ events = [{
27
+ label: pageFragment.name || "页面片容器",
28
+ value: pageFragment.id,
29
+ children: events
30
+ }];
31
+ (pageFragment.items || []).forEach((node) => {
32
+ traverseNode(node, (current) => {
33
+ const nodeEvents = current.type && events_default.getEvent(current.type) || [];
34
+ events.push({
35
+ label: `${current.name}_${current.id}`,
36
+ value: `${current.id}`,
37
+ children: nodeEvents
38
+ });
39
+ });
40
+ });
41
+ return events;
42
+ }
43
+ return events.map((option) => ({
44
+ text: option.label,
45
+ value: option.value
46
+ }));
47
+ }
48
+ if (src === "datasource") {
49
+ const events = dataSource_default.getFormEvent(formValue.type) || [];
50
+ const fields = dataSource_default.getDataSourceById(formValue.id)?.fields || [];
51
+ if (fields.length > 0) return [...events, {
52
+ label: "数据变化",
53
+ value: DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX,
54
+ children: getCascaderOptionsFromFields(fields)
55
+ }];
56
+ return events;
57
+ }
58
+ return [];
59
+ };
60
+ /** 将 select / cascader options 展平为最终写入 name 的字符串集合(cascader 用 `.` 拼接) */
61
+ var collectEventNameOptionValues = (options, checkStrictly, prefix = [], result = /* @__PURE__ */ new Set()) => {
62
+ options.forEach((option) => {
63
+ if (typeof option?.value === "undefined") return;
64
+ const path = [...prefix, option.value];
65
+ const joined = path.map((item) => `${item}`).join(".");
66
+ const children = "children" in option ? option.children : void 0;
67
+ if (Array.isArray(children) && children.length) {
68
+ if (checkStrictly) result.add(joined);
69
+ collectEventNameOptionValues(children, checkStrictly, path, result);
70
+ return;
71
+ }
72
+ result.add(joined);
73
+ });
74
+ return result;
75
+ };
76
+ /**
77
+ * 解析 event-select 允许的 name 集合。
78
+ * 自定义 eventNameConfig.options 时返回 null(跳过枚举校验)。
79
+ */
80
+ var getEventNameAllowedValues = (config = {}, formValue = {}) => {
81
+ if (typeof config.eventNameConfig?.options !== "undefined") return null;
82
+ if (config.src !== "component" && config.src !== "datasource") return null;
83
+ return collectEventNameOptionValues(getEventNameOptions(config.src, formValue), isEventNameCheckStrictly(config.src));
84
+ };
85
+ /**
86
+ * 组装联动组件动作下拉/级联 options,与 EventSelect 默认 compActionConfig.options 逻辑一致。
87
+ */
88
+ var getCompActionOptions = (toId) => {
89
+ if (typeof toId === "undefined" || toId === null || toId === "") return [];
90
+ const node = editor_default.getNodeById(toId);
91
+ if (!node?.type) return [];
92
+ let methods = events_default.getMethod(node.type, toId) || [];
93
+ if (node.type === "page-fragment-container" && node.pageFragmentId) {
94
+ const pageFragment = editor_default.get("root")?.items?.find((page) => page.id === node.pageFragmentId);
95
+ if (!pageFragment) return [];
96
+ methods = [];
97
+ (pageFragment.items || []).forEach((item) => {
98
+ traverseNode(item, (current) => {
99
+ const nodeMethods = current.type && events_default.getMethod(current.type, current.id) || [];
100
+ if (nodeMethods.length) methods.push({
101
+ label: `${current.name}_${current.id}`,
102
+ value: `${current.id}`,
103
+ children: nodeMethods
104
+ });
105
+ });
106
+ });
107
+ return methods;
108
+ }
109
+ return methods.map((method) => ({
110
+ text: method.label,
111
+ value: method.value
112
+ }));
113
+ };
114
+ /**
115
+ * 解析 event-select 联动组件动作允许的 method 集合。
116
+ * 自定义 compActionConfig.options 时返回 null(跳过枚举校验)。
117
+ */
118
+ var getCompActionAllowedValues = (config = {}, model = {}) => {
119
+ if (typeof config.compActionConfig?.options !== "undefined") return null;
120
+ return collectEventNameOptionValues(getCompActionOptions(model.to), isEventNameCheckStrictly(config.src));
121
+ };
122
+ //#endregion
123
+ export { EVENT_NAME_VALUE_SEPARATOR, collectEventNameOptionValues, getCompActionAllowedValues, getCompActionOptions, getEventNameAllowedValues, getEventNameOptions, isEventNameCheckStrictly, normalizeCompActionValue };
@@ -1,12 +1,28 @@
1
1
  //#region packages/editor/src/utils/monaco-editor.ts
2
2
  var cached;
3
- var monaco_editor_default = () => {
4
- if (!cached) cached = Promise.all([import("emmet-monaco-es"), import("monaco-editor")]).then(([emmet, monaco]) => {
5
- const { emmetHTML, emmetCSS } = emmet;
6
- emmetHTML(monaco);
7
- emmetCSS(monaco, ["css", "scss"]);
8
- return monaco;
3
+ var isMonacoCanceledError = (reason) => {
4
+ if (!reason) return false;
5
+ if (reason instanceof Error) return reason.name === "Canceled" || reason.message === "Canceled";
6
+ return reason === "Canceled";
7
+ };
8
+ var canceledRejectionHandlerInstalled = false;
9
+ var installCanceledRejectionHandler = () => {
10
+ if (canceledRejectionHandlerInstalled || typeof globalThis.addEventListener !== "function") return;
11
+ canceledRejectionHandlerInstalled = true;
12
+ globalThis.addEventListener("unhandledrejection", (event) => {
13
+ if (isMonacoCanceledError(event.reason)) event.preventDefault();
9
14
  });
15
+ };
16
+ var monaco_editor_default = () => {
17
+ if (!cached) {
18
+ installCanceledRejectionHandler();
19
+ cached = Promise.all([import("emmet-monaco-es"), import("monaco-editor")]).then(([emmet, monaco]) => {
20
+ const { emmetHTML, emmetCSS } = emmet;
21
+ emmetHTML(monaco);
22
+ emmetCSS(monaco, ["css", "scss"]);
23
+ return monaco;
24
+ });
25
+ }
10
26
  return cached;
11
27
  };
12
28
  //#endregion
@@ -1,5 +1,6 @@
1
+ import { validateForm } from "@tmagic/form";
1
2
  import { tMagicMessage } from "@tmagic/design";
2
- import { NODE_CONDS_KEY, NODE_CONDS_RESULT_KEY, NODE_DISABLE_CODE_BLOCK_KEY, NODE_DISABLE_DATA_SOURCE_KEY } from "@tmagic/core";
3
+ import { HookType, NODE_CONDS_KEY, NODE_CONDS_RESULT_KEY, NODE_DISABLE_CODE_BLOCK_KEY, NODE_DISABLE_DATA_SOURCE_KEY } from "@tmagic/core";
3
4
  //#region packages/editor/src/utils/props.ts
4
5
  var arrayOptions = [{
5
6
  text: "包含",
@@ -41,10 +42,29 @@ var numberOptions = [
41
42
  value: "not_between"
42
43
  }
43
44
  ];
45
+ var booleanOptions = [{
46
+ text: "是",
47
+ value: "is"
48
+ }, {
49
+ text: "不是",
50
+ value: "not"
51
+ }];
52
+ /** 按字段类型返回条件运算符选项(UI 与 typeMatch 校验共用) */
53
+ var getCondOpOptionsByFieldType = (type) => {
54
+ if (type === "array") return arrayOptions;
55
+ if (type === "boolean" || type === "null") return booleanOptions;
56
+ if (type === "number") return [...eqOptions, ...numberOptions];
57
+ if (type === "string") return [...arrayOptions, ...eqOptions];
58
+ return [
59
+ ...arrayOptions,
60
+ ...eqOptions,
61
+ ...numberOptions
62
+ ];
63
+ };
44
64
  var styleTabConfig = {
45
65
  title: "样式",
46
66
  lazy: true,
47
- display: ({ services }) => !(services.uiService.get("showStylePanel") ?? true),
67
+ display: ({ services }) => !(services?.uiService?.get("showStylePanel") ?? true),
48
68
  items: [{
49
69
  name: "style",
50
70
  labelWidth: "100px",
@@ -113,7 +133,8 @@ var eventTabConfig = {
113
133
  name: "events",
114
134
  src: "component",
115
135
  labelWidth: "100px",
116
- type: "event-select"
136
+ type: "event-select",
137
+ rules: [{ typeMatch: true }]
117
138
  }]
118
139
  };
119
140
  var advancedTabConfig = {
@@ -139,21 +160,42 @@ var advancedTabConfig = {
139
160
  text: "created",
140
161
  labelPosition: "top",
141
162
  type: "code-select",
142
- extra: "组件初始化时执行"
163
+ extra: "组件初始化时执行",
164
+ rules: [{
165
+ typeMatch: true,
166
+ trigger: "change"
167
+ }, { validator: ({ value, callback }) => {
168
+ if (value && value.hookType !== HookType.CODE) return callback("hookType 必须是 code");
169
+ callback();
170
+ } }]
143
171
  },
144
172
  {
145
173
  name: "mounted",
146
174
  text: "mounted",
147
175
  labelPosition: "top",
148
176
  type: "code-select",
149
- extra: "组件挂载到dom时执行"
177
+ extra: "组件挂载到dom时执行",
178
+ rules: [{
179
+ typeMatch: true,
180
+ trigger: "change"
181
+ }, { validator: ({ value, callback }) => {
182
+ if (value && value.hookType !== HookType.CODE) return callback("hookType 必须是 code");
183
+ callback();
184
+ } }]
150
185
  },
151
186
  {
152
187
  name: "display",
153
188
  text: "display",
154
189
  extra: "控制组件是否渲染,关系的代码块返回值为false时不渲染",
155
190
  labelPosition: "top",
156
- type: "code-select"
191
+ type: "code-select",
192
+ rules: [{
193
+ typeMatch: true,
194
+ trigger: "change"
195
+ }, { validator: ({ value, callback }) => {
196
+ if (value && value.hookType !== HookType.CODE) return callback("hookType 必须是 code");
197
+ callback();
198
+ } }]
157
199
  }
158
200
  ]
159
201
  };
@@ -177,7 +219,8 @@ var displayTabConfig = {
177
219
  type: "display-conds",
178
220
  name: NODE_CONDS_KEY,
179
221
  titlePrefix: "条件组",
180
- defaultValue: []
222
+ defaultValue: [],
223
+ rules: [{ typeMatch: true }]
181
224
  }]
182
225
  };
183
226
  /**
@@ -232,5 +275,48 @@ var fillConfig = (config = [], { labelWidth = "80px", disabledDataSource = false
232
275
  if (!disabledDataSource) tabConfig.items.push({ ...displayTabConfig });
233
276
  return [tabConfig];
234
277
  };
278
+ /**
279
+ * 对一份「组件属性表单配置 + 值」做一次独立的校验,**不复用也不污染页面上正在展示的表单**。
280
+ *
281
+ * 内部基于 `@tmagic/form` 的 `validateForm` 另建一个独立的 MForm 实例完成校验,并统一处理
282
+ * 编辑器场景所需的上下文注入:将当前组件实例的 provides 合入 appContext,并向 formState 注入
283
+ * stage / services 及外部扩展状态,保证校验规则依赖的上下文可用。
284
+ *
285
+ * 常用于源码编辑器保存后,对最新配置做一次校验,并将校验结果(错误信息)随提交一并抛给上层记录,
286
+ * 使源码保存的错误状态与表单编辑保持一致。
287
+ *
288
+ * @returns 校验通过返回空字符串 `''`,否则返回以 `<br>` 拼接的错误文案。
289
+ * 仅在初始化超时或挂载失败等异常情况下才会 reject。
290
+ *
291
+ * @example
292
+ * ```ts
293
+ * const error = await validatePropsForm({
294
+ * config,
295
+ * values,
296
+ * appContext: getCurrentInstance()?.appContext,
297
+ * services,
298
+ * stage: editorService.get('stage'),
299
+ * extendState,
300
+ * });
301
+ * if (error) {
302
+ * // 配置不合法,error 为错误文案
303
+ * }
304
+ * ```
305
+ */
306
+ var validatePropsForm = ({ config, values, appContext = null, services, stage, extendState, debug, typeMatchValid }) => validateForm({
307
+ config,
308
+ debug,
309
+ typeMatchValid,
310
+ initValues: values,
311
+ appContext: appContext ? {
312
+ ...appContext,
313
+ provides: { services }
314
+ } : null,
315
+ extendState: async (state) => ({
316
+ ...await extendState?.(state) || {},
317
+ stage,
318
+ services
319
+ })
320
+ });
235
321
  //#endregion
236
- export { advancedTabConfig, arrayOptions, displayTabConfig, eqOptions, eventTabConfig, fillConfig, numberOptions, styleTabConfig };
322
+ export { advancedTabConfig, arrayOptions, booleanOptions, displayTabConfig, eqOptions, eventTabConfig, fillConfig, getCondOpOptionsByFieldType, numberOptions, styleTabConfig, validatePropsForm };