@tmagic/editor 1.8.0-beta.14 → 1.8.0-beta.16

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.
@@ -66,15 +66,29 @@ var ContentMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
66
66
  if (contains(target)) return;
67
67
  hide();
68
68
  };
69
+ const fixPosition = () => {
70
+ const menu = menuEl.value;
71
+ if (!menu || !visible.value) return;
72
+ const menuHeight = menu.clientHeight;
73
+ const menuWidth = menu.clientWidth;
74
+ let { top, left } = menuPosition.value;
75
+ if (top + menuHeight > document.body.clientHeight) top = Math.max(0, document.body.clientHeight - menuHeight);
76
+ if (left + menuWidth > document.body.clientWidth) left = Math.max(0, document.body.clientWidth - menuWidth);
77
+ if (top !== menuPosition.value.top || left !== menuPosition.value.left) menuPosition.value = {
78
+ top,
79
+ left
80
+ };
81
+ };
69
82
  const setPosition = (e) => {
70
- const menuHeight = menuEl.value?.clientHeight || 0;
71
- let top = e.clientY;
72
- if (menuHeight + e.clientY > document.body.clientHeight) top = document.body.clientHeight - menuHeight;
73
83
  menuPosition.value = {
74
- top,
84
+ top: e.clientY,
75
85
  left: e.clientX
76
86
  };
87
+ fixPosition();
77
88
  };
89
+ const resizeObserver = new ResizeObserver(() => {
90
+ fixPosition();
91
+ });
78
92
  const show = (e) => {
79
93
  visible.value = true;
80
94
  nextTick(() => {
@@ -103,10 +117,12 @@ var ContentMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
103
117
  emit("mouseenter");
104
118
  };
105
119
  onMounted(() => {
120
+ if (menuEl.value) resizeObserver.observe(menuEl.value);
106
121
  if (props.isSubMenu) return;
107
122
  globalThis.addEventListener("mousedown", outsideClickHideHandler, true);
108
123
  });
109
124
  onBeforeUnmount(() => {
125
+ resizeObserver.disconnect();
110
126
  if (props.isSubMenu) return;
111
127
  globalThis.removeEventListener("mousedown", outsideClickHideHandler, true);
112
128
  });
@@ -1,5 +1,6 @@
1
1
  import CodeEditor_default from "../layouts/CodeEditor.js";
2
- import { computed, createBlock, defineComponent, openBlock } from "vue";
2
+ import { FORM_SILENT_MODE_KEY } from "@tmagic/form";
3
+ import { computed, createBlock, createCommentVNode, defineComponent, inject, openBlock, unref } from "vue";
3
4
  //#region packages/editor/src/fields/Code.vue?vue&type=script&setup=true&lang.ts
4
5
  var Code_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
5
6
  name: "MFieldsVsCode",
@@ -24,6 +25,12 @@ var Code_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
24
25
  },
25
26
  emits: ["change"],
26
27
  setup(__props, { emit: __emit }) {
28
+ /**
29
+ * 静默模式(submitForm/validateForm 隐藏挂载)下跳过 monaco 渲染:
30
+ * 校验由 FormItem 针对 model 中的值完成,与编辑器实例无关;本组件挂载无值副作用
31
+ * (save 仅由用户操作/编辑器内容变更触发),跳过可省去 monaco worker/model 的无谓实例化。
32
+ */
33
+ const silentMode = inject(FORM_SILENT_MODE_KEY, false);
27
34
  const emit = __emit;
28
35
  const props = __props;
29
36
  /**
@@ -41,7 +48,8 @@ var Code_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
41
48
  emit("change", v);
42
49
  };
43
50
  return (_ctx, _cache) => {
44
- return openBlock(), createBlock(CodeEditor_default, {
51
+ return !unref(silentMode) ? (openBlock(), createBlock(CodeEditor_default, {
52
+ key: 0,
45
53
  height: __props.config.height,
46
54
  type: diffMode.value ? "diff" : void 0,
47
55
  "init-values": diffMode.value ? (__props.lastValues || {})[__props.name] : __props.model[__props.name],
@@ -65,7 +73,7 @@ var Code_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
65
73
  "autosize",
66
74
  "parse",
67
75
  "editor-custom-type"
68
- ]);
76
+ ])) : createCommentVNode("v-if", true);
69
77
  };
70
78
  }
71
79
  });
package/dist/es/index.js CHANGED
@@ -2,7 +2,7 @@ import { CODE_DRAFT_STORAGE_KEY, CodeDeleteErrorType, ColumnLayout, DragType, Ke
2
2
  import { useCodeBlockEdit } from "./hooks/use-code-block-edit.js";
3
3
  import { getEditorConfig, isGlobalFlat, setEditorConfig } from "./utils/config.js";
4
4
  import { getCodeBlockFormConfig } from "./utils/code-block.js";
5
- import { advancedTabConfig, arrayOptions, booleanOptions, displayTabConfig, eqOptions, eventTabConfig, fillConfig, getCondOpOptionsByFieldType, numberOptions, removeStyleDisplayConfig, styleTabConfig, validatePropsForm } from "./utils/props.js";
5
+ import { advancedTabConfig, arrayOptions, booleanOptions, displayTabConfig, eqOptions, eventTabConfig, fillConfig, getCondOpOptionsByFieldType, numberOptions, removeStyleDisplayConfig, styleTabConfig } from "./utils/props.js";
6
6
  import { useCompareForm } from "./hooks/use-compare-form.js";
7
7
  import props_default from "./services/props.js";
8
8
  import { UndoRedo } from "./utils/undo-redo.js";
@@ -92,4 +92,4 @@ export * from "@tmagic/table";
92
92
  export * from "@tmagic/stage";
93
93
  export * from "@tmagic/design";
94
94
  export * from "@tmagic/utils";
95
- export { ALL_COND_OPS, CODE_DRAFT_STORAGE_KEY, COPY_CODE_STORAGE_KEY, COPY_DS_STORAGE_KEY, COPY_STORAGE_KEY, CodeBlockEditor_default as CodeBlockEditor, CodeBlockList_default as CodeBlockList, CodeBlockListPanel_default as CodeBlockListPanel, CodeDeleteErrorType, CodeSelect_default as CodeSelect, CodeSelectCol_default as CodeSelectCol, ColumnLayout, CompareForm_default as CompareForm, ComponentListPanel_default as ComponentListPanel, CondOpSelect_default as CondOpSelect, ContentMenu_default as ContentMenu, DEFAULT_LEFT_COLUMN_WIDTH, DEFAULT_RIGHT_COLUMN_WIDTH, DataSourceAddButton_default as DataSourceAddButton, DataSourceConfigPanel_default as DataSourceConfigPanel, Index_default as DataSourceFieldSelect, DataSourceFields_default as DataSourceFields, DataSourceInput_default as DataSourceInput, DataSourceMethodSelect_default as DataSourceMethodSelect, DataSourceMethods_default as DataSourceMethods, DataSourceMocks_default as DataSourceMocks, DataSourceSelect_default as DataSourceSelect, DepTargetType, DisplayConds_default as DisplayConds, DragType, EVENT_NAME_VALUE_SEPARATOR, EventSelect_default as EventSelect, Fixed2Other, FloatingBox_default as FloatingBox, H_GUIDE_LINE_STORAGE_KEY, HistoryDiffDialog_default as HistoryDiffDialog, Bucket_default as HistoryListBucket, BucketTab_default as HistoryListBucketTab, Icon_default as Icon, IdleTask, KeyBindingCommand, KeyValue_default as KeyValue, Keys, LEFT_COLUMN_WIDTH_STORAGE_KEY, LayerNodeContent_default as LayerNodeContent, LayerOffset, LayerPanel_default as LayerPanel, Layout, SplitView_default as LayoutContainer, MIN_CENTER_COLUMN_WIDTH, MIN_LEFT_COLUMN_WIDTH, MIN_RIGHT_COLUMN_WIDTH, PROPS_PANEL_WIDTH_STORAGE_KEY, PageFragmentSelect_default as PageFragmentSelect, FormPanel_default as PropsFormPanel, PropsPanel_default as PropsPanel, RIGHT_COLUMN_WIDTH_STORAGE_KEY, Resizer_default as Resizer, ScrollViewer, SideItemKey, SplitView_default as SplitView, StageCore, Index_default$1 as StyleSetter, CodeEditor_default as TMagicCodeEditor, Editor_default as TMagicEditor, ToolButton_default as ToolButton, Tree_default as Tree, TreeNode_default as TreeNode, UI_SELECT_MODE_EVENT_NAME, UndoRedo, V_GUIDE_LINE_STORAGE_KEY, ViewForm_default as ViewForm, advancedTabConfig, arrayOptions, beforePaste, booleanOptions, buildChangeRecords, calcAlignCenterStyle, calcLayerTargetIndex, calcMoveStyle, canUsePluginMethods, change2Fixed, classifyDragSources, codeBlock_default as codeBlockService, collectEventNameOptionValues, collectRelatedNodes, componentList_default as componentListService, confirmHistoryAction, createStackStep, dataSource_default as dataSourceService, debug, plugin_default as default, defaultIsExpandable, dep_default as depService, describeRevertStep, describeStepForRevert, deserializeStacks, designPlugin, detectStackOpType, detectTargetId, detectTargetName, displayTabConfig, editorNodeMergeCustomizer, editor_default as editorService, editorTypeMatchRules, eqOptions, error, eventTabConfig, events_default as eventsService, fillConfig, fixNodeLeft, fixNodePosition, formPlugin, generatePageName, generatePageNameByApp, getAddParent, getCascaderOptionsFromFields, getCodeBlockFormConfig, getCompActionAllowedValues, getCompActionOptions, getCondOpOptionsByFieldType, getDefaultConfig, getDisplayField, getEditorConfig, getEventNameAllowedValues, getEventNameOptions, getFieldType, getFormConfig, getFormValue, getGuideLineFromCache, getInitPositionStyle, getLastPushedHistoryIds, getNodeIndex, getOrCreateStack, getPageFragmentList, getPageList, getPageNameList, getPositionInContainer, getRelativeStyle, history_default as historyService, idbDelete, idbGet, idbSet, info, isEventNameCheckStrictly, isGlobalFlat, isIncludeDataSource, isIndexedDBSupported, keybinding_default as keybindingService, monaco_editor_default as loadMonaco, log, markStackSaved, mergeSteps, moveItemsInContainer, normalizeCompActionValue, numberOptions, openIndexedDB, props_default as propsService, removeStyleDisplayConfig, resolveFieldByPath, resolveSelectedNode, serializeConfig, serializeStacks, setChildrenLayout, setEditorConfig, setLayout, stageOverlay_default as stageOverlayService, storage_default as storageService, styleTabConfig, tablePlugin, toggleFixedPosition, ui_default as uiService, undoFloor, updateStatus, useCodeBlockEdit, useCompareForm, useEditorContentHeight, useFilter, useFloatBox, useGetSo, useHistoryRevert, useNextFloatBoxPosition, useNodeStatus, useServices, useStage, useWindowRect, validatePropsForm, warn };
95
+ export { ALL_COND_OPS, CODE_DRAFT_STORAGE_KEY, COPY_CODE_STORAGE_KEY, COPY_DS_STORAGE_KEY, COPY_STORAGE_KEY, CodeBlockEditor_default as CodeBlockEditor, CodeBlockList_default as CodeBlockList, CodeBlockListPanel_default as CodeBlockListPanel, CodeDeleteErrorType, CodeSelect_default as CodeSelect, CodeSelectCol_default as CodeSelectCol, ColumnLayout, CompareForm_default as CompareForm, ComponentListPanel_default as ComponentListPanel, CondOpSelect_default as CondOpSelect, ContentMenu_default as ContentMenu, DEFAULT_LEFT_COLUMN_WIDTH, DEFAULT_RIGHT_COLUMN_WIDTH, DataSourceAddButton_default as DataSourceAddButton, DataSourceConfigPanel_default as DataSourceConfigPanel, Index_default as DataSourceFieldSelect, DataSourceFields_default as DataSourceFields, DataSourceInput_default as DataSourceInput, DataSourceMethodSelect_default as DataSourceMethodSelect, DataSourceMethods_default as DataSourceMethods, DataSourceMocks_default as DataSourceMocks, DataSourceSelect_default as DataSourceSelect, DepTargetType, DisplayConds_default as DisplayConds, DragType, EVENT_NAME_VALUE_SEPARATOR, EventSelect_default as EventSelect, Fixed2Other, FloatingBox_default as FloatingBox, H_GUIDE_LINE_STORAGE_KEY, HistoryDiffDialog_default as HistoryDiffDialog, Bucket_default as HistoryListBucket, BucketTab_default as HistoryListBucketTab, Icon_default as Icon, IdleTask, KeyBindingCommand, KeyValue_default as KeyValue, Keys, LEFT_COLUMN_WIDTH_STORAGE_KEY, LayerNodeContent_default as LayerNodeContent, LayerOffset, LayerPanel_default as LayerPanel, Layout, SplitView_default as LayoutContainer, MIN_CENTER_COLUMN_WIDTH, MIN_LEFT_COLUMN_WIDTH, MIN_RIGHT_COLUMN_WIDTH, PROPS_PANEL_WIDTH_STORAGE_KEY, PageFragmentSelect_default as PageFragmentSelect, FormPanel_default as PropsFormPanel, PropsPanel_default as PropsPanel, RIGHT_COLUMN_WIDTH_STORAGE_KEY, Resizer_default as Resizer, ScrollViewer, SideItemKey, SplitView_default as SplitView, StageCore, Index_default$1 as StyleSetter, CodeEditor_default as TMagicCodeEditor, Editor_default as TMagicEditor, ToolButton_default as ToolButton, Tree_default as Tree, TreeNode_default as TreeNode, UI_SELECT_MODE_EVENT_NAME, UndoRedo, V_GUIDE_LINE_STORAGE_KEY, ViewForm_default as ViewForm, advancedTabConfig, arrayOptions, beforePaste, booleanOptions, buildChangeRecords, calcAlignCenterStyle, calcLayerTargetIndex, calcMoveStyle, canUsePluginMethods, change2Fixed, classifyDragSources, codeBlock_default as codeBlockService, collectEventNameOptionValues, collectRelatedNodes, componentList_default as componentListService, confirmHistoryAction, createStackStep, dataSource_default as dataSourceService, debug, plugin_default as default, defaultIsExpandable, dep_default as depService, describeRevertStep, describeStepForRevert, deserializeStacks, designPlugin, detectStackOpType, detectTargetId, detectTargetName, displayTabConfig, editorNodeMergeCustomizer, editor_default as editorService, editorTypeMatchRules, eqOptions, error, eventTabConfig, events_default as eventsService, fillConfig, fixNodeLeft, fixNodePosition, formPlugin, generatePageName, generatePageNameByApp, getAddParent, getCascaderOptionsFromFields, getCodeBlockFormConfig, getCompActionAllowedValues, getCompActionOptions, getCondOpOptionsByFieldType, getDefaultConfig, getDisplayField, getEditorConfig, getEventNameAllowedValues, getEventNameOptions, getFieldType, getFormConfig, getFormValue, getGuideLineFromCache, getInitPositionStyle, getLastPushedHistoryIds, getNodeIndex, getOrCreateStack, getPageFragmentList, getPageList, getPageNameList, getPositionInContainer, getRelativeStyle, history_default as historyService, idbDelete, idbGet, idbSet, info, isEventNameCheckStrictly, isGlobalFlat, isIncludeDataSource, isIndexedDBSupported, keybinding_default as keybindingService, monaco_editor_default as loadMonaco, log, markStackSaved, mergeSteps, moveItemsInContainer, normalizeCompActionValue, numberOptions, openIndexedDB, props_default as propsService, removeStyleDisplayConfig, resolveFieldByPath, resolveSelectedNode, serializeConfig, serializeStacks, setChildrenLayout, setEditorConfig, setLayout, stageOverlay_default as stageOverlayService, storage_default as storageService, styleTabConfig, tablePlugin, toggleFixedPosition, ui_default as uiService, undoFloor, updateStatus, useCodeBlockEdit, useCompareForm, useEditorContentHeight, useFilter, useFloatBox, useGetSo, useHistoryRevert, useNextFloatBoxPosition, useNodeStatus, useServices, useStage, useWindowRect, warn };
@@ -1,10 +1,9 @@
1
- import { validatePropsForm } from "../../utils/props.js";
2
1
  import { useServices } from "../../hooks/use-services.js";
3
2
  import { useEditorContentHeight } from "../../hooks/use-editor-content-height.js";
4
3
  import Icon_default from "../../components/Icon.js";
5
4
  import CodeEditor_default from "../CodeEditor.js";
6
5
  import { ENABLE_PROPS_FORM_VALIDATE } from "../../editorProps.js";
7
- import { MForm } from "@tmagic/form";
6
+ import { MForm, validateForm } from "@tmagic/form";
8
7
  import { TMagicButton, TMagicScrollbar, tMagicMessage } from "@tmagic/design";
9
8
  import { filterXSS } from "@tmagic/utils";
10
9
  import { computed, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, getCurrentInstance, inject, normalizeClass, onMounted, onUnmounted, openBlock, ref, renderSlot, unref, useTemplateRef, watchEffect, withCtx } from "vue";
@@ -82,14 +81,18 @@ var FormPanel_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
82
81
  return;
83
82
  }
84
83
  try {
85
- const error = await validatePropsForm({
84
+ const error = await validateForm({
86
85
  config: props.config,
87
- values: newValues,
88
- appContext: internalInstance?.appContext ?? null,
89
- services,
90
- stage: stage.value,
91
86
  typeMatchValid: true,
92
- extendState: props.extendState
87
+ initValues: newValues,
88
+ appContext: internalInstance?.appContext ? {
89
+ ...internalInstance?.appContext,
90
+ provides: { services }
91
+ } : null,
92
+ extendState: (state) => {
93
+ if (configFormRef.value?.formState) return { ...configFormRef.value?.formState || {} };
94
+ return props.extendState?.(state) || {};
95
+ }
93
96
  });
94
97
  if (error) tMagicMessage({
95
98
  type: "error",
@@ -72,14 +72,14 @@ var PropsPanel_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
72
72
  ...v,
73
73
  style: {}
74
74
  };
75
- if (v.style) {
75
+ if (v.style) if (eventData) {
76
76
  Object.entries(v.style).forEach(([key, value]) => {
77
77
  if (value !== "" && newValue.style) newValue.style[key] = value;
78
78
  });
79
- eventData?.changeRecords?.forEach((record) => {
79
+ eventData.changeRecords?.forEach((record) => {
80
80
  if (record.propPath?.startsWith("style") && record.value === "") setValueByKeyPath(record.propPath, record.value, newValue);
81
81
  });
82
- }
82
+ } else newValue.style = { ...v.style };
83
83
  const historySource = eventData ? "props" : "code";
84
84
  editorService.update(newValue, {
85
85
  changeRecords: eventData?.changeRecords,
@@ -351,6 +351,11 @@ var Editor = class extends BaseService {
351
351
  historySource,
352
352
  doNotPushHistory
353
353
  });
354
+ const addedPages = newNodes.filter((node) => isPage(node) || isPageFragment(node));
355
+ if (addedPages.length) history_default.notifyPageStructureChange({
356
+ add: addedPages,
357
+ remove: []
358
+ });
354
359
  return Array.isArray(addNode) ? newNodes : newNodes[0];
355
360
  }
356
361
  async doRemove(node, { doNotSelect = false, doNotSwitchPage = false } = {}) {
@@ -454,6 +459,11 @@ var Editor = class extends BaseService {
454
459
  historySource,
455
460
  doNotPushHistory
456
461
  });
462
+ const removedPages = nodes.filter((node) => isPage(node) || isPageFragment(node));
463
+ if (removedPages.length) history_default.notifyPageStructureChange({
464
+ add: [],
465
+ remove: removedPages
466
+ });
457
467
  }
458
468
  async doUpdate(config, { changeRecords = [], historySource } = {}) {
459
469
  if (!this.get("root")) throw new Error("root为空");
@@ -1238,24 +1248,35 @@ var Editor = class extends BaseService {
1238
1248
  const prevMap = new Map(prevPages.map((p) => [`${p.id}`, p]));
1239
1249
  const nextMap = new Map(nextPages.map((p) => [`${p.id}`, p]));
1240
1250
  const indexInItems = (root, id) => (root.items ?? []).findIndex((item) => `${item.id}` === `${id}`);
1251
+ const addedPages = [];
1252
+ const removedPages = [];
1241
1253
  nextPages.forEach((nextPage) => {
1242
1254
  const prevPage = prevMap.get(`${nextPage.id}`);
1243
- if (!prevPage) this.pushPageDiffStep("add", nextPage, {
1244
- newSchema: cloneDeep$1(toRaw(nextPage)),
1245
- parentId: nextRoot.id,
1246
- index: indexInItems(nextRoot, nextPage.id)
1247
- }, source);
1248
- else if (!isEqual(toRaw(prevPage), toRaw(nextPage))) this.pushPageDiffStep("update", nextPage, {
1255
+ if (!prevPage) {
1256
+ this.pushPageDiffStep("add", nextPage, {
1257
+ newSchema: cloneDeep$1(toRaw(nextPage)),
1258
+ parentId: nextRoot.id,
1259
+ index: indexInItems(nextRoot, nextPage.id)
1260
+ }, source);
1261
+ addedPages.push(nextPage);
1262
+ } else if (!isEqual(toRaw(prevPage), toRaw(nextPage))) this.pushPageDiffStep("update", nextPage, {
1249
1263
  oldSchema: cloneDeep$1(toRaw(prevPage)),
1250
1264
  newSchema: cloneDeep$1(toRaw(nextPage))
1251
1265
  }, source);
1252
1266
  });
1253
1267
  prevPages.forEach((prevPage) => {
1254
- if (!nextMap.has(`${prevPage.id}`)) this.pushPageDiffStep("remove", prevPage, {
1255
- oldSchema: cloneDeep$1(toRaw(prevPage)),
1256
- parentId: preRoot.id,
1257
- index: indexInItems(preRoot, prevPage.id)
1258
- }, source);
1268
+ if (!nextMap.has(`${prevPage.id}`)) {
1269
+ this.pushPageDiffStep("remove", prevPage, {
1270
+ oldSchema: cloneDeep$1(toRaw(prevPage)),
1271
+ parentId: preRoot.id,
1272
+ index: indexInItems(preRoot, prevPage.id)
1273
+ }, source);
1274
+ removedPages.push(prevPage);
1275
+ }
1276
+ });
1277
+ if (addedPages.length || removedPages.length) history_default.notifyPageStructureChange({
1278
+ add: addedPages,
1279
+ remove: removedPages
1259
1280
  });
1260
1281
  }
1261
1282
  /**
@@ -244,6 +244,22 @@ var History = class extends BaseService {
244
244
  });
245
245
  }
246
246
  /**
247
+ * 派发「页面 / 页面片结构变更」事件(`page-structure-change`)。
248
+ *
249
+ * 常规 `editorService.add` / `remove` 页面节点不会写入 `page` 历史栈(见 editor.add / remove 中
250
+ * 对 isPage / isPageFragment 的分支),因此不会产生任何 historyService 事件。该方法用于在这些
251
+ * 场景(以及 setRoot 整体替换 DSL 增删页面)下,向外统一通知页面结构的增删变化,供业务方感知。
252
+ *
253
+ * 一次操作涉及多个页面时,调用方应把本次增删的页面**合并为一个 change 一次性传入**,
254
+ * 使一次操作只派发一个事件;`add` / `remove` 分别为本次新增与删除的页面列表(其一可为空数组)。
255
+ *
256
+ * @param change 本次结构变更:{ add: 新增的页面列表, remove: 删除的页面列表 }
257
+ */
258
+ notifyPageStructureChange(change) {
259
+ if (!change.add.length && !change.remove.length) return;
260
+ this.emit("page-structure-change", change);
261
+ }
262
+ /**
247
263
  * 把当前内存中的全部历史栈(页面 / 代码块 / 数据源 / 扩展类型)序列化后写入本地 IndexedDB。
248
264
  *
249
265
  * - 每个 UndoRedo 栈连同其游标、容量一并保存,恢复后可继续 undo/redo;
package/dist/es/style.css CHANGED
@@ -103,6 +103,10 @@
103
103
  width: calc(var(--el-input-width, 100%) - 40px);
104
104
  }
105
105
 
106
+ .tmagic-design-color-picker {
107
+ flex: 0 0 auto;
108
+ }
109
+
106
110
  .m-table .el-button.action-btn + .el-button.action-btn {
107
111
  margin-left: 0;
108
112
  }
@@ -199,12 +199,14 @@ var resolveFieldByPath = (fields, fieldNames, options = {}) => {
199
199
  if (options.skipNumberIndices && isNumber(name)) continue;
200
200
  if (!currentFields.length) return {
201
201
  ok: false,
202
- fields: currentFields
202
+ fields: currentFields,
203
+ failedName: name
203
204
  };
204
205
  field = currentFields.find((item) => item.name === name);
205
206
  if (!field) return {
206
207
  ok: false,
207
- fields: currentFields
208
+ fields: currentFields,
209
+ failedName: name
208
210
  };
209
211
  currentFields = field.fields || [];
210
212
  }
@@ -1,4 +1,3 @@
1
- import { validateForm } from "@tmagic/form";
2
1
  import { tMagicMessage } from "@tmagic/design";
3
2
  import { HookType, NODE_CONDS_KEY, NODE_CONDS_RESULT_KEY, NODE_DISABLE_CODE_BLOCK_KEY, NODE_DISABLE_DATA_SOURCE_KEY } from "@tmagic/core";
4
3
  //#region packages/editor/src/utils/props.ts
@@ -314,48 +313,5 @@ var removeStyleDisplayConfig = (formConfig) => formConfig.map((item) => {
314
313
  })
315
314
  };
316
315
  });
317
- /**
318
- * 对一份「组件属性表单配置 + 值」做一次独立的校验,**不复用也不污染页面上正在展示的表单**。
319
- *
320
- * 内部基于 `@tmagic/form` 的 `validateForm` 另建一个独立的 MForm 实例完成校验,并统一处理
321
- * 编辑器场景所需的上下文注入:将当前组件实例的 provides 合入 appContext,并向 formState 注入
322
- * stage / services 及外部扩展状态,保证校验规则依赖的上下文可用。
323
- *
324
- * 常用于源码编辑器保存后,对最新配置做一次校验,并将校验结果(错误信息)随提交一并抛给上层记录,
325
- * 使源码保存的错误状态与表单编辑保持一致。
326
- *
327
- * @returns 校验通过返回空字符串 `''`,否则返回以 `<br>` 拼接的错误文案。
328
- * 仅在初始化超时或挂载失败等异常情况下才会 reject。
329
- *
330
- * @example
331
- * ```ts
332
- * const error = await validatePropsForm({
333
- * config,
334
- * values,
335
- * appContext: getCurrentInstance()?.appContext,
336
- * services,
337
- * stage: editorService.get('stage'),
338
- * extendState,
339
- * });
340
- * if (error) {
341
- * // 配置不合法,error 为错误文案
342
- * }
343
- * ```
344
- */
345
- var validatePropsForm = ({ config, values, appContext = null, services, stage, extendState, debug, typeMatchValid }) => validateForm({
346
- config,
347
- debug,
348
- typeMatchValid,
349
- initValues: values,
350
- appContext: appContext ? {
351
- ...appContext,
352
- provides: { services }
353
- } : null,
354
- extendState: async (state) => ({
355
- ...await extendState?.(state) || {},
356
- stage,
357
- services
358
- })
359
- });
360
316
  //#endregion
361
- export { advancedTabConfig, arrayOptions, booleanOptions, displayTabConfig, eqOptions, eventTabConfig, fillConfig, getCondOpOptionsByFieldType, numberOptions, removeStyleDisplayConfig, styleTabConfig, validatePropsForm };
317
+ export { advancedTabConfig, arrayOptions, booleanOptions, displayTabConfig, eqOptions, eventTabConfig, fillConfig, getCondOpOptionsByFieldType, numberOptions, removeStyleDisplayConfig, styleTabConfig };
@@ -3,6 +3,7 @@ import editor_default from "../services/editor.js";
3
3
  import { getFieldType, resolveFieldByPath } from "./data-source/index.js";
4
4
  import codeBlock_default from "../services/codeBlock.js";
5
5
  import dataSource_default from "../services/dataSource.js";
6
+ import { validateTypeMatch } from "@tmagic/form";
6
7
  import { appendValidateSuggestion } from "@tmagic/design";
7
8
  import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_SET_DATA_METHOD_NAME, dataSourceTemplateRegExp, getKeysArray, removeDataSourceFieldPrefix } from "@tmagic/utils";
8
9
  import { NodeType } from "@tmagic/core";
@@ -20,7 +21,7 @@ var stringifyExampleValue = (value) => {
20
21
  }
21
22
  return String(value);
22
23
  };
23
- var MAX_SUGGESTION_OPTIONS = 5;
24
+ var MAX_SUGGESTION_OPTIONS = 20;
24
25
  /**
25
26
  * 生成「请使用以下某一个值:xxx;xxx」形式的参考建议;无可选值时返回空字符串(不追加建议)。
26
27
  */
@@ -181,10 +182,10 @@ var validateDataSourceFieldPath = (path, options = {}) => {
181
182
  fieldNames = path.slice(1);
182
183
  }
183
184
  const ds = findDataSource(`${dsId}`);
184
- if (!ds) return defaultMessage(options.message, "值不在可选项中", dataSourceIdSuggestion());
185
+ if (!ds) return defaultMessage(options.message, `数据源(${dsId})不存在`, dataSourceIdSuggestion());
185
186
  if (!fieldNames.length) return;
186
- const { field, ok } = resolveFieldByPath(ds.fields, fieldNames);
187
- if (!ok) return defaultMessage(options.message, "值不在可选项中", dataSourceIdSuggestion());
187
+ const { field, ok, fields, failedName } = resolveFieldByPath(ds.fields, fieldNames);
188
+ if (!ok) return defaultMessage(options.message, `数据源字段(${failedName})不存在`, listSuggestion(fields.map((item) => item.name)));
188
189
  const allowedTypes = options.dataSourceFieldType || ["any"];
189
190
  if (!allowedTypes.length || allowedTypes.includes("any")) return;
190
191
  const leafType = field?.type || "any";
@@ -267,9 +268,15 @@ var isDataSourceFieldPathValue = (value, config) => {
267
268
  if (config.value === "key") return true;
268
269
  return `${value[0]}`.startsWith(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX);
269
270
  };
270
- var validateDataSourceFieldSelect = (value, { message, props }) => {
271
+ var validateDataSourceFieldSelect = (value, { mForm, message, props }) => {
271
272
  const config = props.config || {};
272
- if (config.fieldConfig && !isDataSourceFieldPathValue(value, config)) return;
273
+ if (config.fieldConfig && !isDataSourceFieldPathValue(value, config)) return validateTypeMatch(value, mForm, {
274
+ ...props,
275
+ config: {
276
+ name: config.name,
277
+ ...config.fieldConfig
278
+ }
279
+ }, message);
273
280
  if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) return defaultMessage(message, `${value}类型应为字符串数组`, dataSourceFieldPathSuggestion());
274
281
  return validateDataSourceFieldPath(value, {
275
282
  dataSourceId: config.dataSourceId,
package/dist/style.css CHANGED
@@ -103,6 +103,10 @@
103
103
  width: calc(var(--el-input-width, 100%) - 40px);
104
104
  }
105
105
 
106
+ .tmagic-design-color-picker {
107
+ flex: 0 0 auto;
108
+ }
109
+
106
110
  .m-table .el-button.action-btn + .el-button.action-btn {
107
111
  margin-left: 0;
108
112
  }
@@ -103,6 +103,10 @@
103
103
  width: calc(var(--el-input-width, 100%) - 40px);
104
104
  }
105
105
 
106
+ .tmagic-design-color-picker {
107
+ flex: 0 0 auto;
108
+ }
109
+
106
110
  .m-form.m-form--magic-admin .el-collapse-item__header {
107
111
  background-color: transparent;
108
112
  padding: 0;