diff --git a/packages/editor/src/components/FloatingBox.vue b/packages/editor/src/components/FloatingBox.vue
new file mode 100644
index 000000000..66aec2791
--- /dev/null
+++ b/packages/editor/src/components/FloatingBox.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/editor/src/components/TreeNode.vue b/packages/editor/src/components/TreeNode.vue
index aeadddd11..ce662f04f 100644
--- a/packages/editor/src/components/TreeNode.vue
+++ b/packages/editor/src/components/TreeNode.vue
@@ -108,7 +108,7 @@ const selected = computed(() => nodeStatus.value.selected);
const visible = computed(() => nodeStatus.value.visible);
const draggable = computed(() => nodeStatus.value.draggable);
-const hasChilren = computed(() => props.data.items && props.data.items.length > 0);
+const hasChilren = computed(() => props.data.items?.some((item) => props.nodeStatusMap.get(item.id)?.visible));
const handleDragStart = (event: DragEvent) => {
treeEmit?.('node-dragstart', event, props.data);
diff --git a/packages/editor/src/layouts/sidebar/Sidebar.vue b/packages/editor/src/layouts/sidebar/Sidebar.vue
index 49864c25f..812c15696 100644
--- a/packages/editor/src/layouts/sidebar/Sidebar.vue
+++ b/packages/editor/src/layouts/sidebar/Sidebar.vue
@@ -4,13 +4,13 @@
+
+
-
diff --git a/packages/editor/src/theme/floating-box.scss b/packages/editor/src/theme/floating-box.scss
new file mode 100644
index 000000000..014570af8
--- /dev/null
+++ b/packages/editor/src/theme/floating-box.scss
@@ -0,0 +1,30 @@
+.m-editor-float-box {
+ position: absolute;
+ background-color: #fff;
+ z-index: 100;
+ border: 1px solid $--border-color;
+ display: flex;
+ flex-direction: column;
+
+ .m-editor-float-box-title {
+ text-align: center;
+ font-size: 14px;
+ font-weight: 600;
+ padding: 5px;
+ cursor: move;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid $--border-color;
+ }
+
+ .m-editor-float-box-body {
+ padding: 5px;
+ flex: 1;
+ overflow: auto;
+ }
+}
+
+.m-editor-floating-box-moveable {
+ opacity: 0;
+}
diff --git a/packages/editor/src/theme/stage.scss b/packages/editor/src/theme/stage.scss
index 88f9a5c1d..9ae994b13 100644
--- a/packages/editor/src/theme/stage.scss
+++ b/packages/editor/src/theme/stage.scss
@@ -25,3 +25,27 @@
width: 0 !important;
}
}
+
+.m-editor-stage-float-button {
+ cursor: pointer;
+ transform: translateY(-50%);
+ width: 12px;
+ font-size: 12px;
+ line-height: 1.2;
+ position: absolute;
+ left: 100%;
+ top: 50%;
+ padding: 5px;
+ background-color: #ffffff;
+ transition: background-color 0.2s;
+ color: rgba(0, 0, 0, 0.88);
+ box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
+ 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
+}
+
+.m-editor-node-list-menu {
+ height: 100%;
+ width: 100%;
+ min-width: 300px;
+ max-height: 500px;
+}
diff --git a/packages/editor/src/theme/theme.scss b/packages/editor/src/theme/theme.scss
index 058c3f435..3efeed546 100644
--- a/packages/editor/src/theme/theme.scss
+++ b/packages/editor/src/theme/theme.scss
@@ -24,3 +24,4 @@
@import "./key-value.scss";
@import "./floatbox.scss";
@import "./tree.scss";
+@import "./floating-box.scss";
diff --git a/packages/editor/src/utils/editor.ts b/packages/editor/src/utils/editor.ts
index 6946abd0a..2e8dc8584 100644
--- a/packages/editor/src/utils/editor.ts
+++ b/packages/editor/src/utils/editor.ts
@@ -263,7 +263,7 @@ export const traverseNode = (node: MNode, cb: (node: MNode, parents: MNode[]) =>
if (node.items?.length) {
parents.push(node);
node.items.forEach((item: MNode) => {
- traverseNode(item, cb, parents);
+ traverseNode(item, cb, [...parents]);
});
}
};
diff --git a/packages/stage/src/ActionManager.ts b/packages/stage/src/ActionManager.ts
index 17f49a003..97c33ff76 100644
--- a/packages/stage/src/ActionManager.ts
+++ b/packages/stage/src/ActionManager.ts
@@ -561,13 +561,13 @@ export default class ActionManager extends EventEmitter {
/**
* 在up事件中负责对外通知选中事件,通知画布之外的编辑器更新
*/
- private mouseUpHandler = (): void => {
+ private mouseUpHandler = (event: MouseEvent): void => {
getDocument().removeEventListener('mouseup', this.mouseUpHandler);
this.container.addEventListener('mousemove', this.mouseMoveHandler);
if (this.isMultiSelectStatus) {
- this.emit('multi-select', this.selectedElList);
+ this.emit('multi-select', this.selectedElList, event);
} else {
- this.emit('select', this.selectedEl);
+ this.emit('select', this.selectedEl, event);
}
};
diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts
index 570a4c634..e4c0c984f 100644
--- a/packages/stage/src/StageCore.ts
+++ b/packages/stage/src/StageCore.ts
@@ -307,14 +307,14 @@ export default class StageCore extends EventEmitter {
.on('before-select', (idOrEl: Id | HTMLElement, event?: MouseEvent) => {
this.select(idOrEl, event);
})
- .on('select', (selectedEl: HTMLElement) => {
- this.emit('select', selectedEl);
+ .on('select', (selectedEl: HTMLElement, event: MouseEvent) => {
+ this.emit('select', selectedEl, event);
})
.on('before-multi-select', (idOrElList: HTMLElement[] | Id[]) => {
this.multiSelect(idOrElList);
})
- .on('multi-select', (selectedElList: HTMLElement[]) => {
- this.emit('multi-select', selectedElList);
+ .on('multi-select', (selectedElList: HTMLElement[], event: MouseEvent) => {
+ this.emit('multi-select', selectedElList, event);
});
}