feat(editor): 新增 stage-top 插槽用于在画布上方插入自定义元素

ScrollViewer 增加 before 具名插槽,Stage 据此暴露 stage-top 插槽,
经 Workspace、Editor 逐层透传,并补充对应类型定义与文档说明。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
roymondchen 2026-05-07 20:31:25 +08:00
parent 7b870e5908
commit 7ce640627d
6 changed files with 48 additions and 4 deletions

View File

@ -270,6 +270,28 @@
- **默认:** [Stage.vue](https://github.com/Tencent/tmagic-editor/blob/239b5d3efeae916a8cf3e3566d88063ecccc0553/packages/editor/src/layouts/workspace/Stage.vue)
## stage-top
- **详情:** 画布上方位置,与画布共享同一个滚动容器,渲染在画布之前,可用于在画布顶部插入自定义元素,例如顶部工具条、提示信息等
- **默认:**
:::warning
如设置了[stage](#stage)插槽,此插槽将失效
:::
- **示例:**
```html
<template>
<m-editor>
<template #stage-top>
<div class="custom-stage-top">画布顶部自定义内容</div>
</template>
</m-editor>
</template>
```
## workspace-content
- **详情:** 编辑器中间区域内,画布上方位置

View File

@ -86,6 +86,7 @@
:stage-content-menu="stageContentMenu"
:custom-content-menu="customContentMenu"
>
<template #stage-top><slot name="stage-top"></slot></template>
<template #stage><slot name="stage"></slot></template>
<template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
</Workspace>

View File

@ -1,6 +1,7 @@
<template>
<div class="m-editor-scroll-viewer-container" ref="container">
<div ref="target" :style="style">
<slot name="before"></slot>
<slot></slot>
</div>
@ -29,7 +30,7 @@ import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from
import { isNumber } from '@tmagic/utils';
import type { ScrollViewerEvent } from '@editor/type';
import type { ScrollViewerEvent, ScrollViewerSlots } from '@editor/type';
import { ScrollViewer } from '@editor/utils/scroll-viewer';
import ScrollBar from './ScrollBar.vue';
@ -38,6 +39,8 @@ defineOptions({
name: 'MEditorScrollViewer',
});
defineSlots<ScrollViewerSlots>();
const props = withDefaults(
defineProps<{
width?: number | string;

View File

@ -9,7 +9,9 @@
:disabled-stage-overlay="disabledStageOverlay"
:stage-content-menu="stageContentMenu"
:custom-content-menu="customContentMenu"
></MagicStage>
>
<template #stage-top><slot name="stage-top"></slot></template>
</MagicStage>
</slot>
<slot name="workspace-content"></slot>

View File

@ -27,6 +27,10 @@
<NodeListMenu></NodeListMenu>
<template #before>
<slot name="stage-top"></slot>
</template>
<template #content>
<StageOverlay v-if="!disabledStageOverlay"></StageOverlay>
@ -52,7 +56,7 @@ import { calcValueByFontsize, getIdFromEl } from '@tmagic/utils';
import ScrollViewer from '@editor/components/ScrollViewer.vue';
import { useServices } from '@editor/hooks';
import { useStage } from '@editor/hooks/use-stage';
import type { CustomContentMenuFunction, MenuButton, MenuComponent, StageOptions } from '@editor/type';
import type { CustomContentMenuFunction, MenuButton, MenuComponent, StageOptions, StageSlots } from '@editor/type';
import { DragType, Layout } from '@editor/type';
import { getEditorConfig } from '@editor/utils/config';
import { KeyBindingContainerKey } from '@editor/utils/keybinding-config';
@ -65,6 +69,8 @@ defineOptions({
name: 'MEditorStage',
});
defineSlots<StageSlots>();
const props = withDefaults(
defineProps<{
stageOptions: StageOptions;

View File

@ -73,7 +73,17 @@ export interface FrameworkSlots {
'page-list-popover'(props: { list: (MPage | MPageFragment)[] }): any;
}
export interface WorkspaceSlots {
export interface ScrollViewerSlots {
before(props: {}): any;
content(props: {}): any;
default(props: {}): any;
}
export interface StageSlots extends ScrollViewerSlots {
'stage-top'(props: {}): any;
}
export interface WorkspaceSlots extends StageSlots {
stage(props: {}): any;
'workspace-content'(props: {}): any;
}