@tmagic/editor 1.8.0-manmanyu.21 → 1.8.0-manmanyu.22

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 (31) hide show
  1. package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +4 -0
  2. package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +56 -13
  3. package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +7 -0
  4. package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +4 -0
  5. package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +6 -3
  6. package/dist/es/layouts/props-panel/use-style-panel.js +3 -2
  7. package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +3 -0
  8. package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +4 -0
  9. package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +8 -2
  10. package/dist/es/services/ui.js +3 -0
  11. package/dist/es/style.css +9 -1
  12. package/dist/es/utils/const.js +1 -1
  13. package/dist/style.css +9 -1
  14. package/dist/themes/magic-admin.css +32 -13
  15. package/dist/tmagic-editor.umd.cjs +98 -19
  16. package/package.json +7 -7
  17. package/src/components/CodeBlockEditor.vue +3 -0
  18. package/src/components/FloatingBox.vue +71 -7
  19. package/src/fields/DataSourceFields.vue +5 -0
  20. package/src/fields/DataSourceMocks.vue +3 -0
  21. package/src/layouts/Framework.vue +7 -6
  22. package/src/layouts/props-panel/use-style-panel.ts +4 -3
  23. package/src/layouts/sidebar/Sidebar.vue +2 -0
  24. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +3 -0
  25. package/src/layouts/workspace/viewer/NodeListMenu.vue +4 -1
  26. package/src/services/ui.ts +6 -0
  27. package/src/theme/floating-box.scss +9 -1
  28. package/src/theme/themes/magic-admin/index.scss +31 -18
  29. package/src/type.ts +6 -0
  30. package/src/utils/const.ts +2 -2
  31. package/types/index.d.ts +13 -2
@@ -8182,7 +8182,7 @@
8182
8182
  var PROPS_PANEL_WIDTH_STORAGE_KEY = "$MagicEditorPropsPanelWidthData";
8183
8183
  var DEFAULT_LEFT_COLUMN_WIDTH = 310;
8184
8184
  var DEFAULT_RIGHT_COLUMN_WIDTH = 480;
8185
- var MIN_LEFT_COLUMN_WIDTH = 252;
8185
+ var MIN_LEFT_COLUMN_WIDTH = 260;
8186
8186
  var MIN_CENTER_COLUMN_WIDTH = 400;
8187
8187
  var MIN_RIGHT_COLUMN_WIDTH = 300;
8188
8188
  var H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
@@ -8207,6 +8207,9 @@
8207
8207
  center: 0,
8208
8208
  right: storage_default.getItem("$MagicEditorRightColumnWidthData", { protocol: Protocol.NUMBER }) || 480
8209
8209
  },
8210
+ minLeftColumnWidth: 260,
8211
+ minCenterColumnWidth: 400,
8212
+ minRightColumnWidth: 300,
8210
8213
  showGuides: true,
8211
8214
  hasGuides: false,
8212
8215
  showRule: true,
@@ -10360,6 +10363,9 @@
10360
10363
  const pageLength = (0, vue.computed)(() => editorService.get("pageLength") || 0);
10361
10364
  const showSrc = (0, vue.computed)(() => uiService.get("showSrc"));
10362
10365
  const columnWidth = (0, vue.computed)(() => uiService.get("columnWidth"));
10366
+ const minLeftColumnWidth = (0, vue.computed)(() => uiService.get("minLeftColumnWidth"));
10367
+ const minCenterColumnWidth = (0, vue.computed)(() => uiService.get("minCenterColumnWidth"));
10368
+ const minRightColumnWidth = (0, vue.computed)(() => uiService.get("minRightColumnWidth"));
10363
10369
  (0, vue.watch)(pageLength, () => {
10364
10370
  splitViewRef.value?.updateWidth();
10365
10371
  });
@@ -10426,9 +10432,9 @@
10426
10432
  "right-class": "m-editor-framework-right",
10427
10433
  left: __props.hideSidebar ? void 0 : columnWidth.value.left,
10428
10434
  right: columnWidth.value.right,
10429
- "min-left": __props.hideSidebar ? 0 : (0, vue.unref)(252),
10430
- "min-right": (0, vue.unref)(300),
10431
- "min-center": (0, vue.unref)(400),
10435
+ "min-left": __props.hideSidebar ? 0 : minLeftColumnWidth.value,
10436
+ "min-right": minRightColumnWidth.value,
10437
+ "min-center": minCenterColumnWidth.value,
10432
10438
  width: frameworkRect.value.width,
10433
10439
  onChange: columnWidthChange
10434
10440
  }, (0, vue.createSlots)({
@@ -12949,8 +12955,9 @@
12949
12955
  columnWidth.center += propsPanelWidth.value;
12950
12956
  }
12951
12957
  if (columnWidth.center < 0) {
12952
- columnWidth.right = columnWidth.right + columnWidth.center - 400;
12953
- columnWidth.center = 400;
12958
+ const minCenterColumnWidth = uiService.get("minCenterColumnWidth");
12959
+ columnWidth.right = columnWidth.right + columnWidth.center - minCenterColumnWidth;
12960
+ columnWidth.center = minCenterColumnWidth;
12954
12961
  propsPanelWidth.value = columnWidth.right / 2;
12955
12962
  }
12956
12963
  storageService.setItem(RIGHT_COLUMN_WIDTH_STORAGE_KEY, columnWidth.right, { protocol: Protocol.NUMBER });
@@ -13160,6 +13167,9 @@
13160
13167
  top: 0
13161
13168
  }) },
13162
13169
  title: { default: "" },
13170
+ bodyStyle: {},
13171
+ initialStyle: { default: () => ({}) },
13172
+ frameworkWidth: { default: 0 },
13163
13173
  beforeClose: {}
13164
13174
  }, {
13165
13175
  "width": { default: 0 },
@@ -13197,19 +13207,51 @@
13197
13207
  if (targetEl.value) return targetEl.value.clientHeight - titleHeight.value;
13198
13208
  return "auto";
13199
13209
  });
13200
- const { uiService } = useServices();
13201
- const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect").width || 0);
13202
13210
  const style = (0, vue.computed)(() => {
13203
13211
  let { left } = props.position;
13204
- if (width.value) left = left + width.value > frameworkWidth.value ? frameworkWidth.value - width.value : left;
13212
+ const frameworkWidth = props.frameworkWidth || globalThis.window?.innerWidth || 0;
13213
+ if (width.value && frameworkWidth) left = left + width.value > frameworkWidth ? frameworkWidth - width.value : left;
13205
13214
  return {
13206
13215
  left: `${left}px`,
13207
13216
  top: `${props.position.top}px`,
13208
13217
  width: width.value ? `${width.value}px` : "auto",
13209
- height: height.value ? `${height.value}px` : "auto"
13218
+ height: height.value ? `${height.value}px` : "auto",
13219
+ ...props.initialStyle
13210
13220
  };
13211
13221
  });
13212
13222
  let moveable$1 = null;
13223
+ let dragMask = null;
13224
+ let dragMaskVisible = false;
13225
+ const bindDragMaskSafety = () => {
13226
+ globalThis.window?.addEventListener("pointerup", hideDragMask, true);
13227
+ globalThis.window?.addEventListener("blur", hideDragMask);
13228
+ globalThis.document?.addEventListener("visibilitychange", hideDragMask);
13229
+ };
13230
+ const unbindDragMaskSafety = () => {
13231
+ globalThis.window?.removeEventListener("pointerup", hideDragMask, true);
13232
+ globalThis.window?.removeEventListener("blur", hideDragMask);
13233
+ globalThis.document?.removeEventListener("visibilitychange", hideDragMask);
13234
+ };
13235
+ const showDragMask = () => {
13236
+ if (dragMaskVisible) return;
13237
+ if (!dragMask) {
13238
+ dragMask = globalThis.document.createElement("div");
13239
+ dragMask.className = "m-editor-float-box-drag-mask";
13240
+ }
13241
+ globalThis.document.body.appendChild(dragMask);
13242
+ dragMaskVisible = true;
13243
+ bindDragMaskSafety();
13244
+ const setMaskZIndex = () => {
13245
+ if (dragMask) dragMask.style.zIndex = `${curZIndex.value + 1}`;
13246
+ };
13247
+ setMaskZIndex();
13248
+ (0, vue.nextTick)(setMaskZIndex);
13249
+ };
13250
+ const hideDragMask = () => {
13251
+ unbindDragMaskSafety();
13252
+ dragMask?.parentNode?.removeChild(dragMask);
13253
+ dragMaskVisible = false;
13254
+ };
13213
13255
  const initMoveable = () => {
13214
13256
  moveable$1 = new moveable.default(globalThis.document.body, {
13215
13257
  className: "m-editor-floating-box-moveable",
@@ -13232,6 +13274,10 @@
13232
13274
  position: "css"
13233
13275
  }
13234
13276
  });
13277
+ moveable$1.on("drag", showDragMask);
13278
+ moveable$1.on("resize", showDragMask);
13279
+ moveable$1.on("dragEnd", hideDragMask);
13280
+ moveable$1.on("resizeEnd", hideDragMask);
13235
13281
  moveable$1.on("drag", (e) => {
13236
13282
  e.target.style.transform = e.transform;
13237
13283
  });
@@ -13244,6 +13290,7 @@
13244
13290
  });
13245
13291
  };
13246
13292
  const destroyMoveable = () => {
13293
+ hideDragMask();
13247
13294
  moveable$1?.destroy();
13248
13295
  moveable$1 = null;
13249
13296
  };
@@ -13283,15 +13330,16 @@
13283
13330
  return visible.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(vue.Teleport, {
13284
13331
  key: 0,
13285
13332
  to: "body"
13286
- }, [(0, vue.createElementVNode)("div", {
13333
+ }, [(0, vue.createElementVNode)("div", (0, vue.mergeProps)({
13287
13334
  ref: "target",
13288
- class: (0, vue.normalizeClass)(["m-editor-float-box", (0, vue.unref)(themeClass)]),
13289
- style: (0, vue.normalizeStyle)({
13335
+ class: ["m-editor-float-box", (0, vue.unref)(themeClass)]
13336
+ }, _ctx.$attrs, {
13337
+ style: {
13290
13338
  ...style.value,
13291
13339
  zIndex: curZIndex.value
13292
- }),
13340
+ },
13293
13341
  onMousedown: nextZIndex
13294
- }, [(0, vue.createElementVNode)("div", _hoisted_1$56, [(0, vue.renderSlot)(_ctx.$slots, "title", {}, () => [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.title), 1)]), (0, vue.createElementVNode)("div", null, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
13342
+ }), [(0, vue.createElementVNode)("div", _hoisted_1$56, [(0, vue.renderSlot)(_ctx.$slots, "title", {}, () => [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(__props.title), 1)]), (0, vue.createElementVNode)("div", null, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
13295
13343
  link: "",
13296
13344
  size: "small",
13297
13345
  onClick: closeHandler
@@ -13300,8 +13348,11 @@
13300
13348
  _: 1
13301
13349
  })])], 512), (0, vue.createElementVNode)("div", {
13302
13350
  class: "m-editor-float-box-body",
13303
- style: (0, vue.normalizeStyle)({ height: `${bodyHeight.value}px` })
13304
- }, [(0, vue.renderSlot)(_ctx.$slots, "body")], 4)], 38)])) : (0, vue.createCommentVNode)("v-if", true);
13351
+ style: (0, vue.normalizeStyle)({
13352
+ height: `${bodyHeight.value}px`,
13353
+ ...__props.bodyStyle
13354
+ })
13355
+ }, [(0, vue.renderSlot)(_ctx.$slots, "body")], 4)], 16)])) : (0, vue.createCommentVNode)("v-if", true);
13305
13356
  };
13306
13357
  }
13307
13358
  });
@@ -13423,6 +13474,7 @@
13423
13474
  changedValue.value = void 0;
13424
13475
  };
13425
13476
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, (0, vue.inject)("parentFloating", (0, vue.ref)(null)));
13477
+ const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect")?.width || 0);
13426
13478
  (0, vue.watch)(boxVisible, (visible) => {
13427
13479
  (0, vue.nextTick)(() => {
13428
13480
  if (!visible) emit("close");
@@ -13448,7 +13500,9 @@
13448
13500
  "onUpdate:width": _cache[2] || (_cache[2] = ($event) => width.value = $event),
13449
13501
  height: (0, vue.unref)(codeBlockEditorHeight),
13450
13502
  "onUpdate:height": _cache[3] || (_cache[3] = ($event) => (0, vue.isRef)(codeBlockEditorHeight) ? codeBlockEditorHeight.value = $event : null),
13503
+ "body-style": { padding: "0 16px" },
13451
13504
  title: __props.content.name ? `${__props.disabled ? "查看" : "编辑"}${__props.content.name}` : "新增代码",
13505
+ "framework-width": frameworkWidth.value,
13452
13506
  position: (0, vue.unref)(boxPosition),
13453
13507
  "before-close": beforeClose
13454
13508
  }, {
@@ -13490,6 +13544,7 @@
13490
13544
  "width",
13491
13545
  "height",
13492
13546
  "title",
13547
+ "framework-width",
13493
13548
  "position"
13494
13549
  ]),
13495
13550
  ((0, vue.openBlock)(), (0, vue.createBlock)(vue.Teleport, { to: "body" }, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicDialog), {
@@ -14377,6 +14432,7 @@
14377
14432
  const dataSourceConfig = (0, vue.ref)([]);
14378
14433
  const { height: editorHeight } = useEditorContentHeight();
14379
14434
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, (0, vue.inject)("parentFloating", (0, vue.ref)(null)));
14435
+ const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect")?.width || 0);
14380
14436
  /** 供「方法定义」tab 内的字段消费,用于打开数据源详情后自动打开指定方法 */
14381
14437
  (0, vue.provide)("editingDataSourceMethodName", (0, vue.computed)(() => props.editMethodName));
14382
14438
  /** 供「数据定义」tab 内的字段消费,用于打开数据源详情后自动打开指定字段 */
@@ -14415,6 +14471,7 @@
14415
14471
  });
14416
14472
  return (_ctx, _cache) => {
14417
14473
  return (0, vue.openBlock)(), (0, vue.createBlock)(FloatingBox_default, {
14474
+ "body-style": { padding: "0 16px" },
14418
14475
  visible: boxVisible.value,
14419
14476
  "onUpdate:visible": _cache[0] || (_cache[0] = ($event) => boxVisible.value = $event),
14420
14477
  width: width.value,
@@ -14422,6 +14479,7 @@
14422
14479
  height: (0, vue.unref)(editorHeight),
14423
14480
  "onUpdate:height": _cache[2] || (_cache[2] = ($event) => (0, vue.isRef)(editorHeight) ? editorHeight.value = $event : null),
14424
14481
  title: __props.title,
14482
+ "framework-width": frameworkWidth.value,
14425
14483
  position: (0, vue.unref)(boxPosition)
14426
14484
  }, {
14427
14485
  body: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_form.MFormBox), {
@@ -14445,6 +14503,7 @@
14445
14503
  "width",
14446
14504
  "height",
14447
14505
  "title",
14506
+ "framework-width",
14448
14507
  "position"
14449
14508
  ]);
14450
14509
  };
@@ -15774,6 +15833,7 @@
15774
15833
  const taskLength = (0, vue.computed)(() => depService.get("taskLength"));
15775
15834
  const tipsBarVisible = (0, vue.ref)(true);
15776
15835
  const columnLeftWidth = (0, vue.computed)(() => uiService.get("columnWidth")[ColumnLayout.LEFT]);
15836
+ const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect")?.width || 0);
15777
15837
  const { height: editorContentHeight } = useEditorContentHeight();
15778
15838
  const columnLeftHeight = (0, vue.ref)(0);
15779
15839
  const unWatchEditorContentHeight = (0, vue.watch)(editorContentHeight, (height) => {
@@ -16014,6 +16074,7 @@
16014
16074
  "onUpdate:height": _cache[2] || (_cache[2] = ($event) => columnLeftHeight.value = $event),
16015
16075
  width: columnLeftWidth.value,
16016
16076
  title: config.text,
16077
+ "framework-width": frameworkWidth.value,
16017
16078
  position: {
16018
16079
  left: (0, vue.unref)(floatBoxStates)[config.$key].left,
16019
16080
  top: (0, vue.unref)(floatBoxStates)[config.$key].top
@@ -16030,6 +16091,7 @@
16030
16091
  "height",
16031
16092
  "width",
16032
16093
  "title",
16094
+ "framework-width",
16033
16095
  "position"
16034
16096
  ])) : (0, vue.createCommentVNode)("v-if", true)], 64);
16035
16097
  }), 256))]))], 64);
@@ -16219,7 +16281,8 @@
16219
16281
  __name: "NodeListMenu",
16220
16282
  setup(__props) {
16221
16283
  const services = useServices();
16222
- const { editorService } = services;
16284
+ const { editorService, uiService } = services;
16285
+ const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect")?.width || 0);
16223
16286
  const visible = (0, vue.ref)(false);
16224
16287
  const buttonVisible = (0, vue.ref)(false);
16225
16288
  const buttonEl = (0, vue.useTemplateRef)("button");
@@ -16279,6 +16342,7 @@
16279
16342
  visible: visible.value,
16280
16343
  "onUpdate:visible": _cache[1] || (_cache[1] = ($event) => visible.value = $event),
16281
16344
  title: "当前位置下的组件",
16345
+ "framework-width": frameworkWidth.value,
16282
16346
  position: menuPosition.value
16283
16347
  }, {
16284
16348
  body: (0, vue.withCtx)(() => [(0, vue.createVNode)(Tree_default, {
@@ -16288,7 +16352,11 @@
16288
16352
  onNodeClick: clickHandler
16289
16353
  }, null, 8, ["data", "node-status-map"])]),
16290
16354
  _: 1
16291
- }, 8, ["visible", "position"])) : (0, vue.createCommentVNode)("v-if", true)], 64);
16355
+ }, 8, [
16356
+ "visible",
16357
+ "framework-width",
16358
+ "position"
16359
+ ])) : (0, vue.createCommentVNode)("v-if", true)], 64);
16292
16360
  };
16293
16361
  }
16294
16362
  });
@@ -19924,6 +19992,7 @@
19924
19992
  const addFromJsonDialogVisible = (0, vue.useModel)(__props, "visible1");
19925
19993
  const { height: editorHeight } = useEditorContentHeight();
19926
19994
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, (0, vue.inject)("parentFloating", (0, vue.ref)(null)));
19995
+ const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect")?.width || 0);
19927
19996
  /**
19928
19997
  * 由 DataSourceConfigPanel 注入:打开数据源详情后需要直接打开的字段路径(字段名数组)。
19929
19998
  * 当前层消费 path[0],并把剩余路径下发给嵌套字段,实现逐层打开。
@@ -19964,6 +20033,7 @@
19964
20033
  _: 1
19965
20034
  }, 8, ["disabled"])])) : (0, vue.createCommentVNode)("v-if", true),
19966
20035
  (0, vue.createVNode)(FloatingBox_default, {
20036
+ "body-style": { padding: "0 16px" },
19967
20037
  visible: addDialogVisible.value,
19968
20038
  "onUpdate:visible": _cache[2] || (_cache[2] = ($event) => addDialogVisible.value = $event),
19969
20039
  width: width.value,
@@ -19971,6 +20041,7 @@
19971
20041
  height: (0, vue.unref)(editorHeight),
19972
20042
  "onUpdate:height": _cache[4] || (_cache[4] = ($event) => (0, vue.isRef)(editorHeight) ? editorHeight.value = $event : null),
19973
20043
  title: fieldTitle.value,
20044
+ "framework-width": frameworkWidth.value,
19974
20045
  position: (0, vue.unref)(boxPosition)
19975
20046
  }, {
19976
20047
  body: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_form.MFormBox), {
@@ -19993,9 +20064,11 @@
19993
20064
  "width",
19994
20065
  "height",
19995
20066
  "title",
20067
+ "framework-width",
19996
20068
  "position"
19997
20069
  ]),
19998
20070
  (0, vue.createVNode)(FloatingBox_default, {
20071
+ "body-style": { padding: "0 16px" },
19999
20072
  visible: addFromJsonDialogVisible.value,
20000
20073
  "onUpdate:visible": _cache[5] || (_cache[5] = ($event) => addFromJsonDialogVisible.value = $event),
20001
20074
  width: width.value,
@@ -20003,6 +20076,7 @@
20003
20076
  height: (0, vue.unref)(editorHeight),
20004
20077
  "onUpdate:height": _cache[7] || (_cache[7] = ($event) => (0, vue.isRef)(editorHeight) ? editorHeight.value = $event : null),
20005
20078
  title: "快速添加数据定义",
20079
+ "framework-width": frameworkWidth.value,
20006
20080
  position: (0, vue.unref)(boxPosition)
20007
20081
  }, {
20008
20082
  body: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_form.MFormBox), {
@@ -20016,6 +20090,7 @@
20016
20090
  "visible",
20017
20091
  "width",
20018
20092
  "height",
20093
+ "framework-width",
20019
20094
  "position"
20020
20095
  ])
20021
20096
  ]);
@@ -20235,6 +20310,7 @@
20235
20310
  const addDialogVisible = (0, vue.useModel)(__props, "visible");
20236
20311
  const { height: editorHeight } = useEditorContentHeight();
20237
20312
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, (0, vue.inject)("parentFloating", (0, vue.ref)(null)));
20313
+ const frameworkWidth = (0, vue.computed)(() => uiService.get("frameworkRect")?.width || 0);
20238
20314
  return (_ctx, _cache) => {
20239
20315
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$40, [
20240
20316
  (0, vue.createVNode)((0, vue.unref)(_tmagic_table.MagicTable), {
@@ -20252,6 +20328,7 @@
20252
20328
  _: 1
20253
20329
  }, 8, ["disabled"])])) : (0, vue.createCommentVNode)("v-if", true),
20254
20330
  (0, vue.createVNode)(FloatingBox_default, {
20331
+ "body-style": { padding: "0 16px" },
20255
20332
  visible: addDialogVisible.value,
20256
20333
  "onUpdate:visible": _cache[1] || (_cache[1] = ($event) => addDialogVisible.value = $event),
20257
20334
  width: width.value,
@@ -20259,6 +20336,7 @@
20259
20336
  height: (0, vue.unref)(editorHeight),
20260
20337
  "onUpdate:height": _cache[3] || (_cache[3] = ($event) => (0, vue.isRef)(editorHeight) ? editorHeight.value = $event : null),
20261
20338
  title: drawerTitle.value,
20339
+ "framework-width": frameworkWidth.value,
20262
20340
  position: (0, vue.unref)(boxPosition)
20263
20341
  }, {
20264
20342
  body: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_form.MFormBox), {
@@ -20279,6 +20357,7 @@
20279
20357
  "width",
20280
20358
  "height",
20281
20359
  "title",
20360
+ "framework-width",
20282
20361
  "position"
20283
20362
  ])
20284
20363
  ]);
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0-manmanyu.21",
2
+ "version": "1.8.0-manmanyu.22",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -58,11 +58,11 @@
58
58
  "moveable": "^0.53.0",
59
59
  "serialize-javascript": "^7.0.0",
60
60
  "sortablejs": "^1.15.6",
61
- "@tmagic/design": "1.8.0-manmanyu.21",
62
- "@tmagic/table": "1.8.0-manmanyu.21",
63
- "@tmagic/form": "1.8.0-manmanyu.21",
64
- "@tmagic/utils": "1.8.0-manmanyu.21",
65
- "@tmagic/stage": "1.8.0-manmanyu.21"
61
+ "@tmagic/form": "1.8.0-manmanyu.22",
62
+ "@tmagic/table": "1.8.0-manmanyu.22",
63
+ "@tmagic/stage": "1.8.0-manmanyu.22",
64
+ "@tmagic/utils": "1.8.0-manmanyu.22",
65
+ "@tmagic/design": "1.8.0-manmanyu.22"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/events": "^3.0.3",
@@ -76,7 +76,7 @@
76
76
  "type-fest": "^5.2.0",
77
77
  "typescript": "^6.0.3",
78
78
  "vue": "^3.5.38",
79
- "@tmagic/core": "1.8.0-manmanyu.21"
79
+ "@tmagic/core": "1.8.0-manmanyu.22"
80
80
  },
81
81
  "peerDependenciesMeta": {
82
82
  "typescript": {
@@ -4,7 +4,9 @@
4
4
  v-model:visible="boxVisible"
5
5
  v-model:width="width"
6
6
  v-model:height="codeBlockEditorHeight"
7
+ :body-style="{ padding: '0 16px' }"
7
8
  :title="content.name ? `${disabled ? '查看' : '编辑'}${content.name}` : '新增代码'"
9
+ :framework-width="frameworkWidth"
8
10
  :position="boxPosition"
9
11
  :before-close="beforeClose"
10
12
  >
@@ -206,6 +208,7 @@ const closedHandler = () => {
206
208
 
207
209
  const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
208
210
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
211
+ const frameworkWidth = computed(() => uiService.get('frameworkRect')?.width || 0);
209
212
 
210
213
  watch(boxVisible, (visible) => {
211
214
  nextTick(() => {
@@ -3,6 +3,7 @@
3
3
  <div
4
4
  ref="target"
5
5
  :class="['m-editor-float-box', themeClass]"
6
+ v-bind="$attrs"
6
7
  :style="{ ...style, zIndex: curZIndex }"
7
8
  @mousedown="nextZIndex"
8
9
  >
@@ -14,7 +15,7 @@
14
15
  <TMagicButton link size="small" @click="closeHandler"><MIcon :icon="Close"></MIcon></TMagicButton>
15
16
  </div>
16
17
  </div>
17
- <div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px` }">
18
+ <div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px`, ...bodyStyle }">
18
19
  <slot name="body"></slot>
19
20
  </div>
20
21
  </div>
@@ -22,14 +23,13 @@
22
23
  </template>
23
24
 
24
25
  <script setup lang="ts">
25
- import { computed, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
26
+ import { computed, type CSSProperties, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
26
27
  import { Close } from '@element-plus/icons-vue';
27
28
  import VanillaMoveable from 'moveable';
28
29
 
29
30
  import { TMagicButton, useThemeClass, useZIndex } from '@tmagic/design';
30
31
 
31
32
  import MIcon from '@editor/components/Icon.vue';
32
- import { useServices } from '@editor/hooks/use-services';
33
33
 
34
34
  interface Position {
35
35
  left: number;
@@ -44,11 +44,18 @@ const props = withDefaults(
44
44
  defineProps<{
45
45
  position?: Position;
46
46
  title?: string;
47
+ bodyStyle?: CSSProperties;
48
+ /** 浮窗初始样式,会与内部计算样式合并,外部传入优先 */
49
+ initialStyle?: CSSProperties;
50
+ /** 用于约束浮窗 left 的容器宽度,传入时按宽度收敛 left,避免超出右边界;默认取视窗宽度 */
51
+ frameworkWidth?: number;
47
52
  beforeClose?: (_done: (_cancel?: boolean) => void) => void;
48
53
  }>(),
49
54
  {
50
55
  title: '',
51
56
  position: () => ({ left: 0, top: 0 }),
57
+ initialStyle: () => ({}),
58
+ frameworkWidth: 0,
52
59
  },
53
60
  );
54
61
 
@@ -77,12 +84,11 @@ const bodyHeight = computed(() => {
77
84
  return 'auto';
78
85
  });
79
86
 
80
- const { uiService } = useServices();
81
- const frameworkWidth = computed(() => uiService.get('frameworkRect').width || 0);
82
87
  const style = computed(() => {
83
88
  let { left } = props.position;
84
- if (width.value) {
85
- left = left + width.value > frameworkWidth.value ? frameworkWidth.value - width.value : left;
89
+ const frameworkWidth = props.frameworkWidth || globalThis.window?.innerWidth || 0;
90
+ if (width.value && frameworkWidth) {
91
+ left = left + width.value > frameworkWidth ? frameworkWidth - width.value : left;
86
92
  }
87
93
 
88
94
  return {
@@ -90,11 +96,60 @@ const style = computed(() => {
90
96
  top: `${props.position.top}px`,
91
97
  width: width.value ? `${width.value}px` : 'auto',
92
98
  height: height.value ? `${height.value}px` : 'auto',
99
+ ...props.initialStyle,
93
100
  };
94
101
  });
95
102
 
96
103
  let moveable: VanillaMoveable | null = null;
97
104
 
105
+ // 拖拽/缩放时用于覆盖 iframe 的遮罩,防止鼠标进入 iframe 区域后事件被 iframe 吞掉导致拖拽丢失
106
+ let dragMask: HTMLDivElement | null = null;
107
+ let dragMaskVisible = false;
108
+
109
+ // 兜底:正常情况下遮罩由 moveable 的 dragEnd/resizeEnd 移除;但某些极端场景
110
+ // (拖拽中鼠标移出窗口后松开、alt-tab 切走窗口失焦、标签页被隐藏等)结束事件不会触发,
111
+ // 会导致全屏透明遮罩残留、整个编辑器无法点击。这里挂全局 pointerup/blur/visibilitychange 强制收尾。
112
+ const bindDragMaskSafety = () => {
113
+ globalThis.window?.addEventListener('pointerup', hideDragMask, true);
114
+ globalThis.window?.addEventListener('blur', hideDragMask);
115
+ globalThis.document?.addEventListener('visibilitychange', hideDragMask);
116
+ };
117
+
118
+ const unbindDragMaskSafety = () => {
119
+ globalThis.window?.removeEventListener('pointerup', hideDragMask, true);
120
+ globalThis.window?.removeEventListener('blur', hideDragMask);
121
+ globalThis.document?.removeEventListener('visibilitychange', hideDragMask);
122
+ };
123
+
124
+ const showDragMask = () => {
125
+ if (dragMaskVisible) {
126
+ return;
127
+ }
128
+ if (!dragMask) {
129
+ dragMask = globalThis.document.createElement('div');
130
+ dragMask.className = 'm-editor-float-box-drag-mask';
131
+ }
132
+ globalThis.document.body.appendChild(dragMask);
133
+ dragMaskVisible = true;
134
+ bindDragMaskSafety();
135
+
136
+ // 拖拽标题时,root 上的 @mousedown="nextZIndex" 会把浮窗 z-index 抬高,
137
+ // 若此时才读取会拿到旧值导致遮罩被浮窗(及其内部 iframe)盖住,故用 nextTick 在 z-index 稳定后再设置到浮窗之上
138
+ const setMaskZIndex = () => {
139
+ if (dragMask) {
140
+ dragMask.style.zIndex = `${curZIndex.value + 1}`;
141
+ }
142
+ };
143
+ setMaskZIndex();
144
+ nextTick(setMaskZIndex);
145
+ };
146
+
147
+ const hideDragMask = () => {
148
+ unbindDragMaskSafety();
149
+ dragMask?.parentNode?.removeChild(dragMask);
150
+ dragMaskVisible = false;
151
+ };
152
+
98
153
  const initMoveable = () => {
99
154
  moveable = new VanillaMoveable(globalThis.document.body, {
100
155
  className: 'm-editor-floating-box-moveable',
@@ -112,6 +167,14 @@ const initMoveable = () => {
112
167
  bounds: { left: 0, top: 0, right: 0, bottom: 0, position: 'css' },
113
168
  });
114
169
 
170
+ // 仅在真正发生拖拽/缩放位移时插入遮罩:moveable 的 dragStart/resizeStart 在 mousedown 时即触发,
171
+ // 若此时就盖遮罩,会盖住浮窗本身导致 mouseup 落在遮罩上、关闭按钮的 click 无法触发(点击关闭不了)。
172
+ // 改为在 drag/resize(实际位移)时才显示,纯点击不再触发遮罩。
173
+ moveable.on('drag', showDragMask);
174
+ moveable.on('resize', showDragMask);
175
+ moveable.on('dragEnd', hideDragMask);
176
+ moveable.on('resizeEnd', hideDragMask);
177
+
115
178
  moveable.on('drag', (e) => {
116
179
  e.target.style.transform = e.transform;
117
180
  });
@@ -126,6 +189,7 @@ const initMoveable = () => {
126
189
  };
127
190
 
128
191
  const destroyMoveable = () => {
192
+ hideDragMask();
129
193
  moveable?.destroy();
130
194
  moveable = null;
131
195
  };
@@ -8,10 +8,12 @@
8
8
  </div>
9
9
 
10
10
  <FloatingBox
11
+ :body-style="{ padding: '0 16px' }"
11
12
  v-model:visible="addDialogVisible"
12
13
  v-model:width="width"
13
14
  v-model:height="editorHeight"
14
15
  :title="fieldTitle"
16
+ :framework-width="frameworkWidth"
15
17
  :position="boxPosition"
16
18
  >
17
19
  <template #body>
@@ -28,10 +30,12 @@
28
30
  </FloatingBox>
29
31
 
30
32
  <FloatingBox
33
+ :body-style="{ padding: '0 16px' }"
31
34
  v-model:visible="addFromJsonDialogVisible"
32
35
  v-model:width="width"
33
36
  v-model:height="editorHeight"
34
37
  title="快速添加数据定义"
38
+ :framework-width="frameworkWidth"
35
39
  :position="boxPosition"
36
40
  >
37
41
  <template #body>
@@ -358,6 +362,7 @@ const { height: editorHeight } = useEditorContentHeight();
358
362
 
359
363
  const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
360
364
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
365
+ const frameworkWidth = computed(() => uiService.get('frameworkRect')?.width || 0);
361
366
 
362
367
  /**
363
368
  * 由 DataSourceConfigPanel 注入:打开数据源详情后需要直接打开的字段路径(字段名数组)。
@@ -7,10 +7,12 @@
7
7
  </div>
8
8
 
9
9
  <FloatingBox
10
+ :body-style="{ padding: '0 16px' }"
10
11
  v-model:visible="addDialogVisible"
11
12
  v-model:width="width"
12
13
  v-model:height="editorHeight"
13
14
  :title="drawerTitle"
15
+ :framework-width="frameworkWidth"
14
16
  :position="boxPosition"
15
17
  >
16
18
  <template #body>
@@ -254,4 +256,5 @@ const addDialogVisible = defineModel<boolean>('visible', { default: false });
254
256
  const { height: editorHeight } = useEditorContentHeight();
255
257
  const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
256
258
  const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
259
+ const frameworkWidth = computed(() => uiService.get('frameworkRect')?.width || 0);
257
260
  </script>
@@ -29,9 +29,9 @@
29
29
  right-class="m-editor-framework-right"
30
30
  :left="hideSidebar ? undefined : columnWidth.left"
31
31
  :right="columnWidth.right"
32
- :min-left="hideSidebar ? 0 : MIN_LEFT_COLUMN_WIDTH"
33
- :min-right="MIN_RIGHT_COLUMN_WIDTH"
34
- :min-center="MIN_CENTER_COLUMN_WIDTH"
32
+ :min-left="hideSidebar ? 0 : minLeftColumnWidth"
33
+ :min-right="minRightColumnWidth"
34
+ :min-center="minCenterColumnWidth"
35
35
  :width="frameworkRect.width"
36
36
  @change="columnWidthChange"
37
37
  >
@@ -82,9 +82,6 @@ import { getEditorConfig } from '@editor/utils/config';
82
82
  import {
83
83
  DEFAULT_LEFT_COLUMN_WIDTH,
84
84
  LEFT_COLUMN_WIDTH_STORAGE_KEY,
85
- MIN_CENTER_COLUMN_WIDTH,
86
- MIN_LEFT_COLUMN_WIDTH,
87
- MIN_RIGHT_COLUMN_WIDTH,
88
85
  RIGHT_COLUMN_WIDTH_STORAGE_KEY,
89
86
  } from '@editor/utils/const';
90
87
 
@@ -122,6 +119,10 @@ const showSrc = computed(() => uiService.get('showSrc'));
122
119
 
123
120
  const columnWidth = computed(() => uiService.get('columnWidth'));
124
121
 
122
+ const minLeftColumnWidth = computed(() => uiService.get('minLeftColumnWidth'));
123
+ const minCenterColumnWidth = computed(() => uiService.get('minCenterColumnWidth'));
124
+ const minRightColumnWidth = computed(() => uiService.get('minRightColumnWidth'));
125
+
125
126
  watch(pageLength, () => {
126
127
  splitViewRef.value?.updateWidth();
127
128
  });
@@ -2,7 +2,7 @@ import { computed, type Ref, watch } from 'vue';
2
2
 
3
3
  import { Protocol } from '@editor/services/storage';
4
4
  import { Services } from '@editor/type';
5
- import { MIN_CENTER_COLUMN_WIDTH, RIGHT_COLUMN_WIDTH_STORAGE_KEY } from '@editor/utils/const';
5
+ import { RIGHT_COLUMN_WIDTH_STORAGE_KEY } from '@editor/utils/const';
6
6
 
7
7
  export const useStylePanel = (
8
8
  { uiService, storageService }: Pick<Services, 'uiService' | 'storageService'>,
@@ -47,8 +47,9 @@ export const useStylePanel = (
47
47
  }
48
48
 
49
49
  if (columnWidth.center < 0) {
50
- columnWidth.right = columnWidth.right + columnWidth.center - MIN_CENTER_COLUMN_WIDTH;
51
- columnWidth.center = MIN_CENTER_COLUMN_WIDTH;
50
+ const minCenterColumnWidth = uiService.get('minCenterColumnWidth');
51
+ columnWidth.right = columnWidth.right + columnWidth.center - minCenterColumnWidth;
52
+ columnWidth.center = minCenterColumnWidth;
52
53
 
53
54
  propsPanelWidth.value = columnWidth.right / 2;
54
55
  }