@tmagic/editor 1.8.0-beta.27 → 1.8.0-beta.29

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.
@@ -79,8 +79,10 @@
79
79
  var unmasked = true;
80
80
  } catch (e) {}
81
81
  var result = nativeObjectToString$1.call(value);
82
- if (unmasked) if (isOwn) value[symToStringTag$1] = tag;
83
- else delete value[symToStringTag$1];
82
+ if (unmasked) {
83
+ if (isOwn) value[symToStringTag$1] = tag;
84
+ else delete value[symToStringTag$1];
85
+ }
84
86
  return result;
85
87
  }
86
88
  //#endregion
@@ -217,7 +219,7 @@
217
219
  //#endregion
218
220
  //#region node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_baseToString.js
219
221
  /** Used as references for various `Number` constants. */
220
- var INFINITY$1 = Infinity;
222
+ var INFINITY$1 = 1 / 0;
221
223
  /** Used to convert symbols to primitives and strings. */
222
224
  var symbolProto$2 = Symbol$1 ? Symbol$1.prototype : void 0;
223
225
  var symbolToString = symbolProto$2 ? symbolProto$2.toString : void 0;
@@ -1815,7 +1817,7 @@
1815
1817
  //#endregion
1816
1818
  //#region node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_toKey.js
1817
1819
  /** Used as references for various `Number` constants. */
1818
- var INFINITY = Infinity;
1820
+ var INFINITY = 1 / 0;
1819
1821
  /**
1820
1822
  * Converts `value` to a string key if it's not a string or symbol.
1821
1823
  *
@@ -1923,9 +1925,10 @@
1923
1925
  result || (result = []);
1924
1926
  while (++index < length) {
1925
1927
  var value = array[index];
1926
- if (depth > 0 && predicate(value)) if (depth > 1) baseFlatten(value, depth - 1, predicate, isStrict, result);
1927
- else arrayPush(result, value);
1928
- else if (!isStrict) result[result.length] = value;
1928
+ if (depth > 0 && predicate(value)) {
1929
+ if (depth > 1) baseFlatten(value, depth - 1, predicate, isStrict, result);
1930
+ else arrayPush(result, value);
1931
+ } else if (!isStrict) result[result.length] = value;
1929
1932
  }
1930
1933
  return result;
1931
1934
  }
@@ -3281,16 +3284,17 @@
3281
3284
  if (isCommon) {
3282
3285
  var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3283
3286
  newValue = srcValue;
3284
- if (isArr || isBuff || isTyped) if (isArray(objValue)) newValue = objValue;
3285
- else if (isArrayLikeObject(objValue)) newValue = copyArray(objValue);
3286
- else if (isBuff) {
3287
- isCommon = false;
3288
- newValue = cloneBuffer(srcValue, true);
3289
- } else if (isTyped) {
3290
- isCommon = false;
3291
- newValue = cloneTypedArray(srcValue, true);
3292
- } else newValue = [];
3293
- else if (isPlainObject$1(srcValue) || isArguments(srcValue)) {
3287
+ if (isArr || isBuff || isTyped) {
3288
+ if (isArray(objValue)) newValue = objValue;
3289
+ else if (isArrayLikeObject(objValue)) newValue = copyArray(objValue);
3290
+ else if (isBuff) {
3291
+ isCommon = false;
3292
+ newValue = cloneBuffer(srcValue, true);
3293
+ } else if (isTyped) {
3294
+ isCommon = false;
3295
+ newValue = cloneTypedArray(srcValue, true);
3296
+ } else newValue = [];
3297
+ } else if (isPlainObject$1(srcValue) || isArguments(srcValue)) {
3294
3298
  newValue = objValue;
3295
3299
  if (isArguments(objValue)) newValue = toPlainObject(objValue);
3296
3300
  else if (!isObject(objValue) || isFunction(objValue)) newValue = initCloneObject(srcValue);
@@ -3604,7 +3608,7 @@
3604
3608
  * @param {Array} values The values to add to the set.
3605
3609
  * @returns {Object} Returns the new set.
3606
3610
  */
3607
- var createSet = !(Set$1 && 1 / setToArray(new Set$1([, -0]))[1] == Infinity) ? noop : function(values) {
3611
+ var createSet = !(Set$1 && 1 / setToArray(new Set$1([, -0]))[1] == 1 / 0) ? noop : function(values) {
3608
3612
  return new Set$1(values);
3609
3613
  };
3610
3614
  //#endregion
@@ -5369,8 +5373,10 @@
5369
5373
  const secondaryInvalid = isInvalid(secondaryValue);
5370
5374
  if (primaryInvalid && !secondaryInvalid) delete style[primary];
5371
5375
  else if (secondaryInvalid && !primaryInvalid) delete style[secondary];
5372
- else if (primaryInvalid && secondaryInvalid) if (secondaryValue === 0 && primaryValue !== 0) delete style[primary];
5373
- else delete style[secondary];
5376
+ else if (primaryInvalid && secondaryInvalid) {
5377
+ if (secondaryValue === 0 && primaryValue !== 0) delete style[primary];
5378
+ else delete style[secondary];
5379
+ }
5374
5380
  };
5375
5381
  var getInitPositionStyle = (style = {}, layout) => {
5376
5382
  if (layout === Layout.ABSOLUTE) {
@@ -6209,13 +6215,15 @@
6209
6215
  }
6210
6216
  await Promise.all(nodes.map((node) => this.doRemove(node, options)));
6211
6217
  this.removeInvalidNodesBySubtree(nodes);
6212
- if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", {
6213
- diff: removedItems,
6214
- pageData: pageForOp,
6215
- historyDescription,
6216
- source: historySource
6217
- });
6218
- else this.selectionBeforeOp = null;
6218
+ if (removedItems.length > 0 && pageForOp) {
6219
+ if (!doNotPushHistory) this.pushOpHistory("remove", {
6220
+ diff: removedItems,
6221
+ pageData: pageForOp,
6222
+ historyDescription,
6223
+ source: historySource
6224
+ });
6225
+ else this.selectionBeforeOp = null;
6226
+ }
6219
6227
  this.emit("remove", nodes);
6220
6228
  this.emit("change", {
6221
6229
  type: "remove",
@@ -6295,22 +6303,24 @@
6295
6303
  }));
6296
6304
  this.applyInvalidInfo(config, invalidInfo);
6297
6305
  if (updateData[0].oldNode?.type !== _tmagic_core.NodeType.ROOT) {
6298
- if (this.get("nodes").length) if (!doNotPushHistory) {
6299
- const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
6300
- this.pushOpHistory("update", {
6301
- diff: buildUpdateDiff(updateData.map((d) => ({
6302
- oldNode: cloneDeep(d.oldNode),
6303
- newNode: cloneDeep(d.newNode),
6304
- changeRecords: d.changeRecords?.length ? cloneDeep(d.changeRecords) : void 0
6305
- }))),
6306
- pageData: {
6307
- name: pageForOp?.name || "",
6308
- id: pageForOp.id
6309
- },
6310
- historyDescription,
6311
- source: historySource
6312
- });
6313
- } else this.selectionBeforeOp = null;
6306
+ if (this.get("nodes").length) {
6307
+ if (!doNotPushHistory) {
6308
+ const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
6309
+ this.pushOpHistory("update", {
6310
+ diff: buildUpdateDiff(updateData.map((d) => ({
6311
+ oldNode: cloneDeep(d.oldNode),
6312
+ newNode: cloneDeep(d.newNode),
6313
+ changeRecords: d.changeRecords?.length ? cloneDeep(d.changeRecords) : void 0
6314
+ }))),
6315
+ pageData: {
6316
+ name: pageForOp?.name || "",
6317
+ id: pageForOp.id
6318
+ },
6319
+ historyDescription,
6320
+ source: historySource
6321
+ });
6322
+ } else this.selectionBeforeOp = null;
6323
+ }
6314
6324
  }
6315
6325
  this.emit("update", updateData);
6316
6326
  this.emit("change", {
@@ -6438,8 +6448,10 @@
6438
6448
  historyDescription,
6439
6449
  historySource
6440
6450
  });
6441
- if (!doNotSelect) if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
6442
- else await stage?.select(newNodes[0].id);
6451
+ if (!doNotSelect) {
6452
+ if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
6453
+ else await stage?.select(newNodes[0].id);
6454
+ }
6443
6455
  return newNode;
6444
6456
  }
6445
6457
  /**
@@ -8813,12 +8825,13 @@
8813
8825
  //#endregion
8814
8826
  //#region packages/editor/src/fields/configs/stickyAddButton.ts
8815
8827
  /**
8816
- * 属性面板列表字段共用的吸底全宽「添加」按钮,展开到 group-list 配置上。
8828
+ * 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
8817
8829
  *
8818
- * 吸底按钮会盖住列表底部,新增的项必须同时滚进视口才看得见,两者一起给出避免漏配。
8830
+ * 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
8819
8831
  */
8820
8832
  var stickyAddButton = (text) => ({
8821
8833
  scrollLastItemIntoView: true,
8834
+ header: { sticky: true },
8822
8835
  addButtonConfig: {
8823
8836
  sticky: true,
8824
8837
  text,
@@ -225,8 +225,10 @@
225
225
  var unmasked = true;
226
226
  } catch (e) {}
227
227
  var result = nativeObjectToString$1.call(value);
228
- if (unmasked) if (isOwn) value[symToStringTag$1] = tag;
229
- else delete value[symToStringTag$1];
228
+ if (unmasked) {
229
+ if (isOwn) value[symToStringTag$1] = tag;
230
+ else delete value[symToStringTag$1];
231
+ }
230
232
  return result;
231
233
  }
232
234
  var objectProto$4, hasOwnProperty$14, nativeObjectToString$1, symToStringTag$1;
@@ -379,7 +381,7 @@
379
381
  init__arrayMap();
380
382
  init_isArray();
381
383
  init_isSymbol();
382
- INFINITY$1 = Infinity;
384
+ INFINITY$1 = 1 / 0;
383
385
  symbolProto$2 = Symbol$1 ? Symbol$1.prototype : void 0;
384
386
  symbolToString = symbolProto$2 ? symbolProto$2.toString : void 0;
385
387
  }));
@@ -2240,7 +2242,7 @@
2240
2242
  var INFINITY;
2241
2243
  var init__toKey = __esmMin((() => {
2242
2244
  init_isSymbol();
2243
- INFINITY = Infinity;
2245
+ INFINITY = 1 / 0;
2244
2246
  }));
2245
2247
  //#endregion
2246
2248
  //#region node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_baseGet.js
@@ -2350,9 +2352,10 @@
2350
2352
  result || (result = []);
2351
2353
  while (++index < length) {
2352
2354
  var value = array[index];
2353
- if (depth > 0 && predicate(value)) if (depth > 1) baseFlatten(value, depth - 1, predicate, isStrict, result);
2354
- else arrayPush(result, value);
2355
- else if (!isStrict) result[result.length] = value;
2355
+ if (depth > 0 && predicate(value)) {
2356
+ if (depth > 1) baseFlatten(value, depth - 1, predicate, isStrict, result);
2357
+ else arrayPush(result, value);
2358
+ } else if (!isStrict) result[result.length] = value;
2356
2359
  }
2357
2360
  return result;
2358
2361
  }
@@ -4314,16 +4317,17 @@
4314
4317
  if (isCommon) {
4315
4318
  var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue);
4316
4319
  newValue = srcValue;
4317
- if (isArr || isBuff || isTyped) if (isArray(objValue)) newValue = objValue;
4318
- else if (isArrayLikeObject(objValue)) newValue = copyArray(objValue);
4319
- else if (isBuff) {
4320
- isCommon = false;
4321
- newValue = cloneBuffer(srcValue, true);
4322
- } else if (isTyped) {
4323
- isCommon = false;
4324
- newValue = cloneTypedArray(srcValue, true);
4325
- } else newValue = [];
4326
- else if (isPlainObject$1(srcValue) || isArguments(srcValue)) {
4320
+ if (isArr || isBuff || isTyped) {
4321
+ if (isArray(objValue)) newValue = objValue;
4322
+ else if (isArrayLikeObject(objValue)) newValue = copyArray(objValue);
4323
+ else if (isBuff) {
4324
+ isCommon = false;
4325
+ newValue = cloneBuffer(srcValue, true);
4326
+ } else if (isTyped) {
4327
+ isCommon = false;
4328
+ newValue = cloneTypedArray(srcValue, true);
4329
+ } else newValue = [];
4330
+ } else if (isPlainObject$1(srcValue) || isArguments(srcValue)) {
4327
4331
  newValue = objValue;
4328
4332
  if (isArguments(objValue)) newValue = toPlainObject(objValue);
4329
4333
  else if (!isObject(objValue) || isFunction(objValue)) newValue = initCloneObject(srcValue);
@@ -4797,7 +4801,7 @@
4797
4801
  init__Set();
4798
4802
  init_noop();
4799
4803
  init__setToArray();
4800
- createSet = !(Set$1 && 1 / setToArray(new Set$1([, -0]))[1] == Infinity) ? noop : function(values) {
4804
+ createSet = !(Set$1 && 1 / setToArray(new Set$1([, -0]))[1] == 1 / 0) ? noop : function(values) {
4801
4805
  return new Set$1(values);
4802
4806
  };
4803
4807
  }));
@@ -5022,8 +5026,10 @@
5022
5026
  return;
5023
5027
  }
5024
5028
  let codeContent = "";
5025
- if (codeBlock.content) if (typeof codeBlock.content !== "string") codeContent = codeBlock.content.toString();
5026
- else codeContent = codeBlock.content;
5029
+ if (codeBlock.content) {
5030
+ if (typeof codeBlock.content !== "string") codeContent = codeBlock.content.toString();
5031
+ else codeContent = codeBlock.content;
5032
+ }
5027
5033
  codeConfig.value = {
5028
5034
  ...cloneDeep$1(codeBlock),
5029
5035
  content: codeContent
@@ -6953,8 +6959,10 @@
6953
6959
  const secondaryInvalid = isInvalid(secondaryValue);
6954
6960
  if (primaryInvalid && !secondaryInvalid) delete style[primary];
6955
6961
  else if (secondaryInvalid && !primaryInvalid) delete style[secondary];
6956
- else if (primaryInvalid && secondaryInvalid) if (secondaryValue === 0 && primaryValue !== 0) delete style[primary];
6957
- else delete style[secondary];
6962
+ else if (primaryInvalid && secondaryInvalid) {
6963
+ if (secondaryValue === 0 && primaryValue !== 0) delete style[primary];
6964
+ else delete style[secondary];
6965
+ }
6958
6966
  };
6959
6967
  getInitPositionStyle = (style = {}, layout) => {
6960
6968
  if (layout === Layout.ABSOLUTE) {
@@ -7796,13 +7804,15 @@
7796
7804
  }
7797
7805
  await Promise.all(nodes.map((node) => this.doRemove(node, options)));
7798
7806
  this.removeInvalidNodesBySubtree(nodes);
7799
- if (removedItems.length > 0 && pageForOp) if (!doNotPushHistory) this.pushOpHistory("remove", {
7800
- diff: removedItems,
7801
- pageData: pageForOp,
7802
- historyDescription,
7803
- source: historySource
7804
- });
7805
- else this.selectionBeforeOp = null;
7807
+ if (removedItems.length > 0 && pageForOp) {
7808
+ if (!doNotPushHistory) this.pushOpHistory("remove", {
7809
+ diff: removedItems,
7810
+ pageData: pageForOp,
7811
+ historyDescription,
7812
+ source: historySource
7813
+ });
7814
+ else this.selectionBeforeOp = null;
7815
+ }
7806
7816
  this.emit("remove", nodes);
7807
7817
  this.emit("change", {
7808
7818
  type: "remove",
@@ -7882,22 +7892,24 @@
7882
7892
  }));
7883
7893
  this.applyInvalidInfo(config, invalidInfo);
7884
7894
  if (updateData[0].oldNode?.type !== _tmagic_core.NodeType.ROOT) {
7885
- if (this.get("nodes").length) if (!doNotPushHistory) {
7886
- const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
7887
- this.pushOpHistory("update", {
7888
- diff: buildUpdateDiff(updateData.map((d) => ({
7889
- oldNode: cloneDeep$1(d.oldNode),
7890
- newNode: cloneDeep$1(d.newNode),
7891
- changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
7892
- }))),
7893
- pageData: {
7894
- name: pageForOp?.name || "",
7895
- id: pageForOp.id
7896
- },
7897
- historyDescription,
7898
- source: historySource
7899
- });
7900
- } else this.selectionBeforeOp = null;
7895
+ if (this.get("nodes").length) {
7896
+ if (!doNotPushHistory) {
7897
+ const pageForOp = this.getNodeInfo(nodes[0].id, false).page;
7898
+ this.pushOpHistory("update", {
7899
+ diff: buildUpdateDiff(updateData.map((d) => ({
7900
+ oldNode: cloneDeep$1(d.oldNode),
7901
+ newNode: cloneDeep$1(d.newNode),
7902
+ changeRecords: d.changeRecords?.length ? cloneDeep$1(d.changeRecords) : void 0
7903
+ }))),
7904
+ pageData: {
7905
+ name: pageForOp?.name || "",
7906
+ id: pageForOp.id
7907
+ },
7908
+ historyDescription,
7909
+ source: historySource
7910
+ });
7911
+ } else this.selectionBeforeOp = null;
7912
+ }
7901
7913
  }
7902
7914
  this.emit("update", updateData);
7903
7915
  this.emit("change", {
@@ -8025,8 +8037,10 @@
8025
8037
  historyDescription,
8026
8038
  historySource
8027
8039
  });
8028
- if (!doNotSelect) if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
8029
- else await stage?.select(newNodes[0].id);
8040
+ if (!doNotSelect) {
8041
+ if (newNodes.length > 1) await stage?.multiSelect(newNodes.map((node) => node.id));
8042
+ else await stage?.select(newNodes[0].id);
8043
+ }
8030
8044
  return newNode;
8031
8045
  }
8032
8046
  /**
@@ -12265,9 +12279,10 @@
12265
12279
  };
12266
12280
  const toString = (v, language) => {
12267
12281
  let value;
12268
- if (typeof v !== "string") if (language === "json") value = JSON.stringify(v, null, 2);
12269
- else value = serializeConfig(v);
12270
- else value = v;
12282
+ if (typeof v !== "string") {
12283
+ if (language === "json") value = JSON.stringify(v, null, 2);
12284
+ else value = serializeConfig(v);
12285
+ } else value = v;
12271
12286
  if (language === "javascript" && value.startsWith("{") && value.endsWith("}")) value = `(${value})`;
12272
12287
  return value;
12273
12288
  };
@@ -13941,7 +13956,7 @@
13941
13956
  * 不弹差异弹窗,改用一个普通确认框替代「确定回滚」按钮,避免点击后无任何提示直接执行。
13942
13957
  * 用户取消时返回 false,调用方据此中止回滚。
13943
13958
  */
13944
- const confirmRevert = () => confirmHistoryAction("确定回滚该步骤吗?回滚会将该操作作为一条新记录反向应用(新增将被删除、删除将被还原),不影响后续历史记录。");
13959
+ const confirmRevert = () => confirmHistoryAction("确定回滚该步骤吗?");
13945
13960
  /**
13946
13961
  * 「回滚」统一确认入口:可差异对比的步骤动态挂载 HistoryDiffDialog 走差异确认弹窗,
13947
13962
  * 无法对比的步骤(add / remove / 多节点更新)回退到普通二次确认框。
@@ -15096,13 +15111,14 @@
15096
15111
  const historySource = eventData ? "props" : "code";
15097
15112
  const replace = historySource === "code";
15098
15113
  let newValue;
15099
- if (replace) if (source === "style") newValue = {
15100
- ...values.value,
15101
- id: v.id || values.value.id,
15102
- style: { ...v.style || {} }
15103
- };
15104
- else newValue = { ...v };
15105
- else {
15114
+ if (replace) {
15115
+ if (source === "style") newValue = {
15116
+ ...values.value,
15117
+ id: v.id || values.value.id,
15118
+ style: { ...v.style || {} }
15119
+ };
15120
+ else newValue = { ...v };
15121
+ } else {
15106
15122
  newValue = {
15107
15123
  ...v,
15108
15124
  style: {}
@@ -17456,16 +17472,17 @@
17456
17472
  let targetParent = targetInfo.parent;
17457
17473
  if (!targetParent || !targetNode) return;
17458
17474
  let targetIndex = -1;
17459
- if (Array.isArray(targetNode.items) && dragState.dropType === "inner") if (dragState.redirectedTargetId !== void 0) {
17460
- const redirectedNode = editorService.getNodeInfo(dragState.redirectedTargetId, false).node;
17461
- if (!redirectedNode || !Array.isArray(redirectedNode.items)) return;
17462
- targetParent = redirectedNode;
17463
- targetIndex = redirectedNode.items.length;
17464
- } else {
17465
- targetIndex = targetNode.items.length;
17466
- targetParent = targetNode;
17467
- }
17468
- else targetIndex = getNodeIndex(dragState.dragOverNodeId, targetParent);
17475
+ if (Array.isArray(targetNode.items) && dragState.dropType === "inner") {
17476
+ if (dragState.redirectedTargetId !== void 0) {
17477
+ const redirectedNode = editorService.getNodeInfo(dragState.redirectedTargetId, false).node;
17478
+ if (!redirectedNode || !Array.isArray(redirectedNode.items)) return;
17479
+ targetParent = redirectedNode;
17480
+ targetIndex = redirectedNode.items.length;
17481
+ } else {
17482
+ targetIndex = targetNode.items.length;
17483
+ targetParent = targetNode;
17484
+ }
17485
+ } else targetIndex = getNodeIndex(dragState.dragOverNodeId, targetParent);
17469
17486
  if (dragState.dropType === "after") targetIndex += 1;
17470
17487
  const selectedNodes = editorService.get("nodes");
17471
17488
  if (selectedNodes.find((n) => `${n.id}` === `${node.id}`)) editorService.dragTo(selectedNodes, targetParent, targetIndex);
@@ -18299,9 +18316,10 @@
18299
18316
  return props.scrollSize * ratio;
18300
18317
  };
18301
18318
  const scrollBy = (delta) => {
18302
- if (delta < 0) if (props.pos <= 0) emit("scroll", 0);
18303
- else emit("scroll", -Math.min(-delta, props.pos));
18304
- else {
18319
+ if (delta < 0) {
18320
+ if (props.pos <= 0) emit("scroll", 0);
18321
+ else emit("scroll", -Math.min(-delta, props.pos));
18322
+ } else {
18305
18323
  const leftPos = props.size - (thumbSize.value + thumbPos.value);
18306
18324
  if (leftPos <= 0) emit("scroll", 0);
18307
18325
  else emit("scroll", Math.min(delta, leftPos));
@@ -18905,11 +18923,44 @@
18905
18923
  height: contentRect.height
18906
18924
  });
18907
18925
  });
18926
+ const parseDSL = getEditorConfig("parseDSL");
18927
+ /**
18928
+ * 本次拖拽是否由编辑器文档内部发起
18929
+ *
18930
+ * drop 的 text/json 里可能带函数(组件配置的事件、钩子等),还原只能交给 parseDSL,
18931
+ * 而 parseDSL 的默认实现是 eval;HTML 拖放又允许其他源的页面在 DataTransfer 中投递
18932
+ * 自定义 MIME 数据,跨源页面只要诱导用户拖拽一次,就能让 eval 执行任意脚本。
18933
+ *
18934
+ * 跨源页面既不会在本文档触发 dragstart,也无法往本文档创建的 DataTransfer 中写数据,
18935
+ * 因此只有起源于本文档的拖拽才交给 parseDSL 还原。
18936
+ * 同源拖拽源写入的 text/json 由业务保证可信。
18937
+ */
18938
+ let isInternalDrag = false;
18939
+ let internalDragSession = 0;
18940
+ let clearInternalDragTimer;
18941
+ const documentDragStartHandler = () => {
18942
+ internalDragSession += 1;
18943
+ isInternalDrag = true;
18944
+ if (clearInternalDragTimer !== void 0) {
18945
+ globalThis.clearTimeout(clearInternalDragTimer);
18946
+ clearInternalDragTimer = void 0;
18947
+ }
18948
+ };
18949
+ const documentDragEndHandler = () => {
18950
+ const session = internalDragSession;
18951
+ if (clearInternalDragTimer !== void 0) globalThis.clearTimeout(clearInternalDragTimer);
18952
+ clearInternalDragTimer = globalThis.setTimeout(() => {
18953
+ clearInternalDragTimer = void 0;
18954
+ if (session === internalDragSession) isInternalDrag = false;
18955
+ }, 0);
18956
+ };
18908
18957
  (0, vue.onMounted)(() => {
18909
18958
  if (stageWrapRef.value?.container) {
18910
18959
  resizeObserver.observe(stageWrapRef.value.container);
18911
18960
  keybindingService.registerEl(KeyBindingContainerKey.STAGE, stageWrapRef.value.container);
18912
18961
  }
18962
+ globalThis.document.addEventListener("dragstart", documentDragStartHandler, true);
18963
+ globalThis.document.addEventListener("dragend", documentDragEndHandler, true);
18913
18964
  });
18914
18965
  (0, vue.onBeforeUnmount)(() => {
18915
18966
  stage?.destroy();
@@ -18917,8 +18968,13 @@
18917
18968
  resizeObserver.disconnect();
18918
18969
  editorService.set("stage", null);
18919
18970
  keybindingService.unregisterEl("stage");
18971
+ if (clearInternalDragTimer !== void 0) {
18972
+ globalThis.clearTimeout(clearInternalDragTimer);
18973
+ clearInternalDragTimer = void 0;
18974
+ }
18975
+ globalThis.document.removeEventListener("dragstart", documentDragStartHandler, true);
18976
+ globalThis.document.removeEventListener("dragend", documentDragEndHandler, true);
18920
18977
  });
18921
- const parseDSL = getEditorConfig("parseDSL");
18922
18978
  const contextmenuHandler = (e) => {
18923
18979
  e.preventDefault();
18924
18980
  menuRef.value?.show(e);
@@ -18929,11 +18985,19 @@
18929
18985
  e.dataTransfer.dropEffect = "move";
18930
18986
  };
18931
18987
  const dropHandler = async (e) => {
18988
+ const allowed = isInternalDrag;
18989
+ isInternalDrag = false;
18932
18990
  if (!e.dataTransfer) return;
18933
18991
  const data = e.dataTransfer.getData("text/json");
18934
- if (!data) return;
18935
- const config = parseDSL(`(${data})`);
18936
- if (!config || config.dragType !== DragType.COMPONENT_LIST) return;
18992
+ if (!data || !allowed) return;
18993
+ let config;
18994
+ try {
18995
+ config = parseDSL(`(${data})`);
18996
+ } catch {
18997
+ return;
18998
+ }
18999
+ if (!config || config.dragType !== DragType.COMPONENT_LIST || !config.data) return;
19000
+ const dragData = config.data;
18937
19001
  e.preventDefault();
18938
19002
  const doc = stage?.renderer?.contentWindow?.document;
18939
19003
  const parentEl = doc?.querySelector(`.${props.stageOptions?.containerHighlightClassName}`);
@@ -18955,7 +19019,7 @@
18955
19019
  const layout = await editorService.getLayout(parent);
18956
19020
  const containerRect = stageContainerEl.value.getBoundingClientRect();
18957
19021
  const { scrollTop, scrollLeft } = stage.mask;
18958
- const { style = {} } = config.data;
19022
+ const { style = {} } = dragData;
18959
19023
  let top = 0;
18960
19024
  let left = 0;
18961
19025
  let position = "relative";
@@ -18973,14 +19037,14 @@
18973
19037
  top = top - parentTop * zoom.value;
18974
19038
  }
18975
19039
  }
18976
- config.data.style = {
19040
+ dragData.style = {
18977
19041
  ...style,
18978
19042
  position,
18979
19043
  top: (0, _tmagic_utils.calcValueByFontsize)(doc, top / zoom.value),
18980
19044
  left: (0, _tmagic_utils.calcValueByFontsize)(doc, left / zoom.value)
18981
19045
  };
18982
- config.data.inputEvent = e;
18983
- editorService.add(config.data, parent, { historySource: "component-panel" });
19046
+ dragData.inputEvent = e;
19047
+ editorService.add(dragData, parent, { historySource: "component-panel" });
18984
19048
  }
18985
19049
  };
18986
19050
  return (_ctx, _cache) => {
@@ -20181,10 +20245,20 @@
20181
20245
  });
20182
20246
  });
20183
20247
  };
20248
+ /**
20249
+ * root 是否已经不是编辑器当前的 root。
20250
+ *
20251
+ * `editorService.set('root', v)` 是同步赋值后再派发 `root-change`,因此派发那一刻 `v` 一定
20252
+ * 就是当前 root;但处理 `root-change` 要等 stage / runtime / 依赖收集等异步过程,期间 root
20253
+ * 可能被新的一次整体替换(外部重设 DSL、更新 root 节点、源码保存等)顶掉,此时手上的 `v`
20254
+ * 已是过期快照,继续用它刷画布或回写给外部都会与新 root 互相覆盖。
20255
+ */
20256
+ const isStaleRoot = (value) => (0, vue.toRaw)(editorService.get("root")) !== (0, vue.toRaw)(value);
20184
20257
  const updateStageDsl = async (value) => {
20185
20258
  const stage = await getStage();
20186
20259
  const runtime = await stage.renderer?.getRuntime();
20187
20260
  const app = await getTMagicApp();
20261
+ if (isStaleRoot(value)) return;
20188
20262
  if (!app?.dataSourceManager) runtime?.updateRootConfig?.(cloneDeep$1((0, vue.toRaw)(value)));
20189
20263
  const page = editorService.get("page");
20190
20264
  const node = editorService.get("node");
@@ -20195,6 +20269,7 @@
20195
20269
  if (value) {
20196
20270
  depService.clearIdleTasks();
20197
20271
  await (typeof Worker === "undefined" ? collectIdle(value.items, true) : depService.collectByWorker(value));
20272
+ if (isStaleRoot(value)) return;
20198
20273
  const dsl = cloneDeep$1((0, vue.toRaw)(value));
20199
20274
  if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) for (const node of (0, _tmagic_utils.getNodes)((0, _tmagic_utils.getDepNodeIds)(dsl.dataSourceDeps), dsl.items)) (0, _tmagic_core.updateNode)(app.dataSourceManager.compiledNode(node), dsl);
20200
20275
  runtime?.updateRootConfig?.(dsl);
@@ -20205,7 +20280,7 @@
20205
20280
  depService.addTarget((0, _tmagic_core.createDataSourceMethodTarget)(ds, (0, vue.reactive)({})));
20206
20281
  depService.addTarget((0, _tmagic_core.createDataSourceCondTarget)(ds, (0, vue.reactive)({})));
20207
20282
  };
20208
- const rootChangeHandler = (value, preValue) => {
20283
+ const rootChangeHandler = (value) => {
20209
20284
  if (!value) return;
20210
20285
  value.codeBlocks = value.codeBlocks || {};
20211
20286
  value.dataSources = value.dataSources || [];
@@ -20231,7 +20306,8 @@
20231
20306
  editorService.set("parent", null);
20232
20307
  editorService.set("page", null);
20233
20308
  }
20234
- if ((0, vue.toRaw)(value) !== (0, vue.toRaw)(preValue)) emit("update:modelValue", value);
20309
+ if (isStaleRoot(value)) return;
20310
+ if ((0, vue.toRaw)(props.modelValue) !== (0, vue.toRaw)(value)) emit("update:modelValue", value);
20235
20311
  })();
20236
20312
  };
20237
20313
  const nodeAddHandler = (nodes) => {
@@ -20680,12 +20756,13 @@
20680
20756
  //#endregion
20681
20757
  //#region packages/editor/src/fields/configs/stickyAddButton.ts
20682
20758
  /**
20683
- * 属性面板列表字段共用的吸底全宽「添加」按钮,展开到 group-list 配置上。
20759
+ * 属性面板列表字段共用的吸底全宽「添加」按钮与吸顶标题,展开到 group-list 配置上。
20684
20760
  *
20685
- * 吸底按钮会盖住列表底部,新增的项必须同时滚进视口才看得见,两者一起给出避免漏配。
20761
+ * 吸底按钮会盖住列表底部,吸顶标题会盖住列表顶部,新增的项必须同时滚进视口才看得见。
20686
20762
  */
20687
20763
  var stickyAddButton = (text) => ({
20688
20764
  scrollLastItemIntoView: true,
20765
+ header: { sticky: true },
20689
20766
  addButtonConfig: {
20690
20767
  sticky: true,
20691
20768
  text,
@@ -21845,8 +21922,10 @@
21845
21922
  let editIndex = -1;
21846
21923
  const editMethod = (method, index) => {
21847
21924
  let codeContent = "({ params, dataSource, app }) => {\n // place your code here\n}";
21848
- if (method.content) if (typeof method.content !== "string") codeContent = method.content.toString();
21849
- else codeContent = method.content;
21925
+ if (method.content) {
21926
+ if (typeof method.content !== "string") codeContent = method.content.toString();
21927
+ else codeContent = method.content;
21928
+ }
21850
21929
  codeConfig.value = {
21851
21930
  ...cloneDeep$1(method),
21852
21931
  content: codeContent
@@ -22549,7 +22628,7 @@
22549
22628
  notEditable: { type: [Boolean, Function] },
22550
22629
  dataSourceId: {}
22551
22630
  }, {
22552
- "modelValue": { default: [] },
22631
+ "modelValue": { default: () => [] },
22553
22632
  "modelModifiers": {}
22554
22633
  }),
22555
22634
  emits: /*@__PURE__*/ (0, vue.mergeModels)(["change"], ["update:modelValue"]),