Appearance
Plugin Families API
Molio 的公共扩展契约收口到三类 plugin families:
ObjectTypePlugin:新增或接入对象类型。UIContributionPlugin:贡献 toolbar、菜单、选区栏、快捷键、leftDock 和 HUD slot。WorkflowServicePlugin:接入上传、布局、持久化、分享、剪贴板、导入导出等宿主服务。
装载层
| 层 | 用途 |
|---|---|
core | 编辑器必需能力,如 molecule 和 connector。 |
builtin | 默认随包提供、可被宿主覆盖的能力。 |
optional | 宿主或下游产品追加的业务扩展。 |
普通宿主使用 optionalPlugins:
vue
<MolEditor :optional-plugins="[hostUiPlugin, hostWorkflowPlugin]" />高级宿主如果要完全替换 builtin 层,才传 plugins。
UIContributionPlugin
ts
import { EDITOR_COMMANDS, type UIContributionPlugin } from '@shangchien/molio'
export const hostUiPlugin: UIContributionPlugin = {
manifest: { id: 'host:ui', name: 'Host UI', version: '1.0.0' },
toolbar: [
{
id: 'host:toolbar.autofit',
slot: 'top-utility',
label: '适配视图',
commandId: EDITOR_COMMANDS.viewAutofit,
},
],
shortcuts: [
{
id: 'host:shortcut.autofit',
keys: 'mod+shift+0',
scope: 'global',
commandId: EDITOR_COMMANDS.viewAutofit,
},
],
}toolbar slot
| slot | 位置 |
|---|---|
left-tools | 左侧主工具区。 |
left-secondary | 左侧次级工具区。 |
center-actions | 顶部主操作区。 |
right-actions | 右侧动作区。 |
top-utility | 顶部右侧工具区。 |
bottom-status | 底部状态区。 |
leftDock 和 slots
leftDock.panelComponent 与 slots.component 是字符串 ID,宿主需要通过 uiComponents 映射成真实 Vue 组件。
ts
import InspectorPanel from './InspectorPanel.vue'
const uiComponents = {
'host:inspector': InspectorPanel,
}
const hostUiPlugin: UIContributionPlugin = {
manifest: { id: 'host:ui.inspector', name: 'Inspector', version: '1.0.0' },
leftDock: [
{
id: 'host:left-dock.inspector',
label: 'Inspector',
panelComponent: 'host:inspector',
},
],
}vue
<MolEditor :optional-plugins="[hostUiPlugin]" :ui-components="uiComponents" />ObjectTypePlugin
Object plugin 由 descriptor 和 runtime 两部分组成。descriptor 声明对象类型;runtime 把对象接入 hit、select、drag、tool 和 scene 生命周期。
ts
import { ref } from 'vue'
import type { ObjectControllerRuntime, ObjectDescriptor, ObjectTypePlugin } from '@shangchien/molio'
type NotePayload = {
kind: 'host:note'
text: string
}
const descriptor: ObjectDescriptor<NotePayload> = {
id: 'host:note',
kind: 'host:note',
family: 'leaf',
title: 'Host Note',
schemaVersion: 1,
}
export const noteObjectPlugin: ObjectTypePlugin = {
manifest: { id: 'host:note.object', name: 'Host Note Object', version: '1.0.0' },
descriptors: [descriptor],
createRuntime(ctx) {
const selectedIds = ref(new Set<string>())
const controller: ObjectControllerRuntime = {
key: 'host:note',
descriptor,
actions: {},
selectedIds,
hitObject: () => null,
isSelected: id => selectedIds.value.has(id),
selectObject: id => {
selectedIds.value = id ? new Set([id]) : new Set()
},
clearSelection: () => {
selectedIds.value = new Set()
},
getSelectedObject: () => null,
beginDrag: () => false,
updateDrag: () => {},
endDrag: () => {},
cancelDrag: () => {},
}
ctx.registerDisposable({ dispose: () => selectedIds.value.clear() })
return { controllers: [controller] }
},
}WorkflowServicePlugin
Workflow 负责宿主工作流,不应该写进 core。
ts
import type { WorkflowServicePlugin } from '@shangchien/molio'
export const hostWorkflowPlugin: WorkflowServicePlugin = {
manifest: { id: 'host:workflow', name: 'Host Workflow', version: '1.0.0' },
upload: {
id: 'host:upload',
accept: ['image/*'],
async upload(file) {
const formData = new FormData()
formData.append('file', file)
const res = await fetch('/api/upload', { method: 'POST', body: formData })
const data = await res.json()
return { url: data.url }
},
},
}更多 workflow 示例见 Workflow 服务。
可见性控制
UI contribution 可以通过 visibility、visible 或 disabled 按当前选区、只读状态或工具状态控制显示。
ts
{
id: 'host:selection.delete',
label: '删除',
commandId: EDITOR_COMMANDS.selectionDelete,
visibility: ctx => ({ visible: ctx.selectionCount > 0, enabled: !ctx.readonly }),
}建议
- 新对象类型用
ObjectTypePlugin。 - 新按钮、菜单、快捷键、面板和 HUD 用
UIContributionPlugin。 - 上传、保存、分享、布局、导入导出用
WorkflowServicePlugin。 - 只有缺少稳定扩展点时,才考虑向 core 增加最小通用能力。