@tmagic/editor 1.7.13 → 1.7.14-beta.0

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 (45) hide show
  1. package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +21 -3
  2. package/dist/es/components/ScrollViewer.vue_vue_type_script_setup_true_lang.js +1 -1
  3. package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +8 -4
  4. package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +19 -9
  5. package/dist/es/editorProps.js +1 -0
  6. package/dist/es/hooks/use-stage.js +5 -0
  7. package/dist/es/index.js +2 -2
  8. package/dist/es/initService.js +3 -0
  9. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  10. package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +12 -3
  11. package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +21 -5
  12. package/dist/es/layouts/sidebar/layer/use-click.js +22 -3
  13. package/dist/es/layouts/sidebar/layer/use-drag.js +28 -6
  14. package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +87 -12
  15. package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +5 -2
  16. package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +16 -4
  17. package/dist/es/services/editor.js +2 -1
  18. package/dist/es/services/props.js +14 -2
  19. package/dist/es/style.css +20 -0
  20. package/dist/es/utils/dep/worker.js +1 -1
  21. package/dist/es/utils/tree.js +3 -1
  22. package/dist/style.css +20 -0
  23. package/dist/tmagic-editor.umd.cjs +264 -51
  24. package/package.json +7 -7
  25. package/src/Editor.vue +17 -0
  26. package/src/components/ScrollViewer.vue +4 -1
  27. package/src/components/Tree.vue +5 -1
  28. package/src/components/TreeNode.vue +14 -9
  29. package/src/editorProps.ts +23 -0
  30. package/src/hooks/use-stage.ts +9 -0
  31. package/src/initService.ts +10 -0
  32. package/src/layouts/props-panel/PropsPanel.vue +1 -1
  33. package/src/layouts/sidebar/Sidebar.vue +19 -0
  34. package/src/layouts/sidebar/layer/LayerPanel.vue +37 -3
  35. package/src/layouts/sidebar/layer/use-click.ts +36 -3
  36. package/src/layouts/sidebar/layer/use-drag.ts +62 -6
  37. package/src/layouts/workspace/Breadcrumb.vue +87 -6
  38. package/src/layouts/workspace/Workspace.vue +3 -1
  39. package/src/layouts/workspace/viewer/Stage.vue +31 -3
  40. package/src/services/editor.ts +1 -0
  41. package/src/services/props.ts +18 -2
  42. package/src/theme/breadcrumb.scss +24 -0
  43. package/src/type.ts +58 -1
  44. package/src/utils/tree.ts +5 -1
  45. package/types/index.d.ts +97 -8
@@ -4787,6 +4787,9 @@
4787
4787
  });
4788
4788
  this.emit("props-configs-change");
4789
4789
  }
4790
+ getPropsConfigs() {
4791
+ return this.state.propsConfigMap;
4792
+ }
4790
4793
  async fillConfig(config, labelWidth) {
4791
4794
  return fillConfig(config, {
4792
4795
  labelWidth: typeof labelWidth !== "function" ? labelWidth : "80px",
@@ -4805,15 +4808,21 @@
4805
4808
  * @param type 组件类型
4806
4809
  * @returns 组件属性表单配置
4807
4810
  */
4808
- async getPropsConfig(type) {
4809
- if (type === "area") return await this.getPropsConfig("button");
4811
+ async getPropsConfig(type, data) {
4812
+ if (type === "area") return await this.getPropsConfig("button", data);
4810
4813
  return cloneDeep(this.state.propsConfigMap[(0, _tmagic_utils.toLine)(type)] || await this.fillConfig([]));
4811
4814
  }
4815
+ hasPropsConfig(type) {
4816
+ return !!this.state.propsConfigMap[(0, _tmagic_utils.toLine)(type)];
4817
+ }
4812
4818
  setPropsValues(values) {
4813
4819
  Object.keys(values).forEach((type) => {
4814
4820
  this.setPropsValue((0, _tmagic_utils.toLine)(type), values[type]);
4815
4821
  });
4816
4822
  }
4823
+ getPropsValues() {
4824
+ return this.state.propsValueMap;
4825
+ }
4817
4826
  /**
4818
4827
  * 为指点类型组件设置组件初始值
4819
4828
  * @param type 组件类型
@@ -4850,6 +4859,9 @@
4850
4859
  ...mergeWith({}, cloneDeep(this.state.propsValueMap[type] || {}), data)
4851
4860
  };
4852
4861
  }
4862
+ hasPropsValue(type) {
4863
+ return !!this.state.propsValueMap[(0, _tmagic_utils.toLine)(type)];
4864
+ }
4853
4865
  createId(type) {
4854
4866
  return `${type}_${(0, _tmagic_utils.guid)()}`;
4855
4867
  }
@@ -5794,7 +5806,8 @@
5794
5806
  modifiedNodeIds: /* @__PURE__ */ new Map(),
5795
5807
  pageLength: 0,
5796
5808
  pageFragmentLength: 0,
5797
- disabledMultiSelect: false
5809
+ disabledMultiSelect: false,
5810
+ alwaysMultiSelect: false
5798
5811
  });
5799
5812
  isHistoryStateChange = false;
5800
5813
  selectionBeforeOp = null;
@@ -6670,6 +6683,7 @@
6670
6683
  zoom: stageOptions.zoom ?? zoom.value,
6671
6684
  autoScrollIntoView: stageOptions.autoScrollIntoView,
6672
6685
  isContainer: stageOptions.isContainer,
6686
+ canDropIn: stageOptions.canDropIn,
6673
6687
  containerHighlightClassName: stageOptions.containerHighlightClassName,
6674
6688
  containerHighlightDuration: stageOptions.containerHighlightDuration,
6675
6689
  containerHighlightType: stageOptions.containerHighlightType,
@@ -6688,12 +6702,16 @@
6688
6702
  updateDragEl: stageOptions.updateDragEl,
6689
6703
  guidesOptions: stageOptions.guidesOptions,
6690
6704
  disabledMultiSelect: stageOptions.disabledMultiSelect,
6705
+ alwaysMultiSelect: stageOptions.alwaysMultiSelect,
6691
6706
  disabledRule: stageOptions.disabledRule
6692
6707
  });
6693
6708
  (0, vue.watch)(() => editor_default.get("disabledMultiSelect"), (disabledMultiSelect) => {
6694
6709
  if (disabledMultiSelect) stage.disableMultiSelect();
6695
6710
  else stage.enableMultiSelect();
6696
6711
  });
6712
+ (0, vue.watch)(() => editor_default.get("alwaysMultiSelect"), (alwaysMultiSelect) => {
6713
+ stage.setAlwaysMultiSelect(Boolean(alwaysMultiSelect));
6714
+ });
6697
6715
  const hGuidesCache = getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY));
6698
6716
  const vGuidesCache = getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY));
6699
6717
  stage.mask?.setGuides([hGuidesCache, vGuidesCache]);
@@ -6879,6 +6897,8 @@
6879
6897
  if (nodeStatus[key] !== void 0 && status[key] !== void 0) nodeStatus[key] = Boolean(status[key]);
6880
6898
  });
6881
6899
  };
6900
+ /** 默认的组件树节点是否可展开的判断函数:当节点的子项中至少存在一个可见节点时认为可展开 */
6901
+ var defaultIsExpandable = (data, nodeStatusMap) => Array.isArray(data.items) && data.items.some((item) => nodeStatusMap.get(item.id)?.visible);
6882
6902
  //#endregion
6883
6903
  //#region packages/editor/src/hooks/use-filter.ts
6884
6904
  var useFilter = (nodeData, nodeStatusMap, filterNodeMethod) => {
@@ -9020,7 +9040,7 @@
9020
9040
  return;
9021
9041
  }
9022
9042
  const type = node.value.type || (node.value.items ? "container" : "text");
9023
- curFormConfig.value = await propsService.getPropsConfig(type);
9043
+ curFormConfig.value = await propsService.getPropsConfig(type, { node: node.value });
9024
9044
  values.value = node.value;
9025
9045
  };
9026
9046
  (0, vue.watchEffect)(init);
@@ -9860,7 +9880,11 @@
9860
9880
  parentsId: { default: () => [] },
9861
9881
  nodeStatusMap: {},
9862
9882
  indent: { default: 0 },
9863
- nextLevelIndentIncrement: { default: 11 }
9883
+ nextLevelIndentIncrement: { default: 11 },
9884
+ isExpandable: {
9885
+ type: Function,
9886
+ default: defaultIsExpandable
9887
+ }
9864
9888
  },
9865
9889
  emits: [
9866
9890
  "node-dragstart",
@@ -9868,7 +9892,8 @@
9868
9892
  "node-dragend",
9869
9893
  "node-contextmenu",
9870
9894
  "node-mouseenter",
9871
- "node-click"
9895
+ "node-click",
9896
+ "node-dblclick"
9872
9897
  ],
9873
9898
  setup(__props, { emit: __emit }) {
9874
9899
  const treeEmit = (0, vue.inject)("treeEmit");
@@ -9883,7 +9908,6 @@
9883
9908
  const selected = (0, vue.computed)(() => nodeStatus.value.selected);
9884
9909
  const visible = (0, vue.computed)(() => nodeStatus.value.visible);
9885
9910
  const draggable = (0, vue.computed)(() => nodeStatus.value.draggable);
9886
- const hasChildren = (0, vue.computed)(() => Array.isArray(props.data.items) && props.data.items.some((item) => props.nodeStatusMap.get(item.id)?.visible));
9887
9911
  const handleDragStart = (event) => {
9888
9912
  treeEmit?.("node-dragstart", event, props.data);
9889
9913
  };
@@ -9905,6 +9929,9 @@
9905
9929
  const nodeClickHandler = (event) => {
9906
9930
  treeEmit?.("node-click", event, props.data);
9907
9931
  };
9932
+ const nodeDblclickHandler = (event) => {
9933
+ treeEmit?.("node-dblclick", event, props.data);
9934
+ };
9908
9935
  return (_ctx, _cache) => {
9909
9936
  const _component_TreeNode = (0, vue.resolveComponent)("TreeNode", true);
9910
9937
  return (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
@@ -9927,20 +9954,22 @@
9927
9954
  onMouseenter: mouseenterHandler
9928
9955
  }, [(0, vue.createVNode)(Icon_default, {
9929
9956
  class: "expand-icon",
9930
- style: (0, vue.normalizeStyle)(hasChildren.value ? "" : "color: transparent; cursor: default"),
9957
+ style: (0, vue.normalizeStyle)(__props.isExpandable(__props.data, __props.nodeStatusMap) ? "" : "color: transparent; cursor: default"),
9931
9958
  icon: expanded.value ? (0, vue.unref)(_element_plus_icons_vue.ArrowDown) : (0, vue.unref)(_element_plus_icons_vue.ArrowRight),
9932
9959
  onClick: expandHandler
9933
9960
  }, null, 8, ["style", "icon"]), (0, vue.createElementVNode)("div", {
9934
9961
  class: "tree-node-content",
9935
- onClick: nodeClickHandler
9936
- }, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-content", { data: __props.data }, () => [(0, vue.createElementVNode)("div", _hoisted_2$15, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-label", { data: __props.data }, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)(`${__props.data.name} (${__props.data.id})`), 1)])]), (0, vue.createElementVNode)("div", _hoisted_3$4, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-tool", { data: __props.data })])])])], 38), hasChildren.value && expanded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.data.items, (item) => {
9962
+ onClick: nodeClickHandler,
9963
+ onDblclick: nodeDblclickHandler
9964
+ }, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-content", { data: __props.data }, () => [(0, vue.createElementVNode)("div", _hoisted_2$15, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-label", { data: __props.data }, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)(`${__props.data.name} (${__props.data.id})`), 1)])]), (0, vue.createElementVNode)("div", _hoisted_3$4, [(0, vue.renderSlot)(_ctx.$slots, "tree-node-tool", { data: __props.data })])])], 32)], 38), __props.isExpandable(__props.data, __props.nodeStatusMap) && expanded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.data.items, (item) => {
9937
9965
  return (0, vue.openBlock)(), (0, vue.createBlock)(_component_TreeNode, {
9938
9966
  key: item.id,
9939
9967
  data: item,
9940
9968
  parent: __props.data,
9941
9969
  parentsId: [...__props.parentsId, __props.data.id],
9942
9970
  "node-status-map": __props.nodeStatusMap,
9943
- indent: __props.indent + __props.nextLevelIndentIncrement
9971
+ indent: __props.indent + __props.nextLevelIndentIncrement,
9972
+ "is-expandable": __props.isExpandable
9944
9973
  }, {
9945
9974
  "tree-node-content": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "tree-node-content", { data: nodeData })]),
9946
9975
  "tree-node-label": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "tree-node-label", { data: nodeData })]),
@@ -9951,7 +9980,8 @@
9951
9980
  "parent",
9952
9981
  "parentsId",
9953
9982
  "node-status-map",
9954
- "indent"
9983
+ "indent",
9984
+ "is-expandable"
9955
9985
  ]);
9956
9986
  }), 128))])) : (0, vue.createCommentVNode)("v-if", true)], 40, _hoisted_1$49)), [[vue.vShow, visible.value]]);
9957
9987
  };
@@ -9974,7 +10004,8 @@
9974
10004
  nodeStatusMap: {},
9975
10005
  indent: { default: 0 },
9976
10006
  nextLevelIndentIncrement: {},
9977
- emptyText: { default: "暂无数据" }
10007
+ emptyText: { default: "暂无数据" },
10008
+ isExpandable: {}
9978
10009
  },
9979
10010
  emits: [
9980
10011
  "node-dragover",
@@ -9983,7 +10014,8 @@
9983
10014
  "node-dragend",
9984
10015
  "node-contextmenu",
9985
10016
  "node-mouseenter",
9986
- "node-click"
10017
+ "node-click",
10018
+ "node-dblclick"
9987
10019
  ],
9988
10020
  setup(__props, { emit: __emit }) {
9989
10021
  const emit = __emit;
@@ -10001,7 +10033,8 @@
10001
10033
  data: item,
10002
10034
  indent: __props.indent,
10003
10035
  "next-level-indent-increment": __props.nextLevelIndentIncrement,
10004
- "node-status-map": __props.nodeStatusMap
10036
+ "node-status-map": __props.nodeStatusMap,
10037
+ "is-expandable": __props.isExpandable
10005
10038
  }, {
10006
10039
  "tree-node-content": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "tree-node-content", { data: nodeData })]),
10007
10040
  "tree-node-label": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "tree-node-label", { data: nodeData })]),
@@ -10011,7 +10044,8 @@
10011
10044
  "data",
10012
10045
  "indent",
10013
10046
  "next-level-indent-increment",
10014
- "node-status-map"
10047
+ "node-status-map",
10048
+ "is-expandable"
10015
10049
  ]);
10016
10050
  }), 128)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$48, [(0, vue.createElementVNode)("p", null, (0, vue.toDisplayString)(__props.emptyText), 1)]))], 32);
10017
10051
  };
@@ -11056,7 +11090,7 @@
11056
11090
  //#endregion
11057
11091
  //#region packages/editor/src/layouts/sidebar/layer/use-click.ts
11058
11092
  var useClick = ({ editorService, stageOverlayService, uiService }, isCtrlKeyDown, nodeStatusMap, menuRef) => {
11059
- const isMultiSelect = (0, vue.computed)(() => isCtrlKeyDown.value && !editorService.get("disabledMultiSelect"));
11093
+ const isMultiSelect = (0, vue.computed)(() => !editorService.get("disabledMultiSelect") && (isCtrlKeyDown.value || editorService.get("alwaysMultiSelect")));
11060
11094
  const select = async (data) => {
11061
11095
  if (!data.id) throw new Error("没有id");
11062
11096
  if (isMultiSelect.value) multiSelect(data);
@@ -11092,6 +11126,15 @@
11092
11126
  editorService.get("stage")?.highlight(data.id);
11093
11127
  stageOverlayService.get("stage")?.highlight(data.id);
11094
11128
  };
11129
+ const isNodeCanSelect = async (data) => {
11130
+ const canSelect = stageOverlayService.get("stageOptions")?.canSelect;
11131
+ if (!canSelect) return true;
11132
+ const doc = editorService.get("stage")?.renderer?.contentWindow?.document;
11133
+ if (!doc) return true;
11134
+ const el = (0, _tmagic_utils.getElById)()(doc, data.id);
11135
+ if (!el) return true;
11136
+ return Boolean(await canSelect(el));
11137
+ };
11095
11138
  const nodeClickHandler = (event, data) => {
11096
11139
  if (!nodeStatusMap?.value) return;
11097
11140
  if (uiService.get("uiSelectMode")) {
@@ -11099,13 +11142,23 @@
11099
11142
  return;
11100
11143
  }
11101
11144
  if (data.items && data.items.length > 0 && !isMultiSelect.value) updateStatus(nodeStatusMap.value, data.id, { expand: true });
11102
- (0, vue.nextTick)(() => {
11145
+ (0, vue.nextTick)(async () => {
11146
+ if (!await isNodeCanSelect(data)) return;
11103
11147
  select(data);
11104
11148
  });
11105
11149
  };
11150
+ const nodeDblclickHandler = (event, data) => {
11151
+ if (!nodeStatusMap?.value) return;
11152
+ if (uiService.get("uiSelectMode")) return;
11153
+ if (data.items && data.items.length > 0) {
11154
+ const status = nodeStatusMap.value.get(data.id);
11155
+ updateStatus(nodeStatusMap.value, data.id, { expand: !status?.expand });
11156
+ }
11157
+ };
11106
11158
  return {
11107
11159
  menuRef,
11108
11160
  nodeClickHandler,
11161
+ nodeDblclickHandler,
11109
11162
  nodeContentMenuHandler(event, data) {
11110
11163
  event.preventDefault();
11111
11164
  const nodes = editorService.get("nodes") || [];
@@ -11143,7 +11196,7 @@
11143
11196
  * dragover 属于目标节点
11144
11197
  * 这些方法并不是同一个dom事件触发的
11145
11198
  */
11146
- var useDrag = ({ editorService }) => {
11199
+ var useDrag = ({ editorService }, options = {}) => {
11147
11200
  const handleDragStart = (event) => {
11148
11201
  if (!event.dataTransfer || !event.target || !event.currentTarget) return;
11149
11202
  const targetEl = getNodeEl(event.target);
@@ -11175,19 +11228,34 @@
11175
11228
  if (parentsId.includes(`${nodeId}`) && i >= targetIdIndex) return;
11176
11229
  }
11177
11230
  }
11178
- if (distance < targetHeight / 3) {
11231
+ let canDropInTarget = isContainer;
11232
+ let redirectedTargetId;
11233
+ if (canDropInTarget && options.canDropIn && nodeId && targetNodeId !== nodeId) {
11234
+ const result = options.canDropIn([nodeId], targetNodeId);
11235
+ if (result === false) canDropInTarget = false;
11236
+ else if (typeof result === "string" || typeof result === "number") redirectedTargetId = result;
11237
+ }
11238
+ let canDropAsSibling = true;
11239
+ const directParentId = parentsId?.[parentsId.length - 1];
11240
+ if (options.canDropIn && nodeId && directParentId && directParentId !== nodeId) {
11241
+ const siblingResult = options.canDropIn([nodeId], directParentId);
11242
+ if (siblingResult === false || typeof siblingResult === "string" || typeof siblingResult === "number") canDropAsSibling = false;
11243
+ }
11244
+ dragState.dropType = "";
11245
+ if (distance < targetHeight / 3 && canDropAsSibling) {
11179
11246
  dragState.dropType = "before";
11180
11247
  (0, _tmagic_utils.addClassName)(labelEl, globalThis.document, "drag-before");
11181
- } else if (distance > targetHeight * 2 / 3) {
11248
+ } else if (distance > targetHeight * 2 / 3 && canDropAsSibling) {
11182
11249
  dragState.dropType = "after";
11183
11250
  (0, _tmagic_utils.addClassName)(labelEl, globalThis.document, "drag-after");
11184
- } else if (isContainer) {
11251
+ } else if (canDropInTarget) {
11185
11252
  dragState.dropType = "inner";
11186
11253
  (0, _tmagic_utils.addClassName)(labelEl, globalThis.document, "drag-inner");
11187
11254
  }
11188
11255
  if (!dragState.dropType) return;
11189
11256
  dragState.dragOverNodeId = targetNodeId;
11190
11257
  dragState.container = event.currentTarget;
11258
+ dragState.redirectedTargetId = dragState.dropType === "inner" ? redirectedTargetId : void 0;
11191
11259
  event.preventDefault();
11192
11260
  };
11193
11261
  const handleDragLeave = (event) => {
@@ -11209,10 +11277,16 @@
11209
11277
  let targetParent = targetInfo.parent;
11210
11278
  if (!targetParent || !targetNode) return;
11211
11279
  let targetIndex = -1;
11212
- if (Array.isArray(targetNode.items) && dragState.dropType === "inner") {
11280
+ if (Array.isArray(targetNode.items) && dragState.dropType === "inner") if (dragState.redirectedTargetId !== void 0) {
11281
+ const redirectedNode = editorService.getNodeInfo(dragState.redirectedTargetId, false).node;
11282
+ if (!redirectedNode || !Array.isArray(redirectedNode.items)) return;
11283
+ targetParent = redirectedNode;
11284
+ targetIndex = redirectedNode.items.length;
11285
+ } else {
11213
11286
  targetIndex = targetNode.items.length;
11214
11287
  targetParent = targetNode;
11215
- } else targetIndex = getNodeIndex(dragState.dragOverNodeId, targetParent);
11288
+ }
11289
+ else targetIndex = getNodeIndex(dragState.dragOverNodeId, targetParent);
11216
11290
  if (dragState.dropType === "after") targetIndex += 1;
11217
11291
  const selectedNodes = editorService.get("nodes");
11218
11292
  if (selectedNodes.find((n) => `${n.id}` === `${node.id}`)) editorService.dragTo(selectedNodes, targetParent, targetIndex);
@@ -11221,6 +11295,7 @@
11221
11295
  dragState.dragOverNodeId = "";
11222
11296
  dragState.dropType = "";
11223
11297
  dragState.container = null;
11298
+ dragState.redirectedTargetId = void 0;
11224
11299
  };
11225
11300
  return {
11226
11301
  handleDragStart,
@@ -11446,9 +11521,15 @@
11446
11521
  layerContentMenu: {},
11447
11522
  indent: {},
11448
11523
  nextLevelIndentIncrement: {},
11449
- customContentMenu: { type: Function }
11524
+ customContentMenu: { type: Function },
11525
+ isExpandable: { type: Function },
11526
+ canDropIn: { type: Function },
11527
+ beforeNodeDblclick: { type: Function }
11450
11528
  },
11451
- setup(__props) {
11529
+ emits: ["node-dblclick"],
11530
+ setup(__props, { emit: __emit }) {
11531
+ const props = __props;
11532
+ const emit = __emit;
11452
11533
  const services = useServices();
11453
11534
  const { editorService } = services;
11454
11535
  const treeRef = (0, vue.useTemplateRef)("tree");
@@ -11471,8 +11552,15 @@
11471
11552
  status.expand = false;
11472
11553
  }
11473
11554
  };
11474
- const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useDrag(services);
11475
- const { nodeClickHandler, nodeContentMenuHandler, highlightHandler: mouseenterHandler } = useClick(services, isCtrlKeyDown, nodeStatusMap, (0, vue.useTemplateRef)("menu"));
11555
+ const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useDrag(services, { canDropIn: (sourceIds, targetId) => props.canDropIn?.(sourceIds, targetId, "layer") });
11556
+ const { nodeClickHandler, nodeDblclickHandler, nodeContentMenuHandler, highlightHandler: mouseenterHandler } = useClick(services, isCtrlKeyDown, nodeStatusMap, (0, vue.useTemplateRef)("menu"));
11557
+ const dblclickHandler = async (event, data) => {
11558
+ if (props.beforeNodeDblclick) {
11559
+ if (await props.beforeNodeDblclick(event, data) === false) return;
11560
+ }
11561
+ nodeDblclickHandler(event, data);
11562
+ emit("node-dblclick", event, data);
11563
+ };
11476
11564
  return (_ctx, _cache) => {
11477
11565
  return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicScrollbar), { class: "m-editor-layer-panel" }, {
11478
11566
  default: (0, vue.withCtx)(() => [
@@ -11486,13 +11574,15 @@
11486
11574
  "node-status-map": (0, vue.unref)(nodeStatusMap),
11487
11575
  indent: __props.indent,
11488
11576
  "next-level-indent-increment": __props.nextLevelIndentIncrement,
11577
+ "is-expandable": __props.isExpandable,
11489
11578
  onNodeDragover: (0, vue.unref)(handleDragOver),
11490
11579
  onNodeDragstart: (0, vue.unref)(handleDragStart),
11491
11580
  onNodeDragleave: (0, vue.unref)(handleDragLeave),
11492
11581
  onNodeDragend: (0, vue.unref)(handleDragEnd),
11493
11582
  onNodeContextmenu: (0, vue.unref)(nodeContentMenuHandler),
11494
11583
  onNodeMouseenter: (0, vue.unref)(mouseenterHandler),
11495
- onNodeClick: (0, vue.unref)(nodeClickHandler)
11584
+ onNodeClick: (0, vue.unref)(nodeClickHandler),
11585
+ onNodeDblclick: dblclickHandler
11496
11586
  }, {
11497
11587
  "tree-node-content": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "layer-node-content", { data: nodeData })]),
11498
11588
  "tree-node-tool": (0, vue.withCtx)(({ data: nodeData }) => [(0, vue.renderSlot)(_ctx.$slots, "layer-node-tool", { data: nodeData }, () => [(0, vue.createVNode)(LayerNodeTool_default, { data: nodeData }, null, 8, ["data"])])]),
@@ -11503,6 +11593,7 @@
11503
11593
  "node-status-map",
11504
11594
  "indent",
11505
11595
  "next-level-indent-increment",
11596
+ "is-expandable",
11506
11597
  "onNodeDragover",
11507
11598
  "onNodeDragstart",
11508
11599
  "onNodeDragleave",
@@ -11678,9 +11769,14 @@
11678
11769
  layerContentMenu: {},
11679
11770
  indent: {},
11680
11771
  nextLevelIndentIncrement: {},
11681
- customContentMenu: {}
11772
+ customContentMenu: {},
11773
+ layerNodeIsExpandable: {},
11774
+ canDropIn: {},
11775
+ beforeLayerNodeDblclick: {}
11682
11776
  },
11683
- setup(__props, { expose: __expose }) {
11777
+ emits: ["layer-node-dblclick"],
11778
+ setup(__props, { expose: __expose, emit: __emit }) {
11779
+ const emit = __emit;
11684
11780
  const props = __props;
11685
11781
  const { depService, uiService, propsService } = useServices();
11686
11782
  const collecting = (0, vue.computed)(() => depService.get("collecting"));
@@ -11717,8 +11813,12 @@
11717
11813
  layerContentMenu: props.layerContentMenu,
11718
11814
  customContentMenu: props.customContentMenu,
11719
11815
  indent: props.indent,
11720
- nextLevelIndentIncrement: props.nextLevelIndentIncrement
11816
+ nextLevelIndentIncrement: props.nextLevelIndentIncrement,
11817
+ isExpandable: props.layerNodeIsExpandable,
11818
+ canDropIn: props.canDropIn,
11819
+ beforeNodeDblclick: props.beforeLayerNodeDblclick
11721
11820
  },
11821
+ listeners: { "node-dblclick": (event, nodeData) => emit("layer-node-dblclick", event, nodeData) },
11722
11822
  component: LayerPanel_default,
11723
11823
  slots: {}
11724
11824
  },
@@ -12086,7 +12186,7 @@
12086
12186
  (0, vue.createElementVNode)("div", {
12087
12187
  ref: "target",
12088
12188
  style: (0, vue.normalizeStyle)(style.value)
12089
- }, [(0, vue.renderSlot)(_ctx.$slots, "default")], 4),
12189
+ }, [(0, vue.renderSlot)(_ctx.$slots, "before"), (0, vue.renderSlot)(_ctx.$slots, "default")], 4),
12090
12190
  (0, vue.renderSlot)(_ctx.$slots, "content"),
12091
12191
  scrollHeight.value > __props.wrapHeight ? ((0, vue.openBlock)(), (0, vue.createBlock)(ScrollBar_default, {
12092
12192
  key: 0,
@@ -12623,9 +12723,20 @@
12623
12723
  const doc = stage?.renderer?.contentWindow?.document;
12624
12724
  const parentEl = doc?.querySelector(`.${props.stageOptions?.containerHighlightClassName}`);
12625
12725
  let parent = page.value;
12726
+ let resolvedParentEl = parentEl;
12626
12727
  const parentId = (0, _tmagic_utils.getIdFromEl)()(parentEl);
12627
12728
  if (parentId) parent = editorService.getNodeById(parentId, false);
12628
12729
  if (parent && stageContainerEl.value && stage) {
12730
+ if (props.stageOptions.canDropIn) {
12731
+ const result = props.stageOptions.canDropIn([], parent.id);
12732
+ if (result === false) return;
12733
+ if (typeof result === "string" || typeof result === "number") {
12734
+ const redirectedNode = editorService.getNodeById(result, false);
12735
+ if (!redirectedNode) return;
12736
+ parent = redirectedNode;
12737
+ resolvedParentEl = stage.renderer?.getTargetElement(result) ?? null;
12738
+ }
12739
+ }
12629
12740
  const layout = await editorService.getLayout(parent);
12630
12741
  const containerRect = stageContainerEl.value.getBoundingClientRect();
12631
12742
  const { scrollTop, scrollLeft } = stage.mask;
@@ -12641,8 +12752,8 @@
12641
12752
  position = "absolute";
12642
12753
  top = e.clientY - containerRect.top + scrollTop;
12643
12754
  left = e.clientX - containerRect.left + scrollLeft;
12644
- if (parentEl) {
12645
- const { left: parentLeft, top: parentTop } = (0, _tmagic_stage.getOffset)(parentEl);
12755
+ if (resolvedParentEl) {
12756
+ const { left: parentLeft, top: parentTop } = (0, _tmagic_stage.getOffset)(resolvedParentEl);
12646
12757
  left = left - parentLeft * zoom.value;
12647
12758
  top = top - parentTop * zoom.value;
12648
12759
  }
@@ -12675,6 +12786,7 @@
12675
12786
  },
12676
12787
  onClick: _cache[0] || (_cache[0] = ($event) => stageWrapRef.value?.container?.focus())
12677
12788
  }, {
12789
+ before: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "stage-top")]),
12678
12790
  content: (0, vue.withCtx)(() => [!__props.disabledStageOverlay ? ((0, vue.openBlock)(), (0, vue.createBlock)(StageOverlay_default, { key: 0 })) : (0, vue.createCommentVNode)("v-if", true), ((0, vue.openBlock)(), (0, vue.createBlock)(vue.Teleport, { to: "body" }, [(0, vue.createVNode)(ViewerMenu_default, {
12679
12791
  ref: "menu",
12680
12792
  "is-multi-select": isMultiSelect.value,
@@ -12693,7 +12805,7 @@
12693
12805
  onDrop: dropHandler,
12694
12806
  onDragover: dragoverHandler
12695
12807
  }, null, 36), (0, vue.createVNode)(NodeListMenu_default)]),
12696
- _: 1
12808
+ _: 3
12697
12809
  }, 8, [
12698
12810
  "width",
12699
12811
  "height",
@@ -12711,9 +12823,13 @@
12711
12823
  //#region packages/editor/src/layouts/workspace/Breadcrumb.vue?vue&type=script&setup=true&lang.ts
12712
12824
  var _hoisted_1$39 = {
12713
12825
  key: 0,
12714
- class: "m-editor-breadcrumb"
12826
+ class: "m-editor-breadcrumb-ellipsis"
12715
12827
  };
12716
- var _hoisted_2$12 = { key: 0 };
12828
+ var _hoisted_2$12 = {
12829
+ key: 2,
12830
+ class: "m-editor-breadcrumb-separator"
12831
+ };
12832
+ var COLLAPSE_RATIO = .8;
12717
12833
  var Breadcrumb_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
12718
12834
  name: "MEditorBreadcrumb",
12719
12835
  __name: "Breadcrumb",
@@ -12723,21 +12839,92 @@
12723
12839
  const nodes = (0, vue.computed)(() => editorService.get("nodes"));
12724
12840
  const root = (0, vue.computed)(() => editorService.get("root"));
12725
12841
  const path = (0, vue.computed)(() => (0, _tmagic_utils.getNodePath)(node.value?.id || "", root.value?.items || []));
12842
+ const containerRef = (0, vue.ref)(null);
12843
+ const collapsed = (0, vue.ref)(false);
12844
+ const displayPath = (0, vue.computed)(() => {
12845
+ const list = path.value;
12846
+ if (!collapsed.value || list.length <= 3) return list;
12847
+ return [
12848
+ list[0],
12849
+ {
12850
+ isEllipsis: true,
12851
+ id: "__ellipsis__",
12852
+ name: "..."
12853
+ },
12854
+ list[list.length - 2],
12855
+ list[list.length - 1]
12856
+ ];
12857
+ });
12858
+ const measureOverflow = async () => {
12859
+ if (collapsed.value) {
12860
+ collapsed.value = false;
12861
+ await (0, vue.nextTick)();
12862
+ }
12863
+ const el = containerRef.value;
12864
+ const parent = el?.parentElement;
12865
+ if (!el || !parent) return;
12866
+ const contentWidth = el.scrollWidth;
12867
+ const parentWidth = parent.clientWidth;
12868
+ if (parentWidth <= 0) return;
12869
+ collapsed.value = contentWidth > parentWidth * COLLAPSE_RATIO;
12870
+ };
12871
+ let resizeObserver = null;
12872
+ const observe = () => {
12873
+ resizeObserver?.disconnect();
12874
+ const el = containerRef.value;
12875
+ if (!el || typeof ResizeObserver === "undefined") return;
12876
+ resizeObserver = new ResizeObserver(() => {
12877
+ measureOverflow();
12878
+ });
12879
+ resizeObserver.observe(el);
12880
+ if (el.parentElement) resizeObserver.observe(el.parentElement);
12881
+ };
12882
+ (0, vue.onMounted)(() => {
12883
+ observe();
12884
+ measureOverflow();
12885
+ });
12886
+ (0, vue.onBeforeUnmount)(() => {
12887
+ resizeObserver?.disconnect();
12888
+ resizeObserver = null;
12889
+ });
12890
+ (0, vue.watch)(() => nodes.value.length, async () => {
12891
+ await (0, vue.nextTick)();
12892
+ observe();
12893
+ measureOverflow();
12894
+ });
12895
+ (0, vue.watch)(path, async () => {
12896
+ await (0, vue.nextTick)();
12897
+ measureOverflow();
12898
+ });
12726
12899
  const select = async (node) => {
12727
12900
  await editorService.select(node);
12728
12901
  editorService.get("stage")?.select(node.id);
12729
12902
  };
12730
12903
  return (_ctx, _cache) => {
12731
- return nodes.value.length === 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$39, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(path.value, (item, index) => {
12732
- return (0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: item.id }, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
12733
- link: "",
12734
- disabled: item.id === node.value?.id,
12735
- onClick: ($event) => select(item)
12904
+ return nodes.value.length === 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
12905
+ key: 0,
12906
+ ref_key: "containerRef",
12907
+ ref: containerRef,
12908
+ class: "m-editor-breadcrumb"
12909
+ }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(displayPath.value, (item, index) => {
12910
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: item.isEllipsis ? `ellipsis-${index}` : item.id }, [item.isEllipsis ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_1$39, "...")) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
12911
+ key: 1,
12912
+ content: item.name,
12913
+ placement: "top",
12914
+ "show-after": 500
12736
12915
  }, {
12737
- default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)(item.name), 1)]),
12916
+ default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
12917
+ class: "m-editor-breadcrumb-item",
12918
+ link: "",
12919
+ disabled: item.id === node.value?.id,
12920
+ onClick: ($event) => select(item)
12921
+ }, {
12922
+ default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)(item.name), 1)]),
12923
+ _: 2
12924
+ }, 1032, ["disabled", "onClick"])]),
12738
12925
  _: 2
12739
- }, 1032, ["disabled", "onClick"]), index < path.value.length - 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_2$12, "/")) : (0, vue.createCommentVNode)("v-if", true)], 64);
12740
- }), 128))])) : (0, vue.createCommentVNode)("v-if", true);
12926
+ }, 1032, ["content"])), index < displayPath.value.length - 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_2$12, "/")) : (0, vue.createCommentVNode)("v-if", true)], 64);
12927
+ }), 128))], 512)) : (0, vue.createCommentVNode)("v-if", true);
12741
12928
  };
12742
12929
  }
12743
12930
  });
@@ -12771,7 +12958,10 @@
12771
12958
  "disabled-stage-overlay": __props.disabledStageOverlay,
12772
12959
  "stage-content-menu": __props.stageContentMenu,
12773
12960
  "custom-content-menu": __props.customContentMenu
12774
- }, null, 8, [
12961
+ }, {
12962
+ "stage-top": (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "stage-top")]),
12963
+ _: 3
12964
+ }, 8, [
12775
12965
  "stage-options",
12776
12966
  "disabled-stage-overlay",
12777
12967
  "stage-content-menu",
@@ -13201,7 +13391,7 @@
13201
13391
  var dataSource_default = new DataSource();
13202
13392
  //#endregion
13203
13393
  //#region packages/editor/src/utils/dep/worker.ts?worker&inline
13204
- var jsContent = "(function() {\n //#region packages/schema/src/index.ts\n const NODE_CONDS_KEY = \"displayConds\";\n const NODE_DISABLE_DATA_SOURCE_KEY = \"_tmagic_node_disabled_data_source\";\n const NODE_DISABLE_CODE_BLOCK_KEY = \"_tmagic_node_disabled_code_block\";\n let HookType = /* @__PURE__ */ function(HookType) {\n /** 代码块钩子标识 */\n HookType[\"CODE\"] = \"code\";\n return HookType;\n }({});\n //#endregion\n //#region packages/utils/src/const.ts\n const DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX = \"ds-field::\";\n //#endregion\n //#region packages/utils/src/index.ts\n const isObject = (obj) => Object.prototype.toString.call(obj) === \"[object Object]\";\n const getKeysArray = (keys) => `${keys}`.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n const dataSourceTemplateRegExp = /\\$\\{([\\s\\S]+?)\\}/g;\n //#endregion\n //#region packages/dep/src/types.ts\n /** 依赖收集的目标类型 */\n let DepTargetType = /* @__PURE__ */ function(DepTargetType) {\n DepTargetType[\"DEFAULT\"] = \"default\";\n /** 代码块 */\n DepTargetType[\"CODE_BLOCK\"] = \"code-block\";\n /** 数据源 */\n DepTargetType[\"DATA_SOURCE\"] = \"data-source\";\n /** 数据源方法 */\n DepTargetType[\"DATA_SOURCE_METHOD\"] = \"data-source-method\";\n /** 数据源条件 */\n DepTargetType[\"DATA_SOURCE_COND\"] = \"data-source-cond\";\n return DepTargetType;\n }({});\n //#endregion\n //#region packages/dep/src/Target.ts\n /**\n * 需要收集依赖的目标\n * 例如:一个代码块可以为一个目标\n */\n var Target = class {\n /**\n * 如何识别目标\n */\n isTarget;\n /**\n * 目标id,不可重复\n * 例如目标是代码块,则为代码块id\n */\n id;\n /**\n * 目标名称,用于显示在依赖列表中\n */\n name;\n /**\n * 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type\n */\n type = DepTargetType.DEFAULT;\n /**\n * 依赖详情\n * 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }\n */\n deps = {};\n /**\n * 是否默认收集,默认为true,当值为false时需要传入type参数给collect方法才会被收集\n */\n isCollectByDefault;\n constructor(options) {\n this.isTarget = options.isTarget;\n this.id = options.id;\n this.name = options.name;\n this.isCollectByDefault = options.isCollectByDefault ?? true;\n if (options.type) this.type = options.type;\n if (options.initialDeps) this.deps = options.initialDeps;\n }\n /**\n * 更新依赖\n * @param option 节点配置\n * @param key 哪个key配置了这个目标的id\n */\n updateDep({ id, name, key, data }) {\n const dep = this.deps[id] || {\n name,\n keys: []\n };\n dep.name = name;\n dep.data = data;\n this.deps[id] = dep;\n if (!dep.keys.includes(key)) dep.keys.push(key);\n }\n /**\n * 删除依赖\n * @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖\n * @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key\n * @returns void\n */\n removeDep(id, key) {\n if (typeof id === \"undefined\") {\n Object.keys(this.deps).forEach((depKey) => {\n delete this.deps[depKey];\n });\n return;\n }\n const dep = this.deps[id];\n if (!dep) return;\n if (key) {\n const index = dep.keys.indexOf(key);\n dep.keys.splice(index, 1);\n if (dep.keys.length === 0) delete this.deps[id];\n } else delete this.deps[id];\n }\n /**\n * 判断指定节点下的指定key是否存在在依赖列表中\n * @param node 哪个节点\n * @param key 哪个key\n * @returns boolean\n */\n hasDep(id, key) {\n return this.deps[id]?.keys.includes(key) ?? false;\n }\n destroy() {\n this.deps = {};\n }\n };\n //#endregion\n //#region packages/dep/src/utils.ts\n const INTEGER_REGEXP = /^\\d+$/;\n const createCodeBlockTarget = (id, codeBlock, initialDeps = {}) => new Target({\n type: DepTargetType.CODE_BLOCK,\n id,\n initialDeps,\n name: codeBlock.name,\n isTarget: (_key, value) => {\n if (id === value) return true;\n if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) return value.hookData.some((item) => item.codeId === id);\n return false;\n }\n });\n /**\n * ['array'] ['array', '0'] ['array', '0', 'a'] 这种返回false\n * ['array', 'a'] 这种返回true\n * @param keys\n * @param fields\n * @returns boolean\n */\n const isIncludeArrayField = (keys, fields) => {\n let f = fields;\n return keys.some((key, index) => {\n const field = f.find(({ name }) => name === key);\n f = field?.fields || [];\n return field?.type === \"array\" && index < keys.length - 1 && !INTEGER_REGEXP.test(keys[index + 1]);\n });\n };\n /**\n * 判断模板(value)是不是使用数据源Id(dsId),如:`xxx${dsId.field}xxx${dsId.field}`\n * @param value any\n * @param dsId string | number\n * @param hasArray boolean true: 一定要包含有需要迭代的模板; false: 一定要包含普通模板;\n * @returns boolean\n */\n const isDataSourceTemplate = (value, ds, hasArray = false) => {\n const templates = value.match(dataSourceTemplateRegExp) || [];\n if (templates.length <= 0) return false;\n for (const tpl of templates) {\n const keys = getKeysArray(tpl.substring(2, tpl.length - 1));\n const dsId = keys.shift();\n if (!dsId || dsId !== ds.id) continue;\n if (hasArray === isIncludeArrayField(keys, ds.fields)) return true;\n }\n return false;\n };\n /**\n * 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}\n * @param value any\n * @param dsId string | number\n * @returns boolean\n */\n const isSpecificDataSourceTemplate = (value, dsId) => value?.isBindDataSourceField && value.dataSourceId && value.dataSourceId === dsId && typeof value.template === \"string\";\n /**\n * 关联数据源字段,格式为 [前缀+数据源ID, 字段名]\n * 使用data-source-field-select value: 'value' 可以配置出来\n * @param value any[]\n * @param id string | number\n * @returns boolean\n */\n const isUseDataSourceField = (value, id) => {\n if (!Array.isArray(value) || typeof value[0] !== \"string\") return false;\n const [prefixId] = value;\n const prefixIndex = prefixId.indexOf(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX);\n if (prefixIndex === -1) return false;\n return prefixId.substring(prefixIndex + DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX.length) === id;\n };\n const isDataSourceTarget = (ds, key, value, hasArray = false) => {\n if (!value) return false;\n const valueType = typeof value;\n if (valueType !== \"string\" && valueType !== \"object\") return false;\n if (`${key}`.startsWith(\"displayConds\")) return false;\n if (valueType === \"string\") return isDataSourceTemplate(value, ds, hasArray);\n if (isObject(value) && value.isBindDataSource && value.dataSourceId === ds.id) return true;\n if (isSpecificDataSourceTemplate(value, ds.id)) return true;\n if (isUseDataSourceField(value, ds.id)) {\n const [, ...keys] = value;\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const isDataSourceCondTarget = (ds, key, value, hasArray = false) => {\n if (!Array.isArray(value) || !ds) return false;\n const [dsId, ...keys] = value;\n if (dsId !== ds.id || !`${key}`.startsWith(\"displayConds\")) return false;\n if (ds.fields?.some((field) => field.name === keys[0])) {\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const createDataSourceTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceTarget(ds, key, value)\n });\n const createDataSourceCondTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_COND,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceCondTarget(ds, key, value)\n });\n const createDataSourceMethodTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_METHOD,\n id: ds.id,\n initialDeps,\n isTarget: (_key, value) => {\n if (!Array.isArray(value)) return false;\n const [dsId, methodName] = value;\n if (!methodName || dsId !== ds.id) return false;\n if (ds.methods?.some((method) => method.name === methodName)) return true;\n if (ds.fields?.some((field) => field.name === methodName)) return false;\n return true;\n }\n });\n const traverseTarget = (targetsList, cb, type) => {\n if (type) {\n const targets = targetsList[type];\n if (targets) for (const target of Object.values(targets)) cb(target);\n return;\n }\n for (const targets of Object.values(targetsList)) for (const target of Object.values(targets)) cb(target);\n };\n //#endregion\n //#region packages/dep/src/Watcher.ts\n const DATA_SOURCE_TARGET_TYPES = new Set([\n DepTargetType.DATA_SOURCE,\n DepTargetType.DATA_SOURCE_COND,\n DepTargetType.DATA_SOURCE_METHOD\n ]);\n var Watcher = class {\n targetsList = {};\n childrenProp = \"items\";\n idProp = \"id\";\n nameProp = \"name\";\n constructor(options) {\n if (options?.initialTargets) this.targetsList = options.initialTargets;\n if (options?.childrenProp) this.childrenProp = options.childrenProp;\n }\n getTargetsList() {\n return this.targetsList;\n }\n /**\n * 获取指定类型中的所有target\n * @param type 分类\n * @returns Target[]\n */\n getTargets(type = DepTargetType.DEFAULT) {\n return this.targetsList[type] || {};\n }\n /**\n * 添加新的目标\n * @param target Target\n */\n addTarget(target) {\n const targets = this.getTargets(target.type) || {};\n this.targetsList[target.type] = targets;\n targets[target.id] = target;\n }\n /**\n * 获取指定id的target\n * @param id target id\n * @returns Target\n */\n getTarget(id, type = DepTargetType.DEFAULT) {\n return this.getTargets(type)[id];\n }\n /**\n * 判断是否存在指定id的target\n * @param id target id\n * @returns boolean\n */\n hasTarget(id, type = DepTargetType.DEFAULT) {\n return Boolean(this.getTarget(id, type));\n }\n /**\n * 判断是否存在指定类型的target\n * @param type target type\n * @returns boolean\n */\n hasSpecifiedTypeTarget(type = DepTargetType.DEFAULT) {\n return Object.keys(this.getTargets(type)).length > 0;\n }\n /**\n * 删除指定id的target\n * @param id target id\n */\n removeTarget(id, type = DepTargetType.DEFAULT) {\n const targets = this.getTargets(type);\n if (targets[id]) {\n targets[id].destroy();\n delete targets[id];\n }\n }\n /**\n * 删除指定分类的所有target\n * @param type 分类\n * @returns void\n */\n removeTargets(type = DepTargetType.DEFAULT) {\n const targets = this.targetsList[type];\n if (!targets) return;\n for (const target of Object.values(targets)) target.destroy();\n delete this.targetsList[type];\n }\n /**\n * 删除所有target\n */\n clearTargets() {\n for (const key of Object.keys(this.targetsList)) delete this.targetsList[key];\n }\n /**\n * 收集依赖\n * @param nodes 需要收集的节点\n * @param deep 是否需要收集子节点\n * @param type 强制收集指定类型的依赖\n */\n collect(nodes, depExtendedData = {}, deep = false, type) {\n this.collectByCallback(nodes, type, ({ node, target }) => {\n this.removeTargetDep(target, node);\n this.collectItem(node, target, depExtendedData, deep);\n });\n }\n collectByCallback(nodes, type, cb) {\n traverseTarget(this.targetsList, (target) => {\n if (!type && !target.isCollectByDefault) return;\n for (const node of nodes) cb({\n node,\n target\n });\n }, type);\n }\n /**\n * 清除所有目标的依赖\n * @param nodes 需要清除依赖的节点\n */\n clear(nodes, type) {\n let { targetsList } = this;\n if (type) targetsList = { [type]: this.getTargets(type) };\n const clearedItemsNodeIds = /* @__PURE__ */ new Set();\n traverseTarget(targetsList, (target) => {\n if (nodes) for (const node of nodes) {\n target.removeDep(node[this.idProp]);\n if (Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length && !clearedItemsNodeIds.has(node[this.idProp])) {\n clearedItemsNodeIds.add(node[this.idProp]);\n this.clear(node[this.childrenProp]);\n }\n }\n else target.removeDep();\n });\n }\n /**\n * 清除指定类型的依赖\n * @param type 类型\n * @param nodes 需要清除依赖的节点\n */\n clearByType(type, nodes) {\n this.clear(nodes, type);\n }\n collectItem(node, target, depExtendedData = {}, deep = false) {\n if (node[\"_tmagic_node_disabled_data_source\"] && DATA_SOURCE_TARGET_TYPES.has(target.type)) return;\n if (node[\"_tmagic_node_disabled_code_block\"] && target.type === DepTargetType.CODE_BLOCK) return;\n const collectTarget = (config, prop = \"\") => {\n const doCollect = (key, value) => {\n const keyIsItems = key === this.childrenProp;\n const fullKey = prop ? `${prop}.${key}` : key;\n if (target.isTarget(fullKey, value)) target.updateDep({\n id: node[this.idProp],\n name: `${node[this.nameProp] || node[this.idProp]}`,\n data: depExtendedData,\n key: fullKey\n });\n else if (!keyIsItems && Array.isArray(value)) for (let i = 0, l = value.length; i < l; i++) {\n const item = value[i];\n if (isObject(item)) collectTarget(item, `${fullKey}[${i}]`);\n }\n else if (isObject(value)) collectTarget(value, fullKey);\n if (keyIsItems && deep && Array.isArray(value)) for (const child of value) this.collectItem(child, target, depExtendedData, deep);\n };\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === \"undefined\" || value === \"\") continue;\n doCollect(key, value);\n }\n };\n collectTarget(node);\n }\n removeTargetDep(target, node, key) {\n target.removeDep(node[this.idProp], key);\n if (typeof key === \"undefined\" && Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length) for (const item of node[this.childrenProp]) this.removeTargetDep(target, item, key);\n }\n };\n //#endregion\n //#region packages/editor/src/utils/logger.ts\n const error = (...args) => {\n console.error(\"magic editor: \", ...args);\n };\n //#endregion\n //#region packages/editor/src/utils/dep/worker.ts\n onmessage = (e) => {\n const watcher = new Watcher({ initialTargets: {} });\n const { dsl } = e.data;\n try {\n const mApp = eval(`(${dsl})`);\n if (!mApp) postMessage({});\n watcher.clearTargets();\n if (mApp.codeBlocks) for (const [id, code] of Object.entries(mApp.codeBlocks)) watcher.addTarget(createCodeBlockTarget(id, code));\n if (mApp.dataSources) for (const ds of mApp.dataSources) {\n watcher.addTarget(createDataSourceTarget(ds, {}));\n watcher.addTarget(createDataSourceMethodTarget(ds, {}));\n watcher.addTarget(createDataSourceCondTarget(ds, {}));\n }\n watcher.collectByCallback(mApp.items, void 0, ({ node, target }) => {\n watcher.collectItem(node, target, { pageId: node.id }, true);\n });\n const data = {\n [DepTargetType.DATA_SOURCE]: {},\n [DepTargetType.DATA_SOURCE_METHOD]: {},\n [DepTargetType.DATA_SOURCE_COND]: {},\n [DepTargetType.CODE_BLOCK]: {}\n };\n traverseTarget(watcher.getTargetsList(), (target) => {\n data[target.type][target.id] = target.deps;\n });\n postMessage(data);\n } catch (e) {\n error(e);\n postMessage({});\n }\n };\n //#endregion\n})();\n";
13394
+ var jsContent = "(function() {\n //#region packages/schema/src/index.ts\n const NODE_CONDS_KEY = \"displayConds\";\n const NODE_DISABLE_DATA_SOURCE_KEY = \"_tmagic_node_disabled_data_source\";\n const NODE_DISABLE_CODE_BLOCK_KEY = \"_tmagic_node_disabled_code_block\";\n let HookType = /* @__PURE__ */ function(HookType) {\n /** 代码块钩子标识 */\n HookType[\"CODE\"] = \"code\";\n return HookType;\n }({});\n //#endregion\n //#region packages/utils/src/const.ts\n const DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX = \"ds-field::\";\n //#endregion\n //#region packages/utils/src/index.ts\n const isObject = (obj) => Object.prototype.toString.call(obj) === \"[object Object]\";\n const getKeysArray = (keys) => `${keys}`.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n const dataSourceTemplateRegExp = /\\$\\{([\\s\\S]+?)\\}/g;\n //#endregion\n //#region packages/dep/src/types.ts\n /** 依赖收集的目标类型 */\n let DepTargetType = /* @__PURE__ */ function(DepTargetType) {\n DepTargetType[\"DEFAULT\"] = \"default\";\n /** 代码块 */\n DepTargetType[\"CODE_BLOCK\"] = \"code-block\";\n /** 数据源 */\n DepTargetType[\"DATA_SOURCE\"] = \"data-source\";\n /** 数据源方法 */\n DepTargetType[\"DATA_SOURCE_METHOD\"] = \"data-source-method\";\n /** 数据源条件 */\n DepTargetType[\"DATA_SOURCE_COND\"] = \"data-source-cond\";\n return DepTargetType;\n }({});\n //#endregion\n //#region packages/dep/src/Target.ts\n /**\n * 需要收集依赖的目标\n * 例如:一个代码块可以为一个目标\n */\n var Target = class {\n /**\n * 如何识别目标\n */\n isTarget;\n /**\n * 目标id,不可重复\n * 例如目标是代码块,则为代码块id\n */\n id;\n /**\n * 目标名称,用于显示在依赖列表中\n */\n name;\n /**\n * 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type\n */\n type = DepTargetType.DEFAULT;\n /**\n * 依赖详情\n * 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }\n */\n deps = {};\n /**\n * 是否默认收集,默认为true,当值为false时需要传入type参数给collect方法才会被收集\n */\n isCollectByDefault;\n constructor(options) {\n this.isTarget = options.isTarget;\n this.id = options.id;\n this.name = options.name;\n this.isCollectByDefault = options.isCollectByDefault ?? true;\n if (options.type) this.type = options.type;\n if (options.initialDeps) this.deps = options.initialDeps;\n }\n /**\n * 更新依赖\n * @param option 节点配置\n * @param key 哪个key配置了这个目标的id\n */\n updateDep({ id, name, key, data }) {\n const dep = this.deps[id] || {\n name,\n keys: []\n };\n dep.name = name;\n dep.data = data;\n this.deps[id] = dep;\n if (!dep.keys.includes(key)) dep.keys.push(key);\n }\n /**\n * 删除依赖\n * @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖\n * @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key\n * @returns void\n */\n removeDep(id, key) {\n if (typeof id === \"undefined\") {\n Object.keys(this.deps).forEach((depKey) => {\n delete this.deps[depKey];\n });\n return;\n }\n const dep = this.deps[id];\n if (!dep) return;\n if (key) {\n const index = dep.keys.indexOf(key);\n dep.keys.splice(index, 1);\n if (dep.keys.length === 0) delete this.deps[id];\n } else delete this.deps[id];\n }\n /**\n * 判断指定节点下的指定key是否存在在依赖列表中\n * @param node 哪个节点\n * @param key 哪个key\n * @returns boolean\n */\n hasDep(id, key) {\n return this.deps[id]?.keys.includes(key) ?? false;\n }\n destroy() {\n this.deps = {};\n }\n };\n //#endregion\n //#region packages/dep/src/utils.ts\n const INTEGER_REGEXP = /^\\d+$/;\n const createCodeBlockTarget = (id, codeBlock, initialDeps = {}) => new Target({\n type: DepTargetType.CODE_BLOCK,\n id,\n initialDeps,\n name: codeBlock.name,\n isTarget: (_key, value) => {\n if (id === value) return true;\n if (value?.hookType === HookType.CODE && Array.isArray(value.hookData)) return value.hookData.some((item) => item.codeId === id);\n return false;\n }\n });\n /**\n * ['array'] ['array', '0'] ['array', '0', 'a'] 这种返回false\n * ['array', 'a'] 这种返回true\n * @param keys\n * @param fields\n * @returns boolean\n */\n const isIncludeArrayField = (keys, fields) => {\n let f = fields;\n return keys.some((key, index) => {\n const field = f.find(({ name }) => name === key);\n f = field?.fields || [];\n return field?.type === \"array\" && index < keys.length - 1 && !INTEGER_REGEXP.test(keys[index + 1]);\n });\n };\n /**\n * 判断模板(value)是不是使用数据源Id(dsId),如:`xxx${dsId.field}xxx${dsId.field}`\n * @param value any\n * @param dsId string | number\n * @param hasArray boolean true: 一定要包含有需要迭代的模板; false: 一定要包含普通模板;\n * @returns boolean\n */\n const isDataSourceTemplate = (value, ds, hasArray = false) => {\n const templates = value.match(dataSourceTemplateRegExp) || [];\n if (templates.length <= 0) return false;\n for (const tpl of templates) {\n const keys = getKeysArray(tpl.substring(2, tpl.length - 1));\n const dsId = keys.shift();\n if (!dsId || dsId !== ds.id) continue;\n if (hasArray === isIncludeArrayField(keys, ds.fields)) return true;\n }\n return false;\n };\n /**\n * 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}\n * @param value any\n * @param dsId string | number\n * @returns boolean\n */\n const isSpecificDataSourceTemplate = (value, dsId) => value?.isBindDataSourceField && value.dataSourceId && value.dataSourceId === dsId && typeof value.template === \"string\";\n /**\n * 关联数据源字段,格式为 [前缀+数据源ID, 字段名]\n * 使用data-source-field-select value: 'value' 可以配置出来\n * @param value any[]\n * @param id string | number\n * @returns boolean\n */\n const isUseDataSourceField = (value, id) => {\n if (!Array.isArray(value) || typeof value[0] !== \"string\") return false;\n const [prefixId] = value;\n const prefixIndex = prefixId.indexOf(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX);\n if (prefixIndex === -1) return false;\n return prefixId.substring(prefixIndex + DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX.length) === id;\n };\n const isDataSourceTarget = (ds, key, value, hasArray = false) => {\n if (!value) return false;\n const valueType = typeof value;\n if (valueType !== \"string\" && valueType !== \"object\") return false;\n if (`${key}`.startsWith(\"displayConds\")) return false;\n if (valueType === \"string\") return isDataSourceTemplate(value, ds, hasArray);\n if (isObject(value) && value.isBindDataSource && value.dataSourceId === ds.id) return true;\n if (isSpecificDataSourceTemplate(value, ds.id)) return true;\n if (isUseDataSourceField(value, ds.id)) {\n const [, ...keys] = value;\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const isDataSourceCondTarget = (ds, key, value, hasArray = false) => {\n if (!Array.isArray(value) || !ds) return false;\n const [dsId, ...keys] = value;\n if (dsId !== ds.id || !`${key}`.startsWith(\"displayConds\")) return false;\n if (ds.fields?.some((field) => field.name === keys[0])) {\n const includeArray = isIncludeArrayField(keys, ds.fields);\n return hasArray ? includeArray : !includeArray;\n }\n return false;\n };\n const createDataSourceTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceTarget(ds, key, value)\n });\n const createDataSourceCondTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_COND,\n id: ds.id,\n initialDeps,\n isTarget: (key, value) => isDataSourceCondTarget(ds, key, value)\n });\n const createDataSourceMethodTarget = (ds, initialDeps = {}) => new Target({\n type: DepTargetType.DATA_SOURCE_METHOD,\n id: ds.id,\n initialDeps,\n isTarget: (_key, value) => {\n if (!Array.isArray(value)) return false;\n const [dsId, methodName] = value;\n if (!methodName || dsId !== ds.id) return false;\n if (ds.methods?.some((method) => method.name === methodName)) return true;\n if (ds.fields?.some((field) => field.name === methodName)) return false;\n return true;\n }\n });\n const traverseTarget = (targetsList, cb, type) => {\n if (type) {\n const targets = targetsList[type];\n if (targets) for (const target of Object.values(targets)) cb(target);\n return;\n }\n for (const targets of Object.values(targetsList)) for (const target of Object.values(targets)) cb(target);\n };\n //#endregion\n //#region packages/dep/src/Watcher.ts\n const DATA_SOURCE_TARGET_TYPES = new Set([\n DepTargetType.DATA_SOURCE,\n DepTargetType.DATA_SOURCE_COND,\n DepTargetType.DATA_SOURCE_METHOD\n ]);\n var Watcher = class {\n targetsList = {};\n childrenProp = \"items\";\n idProp = \"id\";\n nameProp = \"name\";\n constructor(options) {\n if (options?.initialTargets) this.targetsList = options.initialTargets;\n if (options?.childrenProp) this.childrenProp = options.childrenProp;\n }\n getTargetsList() {\n return this.targetsList;\n }\n /**\n * 获取指定类型中的所有target\n * @param type 分类\n * @returns Target[]\n */\n getTargets(type = DepTargetType.DEFAULT) {\n return this.targetsList[type] || {};\n }\n /**\n * 添加新的目标\n * @param target Target\n */\n addTarget(target) {\n const targets = this.getTargets(target.type) || {};\n this.targetsList[target.type] = targets;\n targets[target.id] = target;\n }\n /**\n * 获取指定id的target\n * @param id target id\n * @returns Target\n */\n getTarget(id, type = DepTargetType.DEFAULT) {\n return this.getTargets(type)[id];\n }\n /**\n * 判断是否存在指定id的target\n * @param id target id\n * @returns boolean\n */\n hasTarget(id, type = DepTargetType.DEFAULT) {\n return Boolean(this.getTarget(id, type));\n }\n /**\n * 判断是否存在指定类型的target\n * @param type target type\n * @returns boolean\n */\n hasSpecifiedTypeTarget(type = DepTargetType.DEFAULT) {\n return Object.keys(this.getTargets(type)).length > 0;\n }\n /**\n * 删除指定id的target\n * @param id target id\n */\n removeTarget(id, type = DepTargetType.DEFAULT) {\n const targets = this.getTargets(type);\n if (targets[id]) {\n targets[id].destroy();\n delete targets[id];\n }\n }\n /**\n * 删除指定分类的所有target\n * @param type 分类\n * @returns void\n */\n removeTargets(type = DepTargetType.DEFAULT) {\n const targets = this.targetsList[type];\n if (!targets) return;\n for (const target of Object.values(targets)) target.destroy();\n delete this.targetsList[type];\n }\n /**\n * 删除所有target\n */\n clearTargets() {\n for (const key of Object.keys(this.targetsList)) delete this.targetsList[key];\n }\n /**\n * 收集依赖\n * @param nodes 需要收集的节点\n * @param deep 是否需要收集子节点\n * @param type 强制收集指定类型的依赖\n */\n collect(nodes, depExtendedData = {}, deep = false, type) {\n this.collectByCallback(nodes, type, ({ node, target }) => {\n this.removeTargetDep(target, node);\n this.collectItem(node, target, depExtendedData, deep);\n });\n }\n collectByCallback(nodes, type, cb) {\n traverseTarget(this.targetsList, (target) => {\n if (!type && !target.isCollectByDefault) return;\n for (const node of nodes) cb({\n node,\n target\n });\n }, type);\n }\n /**\n * 清除所有目标的依赖\n * @param nodes 需要清除依赖的节点\n */\n clear(nodes, type) {\n let { targetsList } = this;\n if (type) targetsList = { [type]: this.getTargets(type) };\n const clearedItemsNodeIds = /* @__PURE__ */ new Set();\n traverseTarget(targetsList, (target) => {\n if (nodes) for (const node of nodes) {\n target.removeDep(node[this.idProp]);\n if (Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length && !clearedItemsNodeIds.has(node[this.idProp])) {\n clearedItemsNodeIds.add(node[this.idProp]);\n this.clear(node[this.childrenProp]);\n }\n }\n else target.removeDep();\n });\n }\n /**\n * 清除指定类型的依赖\n * @param type 类型\n * @param nodes 需要清除依赖的节点\n */\n clearByType(type, nodes) {\n this.clear(nodes, type);\n }\n collectItem(node, target, depExtendedData = {}, deep = false) {\n if (node[\"_tmagic_node_disabled_data_source\"] && DATA_SOURCE_TARGET_TYPES.has(target.type)) return;\n if (node[\"_tmagic_node_disabled_code_block\"] && target.type === DepTargetType.CODE_BLOCK) return;\n const collectTarget = (config, prop = \"\") => {\n const doCollect = (key, value) => {\n const keyIsItems = key === this.childrenProp;\n const fullKey = prop ? `${prop}.${key}` : key;\n if (target.isTarget(fullKey, value)) target.updateDep({\n id: node[this.idProp],\n name: `${node[this.nameProp] || node[this.idProp]}`,\n data: depExtendedData,\n key: fullKey\n });\n else if (!keyIsItems && Array.isArray(value)) for (let i = 0, l = value.length; i < l; i++) {\n const item = value[i];\n if (isObject(item)) collectTarget(item, `${fullKey}[${i}]`);\n }\n else if (isObject(value)) collectTarget(value, fullKey);\n if (keyIsItems && deep && Array.isArray(value)) for (const child of value) this.collectItem(child, target, depExtendedData, deep);\n };\n for (const [key, value] of Object.entries(config)) {\n if (typeof value === \"undefined\" || value === \"\") continue;\n doCollect(key, value);\n }\n };\n collectTarget(node);\n }\n removeTargetDep(target, node, key) {\n target.removeDep(node[this.idProp], key);\n if (typeof key === \"undefined\" && Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length) for (const item of node[this.childrenProp]) this.removeTargetDep(target, item, key);\n }\n };\n //#endregion\n //#region packages/editor/src/utils/logger.ts\n const error = (...args) => {\n if (process.env.NODE_ENV === \"development\") console.error(\"magic editor: \", ...args);\n };\n //#endregion\n //#region packages/editor/src/utils/dep/worker.ts\n onmessage = (e) => {\n const watcher = new Watcher({ initialTargets: {} });\n const { dsl } = e.data;\n try {\n const mApp = eval(`(${dsl})`);\n if (!mApp) postMessage({});\n watcher.clearTargets();\n if (mApp.codeBlocks) for (const [id, code] of Object.entries(mApp.codeBlocks)) watcher.addTarget(createCodeBlockTarget(id, code));\n if (mApp.dataSources) for (const ds of mApp.dataSources) {\n watcher.addTarget(createDataSourceTarget(ds, {}));\n watcher.addTarget(createDataSourceMethodTarget(ds, {}));\n watcher.addTarget(createDataSourceCondTarget(ds, {}));\n }\n watcher.collectByCallback(mApp.items, void 0, ({ node, target }) => {\n watcher.collectItem(node, target, { pageId: node.id }, true);\n });\n const data = {\n [DepTargetType.DATA_SOURCE]: {},\n [DepTargetType.DATA_SOURCE_METHOD]: {},\n [DepTargetType.DATA_SOURCE_COND]: {},\n [DepTargetType.CODE_BLOCK]: {}\n };\n traverseTarget(watcher.getTargetsList(), (target) => {\n data[target.type][target.id] = target.deps;\n });\n postMessage(data);\n } catch (e) {\n error(e);\n postMessage({});\n }\n };\n //#endregion\n})();\n";
13205
13395
  var blob = typeof self !== "undefined" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", jsContent], { type: "text/javascript;charset=utf-8" });
13206
13396
  function WorkerWrapper(options) {
13207
13397
  let objURL;
@@ -13775,6 +13965,7 @@
13775
13965
  var defaultEditorProps = {
13776
13966
  renderType: _tmagic_stage.RenderType.IFRAME,
13777
13967
  disabledMultiSelect: false,
13968
+ alwaysMultiSelect: false,
13778
13969
  disabledPageFragment: false,
13779
13970
  disabledStageOverlay: false,
13780
13971
  containerHighlightClassName: _tmagic_stage.CONTAINER_HIGHLIGHT_CLASS_NAME,
@@ -13810,6 +14001,9 @@
13810
14001
  (0, vue.watch)(() => props.disabledMultiSelect, (disabledMultiSelect) => {
13811
14002
  editorService.set("disabledMultiSelect", disabledMultiSelect || false);
13812
14003
  }, { immediate: true });
14004
+ (0, vue.watch)(() => props.alwaysMultiSelect, (alwaysMultiSelect) => {
14005
+ editorService.set("alwaysMultiSelect", alwaysMultiSelect || false);
14006
+ }, { immediate: true });
13813
14007
  (0, vue.watch)(() => props.componentGroupList, (componentGroupList) => componentGroupList && componentListService.setList(componentGroupList), { immediate: true });
13814
14008
  (0, vue.watch)(() => props.datasourceList, (datasourceList) => datasourceList && dataSourceService.set("datasourceTypeList", datasourceList), { immediate: true });
13815
14009
  (0, vue.watch)(() => props.propsConfigs, (configs) => configs && propsService.setPropsConfigs(configs), { immediate: true });
@@ -14219,6 +14413,7 @@
14219
14413
  disabledDragStart: { type: Boolean },
14220
14414
  guidesOptions: {},
14221
14415
  disabledMultiSelect: { type: Boolean },
14416
+ alwaysMultiSelect: { type: Boolean },
14222
14417
  disabledPageFragment: { type: Boolean },
14223
14418
  disabledStageOverlay: { type: Boolean },
14224
14419
  disabledShowSrc: { type: Boolean },
@@ -14231,7 +14426,10 @@
14231
14426
  canSelect: { type: Function },
14232
14427
  isContainer: { type: Function },
14233
14428
  customContentMenu: { type: Function },
14429
+ layerNodeIsExpandable: { type: Function },
14430
+ canDropIn: { type: Function },
14234
14431
  beforeDblclick: { type: Function },
14432
+ beforeLayerNodeDblclick: { type: Function },
14235
14433
  extendFormState: { type: Function },
14236
14434
  pageBarSortOptions: {},
14237
14435
  pageFilterFunction: { type: Function }
@@ -14241,7 +14439,8 @@
14241
14439
  "props-panel-unmounted",
14242
14440
  "update:modelValue",
14243
14441
  "props-form-error",
14244
- "props-submit-error"
14442
+ "props-submit-error",
14443
+ "layer-node-dblclick"
14245
14444
  ],
14246
14445
  setup(__props, { expose: __expose, emit: __emit }) {
14247
14446
  const emit = __emit;
@@ -14272,6 +14471,7 @@
14272
14471
  canSelect: props.canSelect,
14273
14472
  updateDragEl: props.updateDragEl,
14274
14473
  isContainer: props.isContainer,
14474
+ canDropIn: props.canDropIn ? (sourceIds, targetId) => props.canDropIn(sourceIds, targetId, sourceIds.length === 0 ? "stage-add" : "stage-drag") : void 0,
14275
14475
  containerHighlightClassName: props.containerHighlightClassName,
14276
14476
  containerHighlightDuration: props.containerHighlightDuration,
14277
14477
  containerHighlightType: props.containerHighlightType,
@@ -14279,6 +14479,7 @@
14279
14479
  renderType: props.renderType,
14280
14480
  guidesOptions: props.guidesOptions,
14281
14481
  disabledMultiSelect: props.disabledMultiSelect,
14482
+ alwaysMultiSelect: props.alwaysMultiSelect,
14282
14483
  beforeDblclick: props.beforeDblclick
14283
14484
  };
14284
14485
  stageOverlay_default.set("stageOptions", stageOptions);
@@ -14298,6 +14499,9 @@
14298
14499
  const propsPanelFormErrorHandler = (e) => {
14299
14500
  emit("props-form-error", e);
14300
14501
  };
14502
+ const layerNodeDblclickHandler = (event, data) => {
14503
+ emit("layer-node-dblclick", event, data);
14504
+ };
14301
14505
  __expose(services);
14302
14506
  return (_ctx, _cache) => {
14303
14507
  return (0, vue.openBlock)(), (0, vue.createBlock)(Framework_default, {
@@ -14314,7 +14518,11 @@
14314
14518
  "layer-content-menu": __props.layerContentMenu,
14315
14519
  "custom-content-menu": __props.customContentMenu,
14316
14520
  indent: __props.treeIndent,
14317
- "next-level-indent-increment": __props.treeNextLevelIndentIncrement
14521
+ "next-level-indent-increment": __props.treeNextLevelIndentIncrement,
14522
+ "layer-node-is-expandable": __props.layerNodeIsExpandable,
14523
+ "can-drop-in": __props.canDropIn,
14524
+ "before-layer-node-dblclick": __props.beforeLayerNodeDblclick,
14525
+ onLayerNodeDblclick: layerNodeDblclickHandler
14318
14526
  }, {
14319
14527
  "layer-panel-header": (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "layer-panel-header")]),
14320
14528
  "layer-node-content": (0, vue.withCtx)(({ data }) => [(0, vue.renderSlot)(_ctx.$slots, "layer-node-content", { data })]),
@@ -14337,13 +14545,17 @@
14337
14545
  "layer-content-menu",
14338
14546
  "custom-content-menu",
14339
14547
  "indent",
14340
- "next-level-indent-increment"
14548
+ "next-level-indent-increment",
14549
+ "layer-node-is-expandable",
14550
+ "can-drop-in",
14551
+ "before-layer-node-dblclick"
14341
14552
  ])])]),
14342
14553
  workspace: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "workspace", { editorService: (0, vue.unref)(editor_default) }, () => [(0, vue.createVNode)(Workspace_default, {
14343
14554
  "disabled-stage-overlay": __props.disabledStageOverlay,
14344
14555
  "stage-content-menu": __props.stageContentMenu,
14345
14556
  "custom-content-menu": __props.customContentMenu
14346
14557
  }, {
14558
+ "stage-top": (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "stage-top")]),
14347
14559
  stage: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "stage")]),
14348
14560
  "workspace-content": (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "workspace-content", { editorService: (0, vue.unref)(editor_default) })]),
14349
14561
  _: 3
@@ -18856,6 +19068,7 @@
18856
19068
  exports.dataSourceService = dataSource_default;
18857
19069
  exports.debug = debug;
18858
19070
  exports.default = plugin_default;
19071
+ exports.defaultIsExpandable = defaultIsExpandable;
18859
19072
  exports.depService = dep_default;
18860
19073
  Object.defineProperty(exports, "designPlugin", {
18861
19074
  enumerable: true,