+
+
@@ -22,6 +24,7 @@ import { isPage } from '@tmagic/utils';
import type { Services } from '../../type';
+import Breadcrumb from './Breadcrumb.vue';
import PageBar from './PageBar.vue';
import MagicStage from './Stage.vue';
diff --git a/packages/editor/src/theme/breadcrumb.scss b/packages/editor/src/theme/breadcrumb.scss
new file mode 100644
index 00000000..bb345f50
--- /dev/null
+++ b/packages/editor/src/theme/breadcrumb.scss
@@ -0,0 +1,6 @@
+.m-editor-breadcrumb {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ z-index: 10;
+}
diff --git a/packages/editor/src/theme/theme.scss b/packages/editor/src/theme/theme.scss
index 30fb2d18..083faa04 100644
--- a/packages/editor/src/theme/theme.scss
+++ b/packages/editor/src/theme/theme.scss
@@ -13,3 +13,4 @@
@import "./icon.scss";
@import "./code-block.scss";
@import "./layout.scss";
+@import "./breadcrumb.scss";
diff --git a/packages/editor/src/utils/stage.ts b/packages/editor/src/utils/stage.ts
index 1a18adcc..acc1da18 100644
--- a/packages/editor/src/utils/stage.ts
+++ b/packages/editor/src/utils/stage.ts
@@ -73,6 +73,12 @@ export const useStage = (stageOptions: StageOptions) => {
editorService.sort(ev.src, ev.dist);
});
+ stage.on('select-parent', () => {
+ const parent = editorService.get('parent');
+ editorService.select(parent);
+ editorService.get
('stage').select(parent.id);
+ });
+
stage.on('changeGuides', (e) => {
uiService.set('showGuides', true);
diff --git a/packages/stage/src/MoveableSelectParentAble.ts b/packages/stage/src/MoveableSelectParentAble.ts
new file mode 100644
index 00000000..8a4e105e
--- /dev/null
+++ b/packages/stage/src/MoveableSelectParentAble.ts
@@ -0,0 +1,78 @@
+import { MoveableManagerInterface, Renderer } from 'moveable';
+
+import type StageDragResize from './StageDragResize';
+
+export default (dr: StageDragResize) => ({
+ name: 'selectParent',
+ props: {},
+ events: {},
+ render(moveable: MoveableManagerInterface, React: Renderer) {
+ const rect = moveable.getRect();
+ const { pos2 } = moveable.state;
+
+ // use css for able
+ const editableViewer = moveable.useCSS(
+ 'div',
+ `
+ {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ will-change: transform;
+ transform-origin: 0px 0px;
+ display: flex;
+ }
+ .moveable-button {
+ width: 20px;
+ height: 20px;
+ background: #4af;
+ border-radius: 4px;
+ appearance: none;
+ border: 0;
+ color: white;
+ font-size: 12px;
+ font-weight: bold;
+ }
+ `,
+ );
+ // Add key (required)
+ // Add class prefix moveable-(required)
+ return React.createElement(
+ editableViewer,
+ {
+ className: 'moveable-editable',
+ style: {
+ transform: `translate(${pos2[0] - 25}px, ${pos2[1] - 30}px) rotate(${rect.rotation}deg) translate(10px)`,
+ },
+ },
+ React.createElement(
+ 'button',
+ {
+ className: 'moveable-button',
+ title: '选中父组件',
+ onClick: () => {
+ dr.emit('select-parent');
+ },
+ },
+ React.createElement(
+ 'svg',
+ {
+ width: '1em',
+ height: '1em',
+ viewBox: '0 0 16 16',
+ fill: 'none',
+ xmlns: 'http://www.w3.org/2000/svg',
+ style: {
+ transform: 'rotate(90deg)',
+ },
+ },
+ React.createElement('path', {
+ d: 'M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z',
+ fill: 'currentColor',
+ fillOpacity: '0.9',
+ }),
+ ),
+ ),
+ );
+ },
+});
diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts
index adeae495..3602e70a 100644
--- a/packages/stage/src/StageCore.ts
+++ b/packages/stage/src/StageCore.ts
@@ -144,6 +144,9 @@ export default class StageCore extends EventEmitter {
})
.on('sort', (data: UpdateEventData) => {
setTimeout(() => this.emit('sort', data));
+ })
+ .on('select-parent', () => {
+ this.emit('select-parent');
});
this.multiDr
diff --git a/packages/stage/src/StageDragResize.ts b/packages/stage/src/StageDragResize.ts
index 3ccca920..ba0e1219 100644
--- a/packages/stage/src/StageDragResize.ts
+++ b/packages/stage/src/StageDragResize.ts
@@ -27,6 +27,7 @@ import MoveableHelper from 'moveable-helper';
import { removeClassNameByClassName } from '@tmagic/utils';
import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
+import selectParentAbles from './MoveableSelectParentAble';
import StageCore from './StageCore';
import StageMask from './StageMask';
import type { StageDragResizeConfig } from './types';
@@ -593,6 +594,13 @@ export default class StageDragResize extends EventEmitter {
bottom: isSortable ? undefined : this.container.clientHeight,
...(moveableOptions.bounds || {}),
},
+
+ props: {
+ selectParent: true,
+ },
+
+ ables: [selectParentAbles(this)],
+
...options,
...moveableOptions,
};
diff --git a/packages/stage/src/StageMask.ts b/packages/stage/src/StageMask.ts
index bfb3a14a..3208f2e4 100644
--- a/packages/stage/src/StageMask.ts
+++ b/packages/stage/src/StageMask.ts
@@ -25,7 +25,7 @@ import { Mode, MouseButton, ZIndex } from './const';
import Rule from './Rule';
import type StageCore from './StageCore';
import type { StageMaskConfig } from './types';
-import { getScrollParent, isFixedParent } from './util';
+import { getScrollParent, isFixedParent, isMoveableButton } from './util';
const wrapperClassName = 'editor-mask-wrapper';
const throttleTime = 100;
@@ -315,13 +315,18 @@ export default class StageMask extends Rule {
event.stopPropagation();
if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT) return;
+ if (!event.target) return;
+
+ const targetClassList = (event.target as HTMLDivElement).classList;
+
+ console.log(targetClassList);
// 如果单击多选选中区域,则不需要再触发选中了,而可能是拖动行为
- if (!this.isMultiSelectStatus && (event.target as HTMLDivElement).className.indexOf('moveable-area') !== -1) {
+ if (!this.isMultiSelectStatus && targetClassList.contains('moveable-area')) {
return;
}
- // 点击对象如果是边框锚点,则可能是resize
- if ((event.target as HTMLDivElement).className.indexOf('moveable-control') !== -1) {
+ // 点击对象如果是边框锚点,则可能是resize; 点击对象是功能按钮
+ if (targetClassList.contains('moveable-control') || isMoveableButton(event.target as Element)) {
return;
}
diff --git a/packages/stage/src/util.ts b/packages/stage/src/util.ts
index 8f457019..35bd214b 100644
--- a/packages/stage/src/util.ts
+++ b/packages/stage/src/util.ts
@@ -229,3 +229,6 @@ export const up = (deltaTop: number, target: HTMLElement | SVGElement): SortEven
dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id,
};
};
+
+export const isMoveableButton = (target: Element) =>
+ target.classList.contains('moveable-button') || target.parentElement?.classList.contains('moveable-button');