Skip to content

Commit 2475250

Browse files
committed
docs: add docs for draggable menu extension point
Revised documentation to reflect the new draggable menu extension API, replacing the previous draggable functionality. Added details and examples for `getDraggableMenuItems`, described menu nesting, and included a new reference image for the draggable menu.
1 parent 4f0a5d2 commit 2475250

2 files changed

Lines changed: 101 additions & 80 deletions

File tree

docs/developer-guide/plugin/extension-points/ui/default-editor-extension-create.md

Lines changed: 101 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,12 @@ export interface ExtensionOptions {
4949
editor: Editor;
5050
}) => ToolboxItem | ToolboxItem[];
5151

52-
// 拖拽扩展
53-
getDraggable?: ({ editor }: { editor: Editor }) => DraggableItem | boolean;
52+
// 拖拽菜单扩展
53+
getDraggableMenuItems?: ({
54+
editor,
55+
}: {
56+
editor: Editor;
57+
}) => DragButtonType | DragButtonType[];
5458
}
5559
```
5660

@@ -367,111 +371,128 @@ addOptions() {
367371
}
368372
```
369373

370-
#### 5. 拖拽功能扩展
374+
#### 5. 拖拽菜单扩展
375+
376+
拖拽菜单扩展主要用于拖拽的菜单功能扩展,例如转换为、复制、剪切、删除等操作。
371377

372-
拖拽功能的扩展,可用于支持当前块元素的拖拽功能。
378+
![拖拽功能扩展](/img/developer-guide/plugin/extension-points/ui/default-editor-extension-drag-menu.png)
373379

374-
![拖拽功能扩展](/img/developer-guide/plugin/extension-points/ui/default-editor-extension-drag.png)
380+
[https://github.com/halo-dev/halo/pull/7861](https://github.com/halo-dev/halo/pull/7861) 中,我们重构了对编辑器拖拽区域的扩展,并且支持了对拖拽菜单的扩展。如果需要对拖拽菜单进行扩展,只需要在具体的 Tiptap Extension 中的 `addOptions` 中定义 `getDraggableMenuItems` 函数即可,如:
381+
382+
```ts
383+
{
384+
addOptions() {
385+
return {
386+
...this.parent?.(),
387+
getDraggableMenuItems({ editor }: { editor: Editor }) {
388+
return []
389+
},
390+
};
391+
},
392+
}
393+
```
375394

376-
[https://github.com/halo-sigs/richtext-editor/pull/48](https://github.com/halo-sigs/richtext-editor/pull/48) 中,我们实现了对所有元素的拖拽功能,如果需要让当前扩展支持拖拽,只需要在具体的 Tiptap Extension 中的 `addOptions` 中定义 `getDraggable` 函数,并让其返回 true 即可。如:
395+
并且,拖拽菜单最多支持两级菜单嵌套, 如果想扩展已有的一级菜单,为其二级菜单增加内容,则只需将二级菜单的 `parentKey` 设置为一级菜单的 `key`。如:
377396

378397
```ts
379398
{
380399
addOptions() {
381400
return {
382401
...this.parent?.(),
383-
getDraggable() {
384-
return true;
402+
getDraggableMenuItems({ editor }: { editor: Editor }) {
403+
return {
404+
parentKey: CONVERT_TO_KEY,
405+
children: {
406+
items: [
407+
{
408+
priority: 10,
409+
icon: markRaw(MdiFormatParagraph),
410+
title: i18n.global.t("editor.common.heading.paragraph"),
411+
action: ({ editor }: { editor: Editor }) =>
412+
editor.chain().focus().setParagraph().run(),
413+
},
414+
],
415+
},
416+
}
385417
},
386418
};
387419
},
388420
}
389421
```
390422

391-
其中 `getDraggable` 即为为当前扩展增加可拖拽的功能。其返回类型为
423+
下面为 `getDraggableMenuItems` 的返回类型
392424

393425
```ts
394-
// 拖拽扩展
395-
getDraggable?: ({ editor }: { editor: Editor }) => DraggableItem | boolean;
396426

397-
export interface DraggableItem {
398-
getRenderContainer?: ({ // 拖拽按钮计算偏移位置的基准 DOM
399-
dom,
400-
view,
427+
// 拖拽菜单扩展
428+
getDraggableMenuItems?: ({
429+
editor,
430+
}: {
431+
editor: Editor;
432+
}) => DragButtonType | DragButtonType[];
433+
434+
// 拖拽菜单项目属性
435+
export interface DragButtonItemProps {
436+
priority?: number; // 优先级,数字越小优先级越大,越靠前
437+
title?: string | (() => string); // 标题
438+
icon?: Component; // 图标
439+
key?: string; // 唯一标识,如果同级菜单项设置了同样的 key,则会被合并为一个菜单项。
440+
action?: ({ // 点击菜单后的操作,如果返回 Component,则会将其包含在子菜单中。
441+
// 可以通过调用 close 方法可以在操作完成后关闭拖拽菜单,或者当返回为 true 或 undefined 时,会自动关闭拖拽菜单,如果返回 false,则不会关闭拖拽菜单。
442+
editor,
443+
node,
444+
pos,
445+
close,
446+
}: {
447+
editor: Editor;
448+
node: PMNode | null;
449+
pos: number;
450+
close: () => void;
451+
}) => Component | boolean | void | Promise<Component | boolean | void>;
452+
iconStyle?: string; // 图标自定义样式
453+
class?: string; // 自定义样式
454+
visible?: ({ // 是否显示当前菜单项,默认为 true
455+
editor,
456+
node,
457+
pos,
458+
}: {
459+
editor: Editor;
460+
node: PMNode | null;
461+
pos: number;
462+
}) => boolean;
463+
isActive?: ({ // 当前菜单项是否处于活动状态,默认为 false
464+
editor,
465+
node,
466+
pos,
401467
}: {
402-
dom: HTMLElement;
403-
view: EditorView;
404-
}) => DragSelectionNode;
405-
handleDrop?: ({ // 完成拖拽功能之后的处理。返回 true 则会阻止拖拽的发生
406-
view,
407-
event,
408-
slice,
409-
insertPos,
468+
editor: Editor;
469+
node: PMNode | null;
470+
pos: number;
471+
}) => boolean;
472+
disabled?: ({ // 是否禁用当前菜单项,默认为 false
473+
editor,
410474
node,
411-
selection,
475+
pos,
412476
}: {
413-
view: EditorView;
414-
event: DragEvent;
415-
slice: Slice;
416-
insertPos: number;
417-
node: Node;
418-
selection: Selection;
419-
}) => boolean | void;
420-
allowPropagationDownward?: boolean; // 是否允许拖拽事件向内部传播,
477+
editor: Editor;
478+
node: PMNode | null;
479+
pos: number;
480+
}) => boolean;
481+
keyboard?: string; // 快捷键,遵循 https://tiptap.dev/docs/editor/core-concepts/keyboard-shortcuts
482+
component?: Component; // 自定义组件,如果提供了该属性,则不会显示默认的菜单项,而是会显示自定义组件,并且将所有 props 传递给自定义组件。
483+
[key: string]: any; // 其他自定义属性,将会传递给自定义组件。
421484
}
422485

423-
export interface DragSelectionNode {
424-
$pos?: ResolvedPos;
425-
node?: Node;
426-
el: HTMLElement;
427-
nodeOffset?: number;
428-
dragDomOffset?: {
429-
x: number;
430-
y: number;
486+
// 一级菜单项
487+
export interface DragButtonType extends DragButtonItemProps {
488+
parentKey?: string; // 父级菜单项的唯一标识,如果提供了该属性,则视为扩展目标菜单项的二级菜单。
489+
children?: { // 子菜单项,如果提供了该属性,则视为扩展目标菜单项的二级菜单。
490+
component?: Component; // 自定义组件,如果提供了该属性,则不会显示默认的子菜单项,而是会显示自定义组件,并且将所有 props 传递给自定义组件。
491+
items?: DragButtonItemProps[]; // 子菜单项列表,如果提供了该属性,则视为扩展目标菜单项的二级菜单。
431492
};
432493
}
433494
```
434495

435-
> 拖拽会从父 Node 节点开始触发,直到找到一个实现 `getDraggable` 的扩展,如果没有找到,则不会触发拖拽事件。父 Node 可以通过 `allowPropagationDownward` 来控制是否允许拖拽事件向内部传播。如果 `allowPropagationDownward` 设置为 true,则会继续向内部寻找实现 `getDraggable` 的扩展,如果没有找到,则触发父 Node 的 `getDraggable` 实现,否则继续进行传播。
436-
437-
如下为 [`Iframe`](https://github.com/halo-dev/halo/blob/main/console/packages/editor/src/extensions/iframe/index.ts) 扩展中对于 `getDraggable` 拖拽功能的扩展示例:
438-
439-
```ts
440-
addOptions() {
441-
return {
442-
...this.parent?.(),
443-
getDraggable() {
444-
return {
445-
getRenderContainer({ dom, view }) {
446-
let container = dom;
447-
while (
448-
container.parentElement &&
449-
container.parentElement.tagName !== "P"
450-
) {
451-
container = container.parentElement;
452-
}
453-
if (container) {
454-
container = container.firstElementChild
455-
?.firstElementChild as HTMLElement;
456-
}
457-
let node;
458-
if (container.firstElementChild) {
459-
const pos = view.posAtDOM(container.firstElementChild, 0);
460-
const $pos = view.state.doc.resolve(pos);
461-
node = $pos.node();
462-
}
463-
464-
return {
465-
node: node,
466-
el: container as HTMLElement,
467-
};
468-
},
469-
};
470-
},
471-
}
472-
}
473-
```
474-
475496
## 实现案例
476497

477498
- [https://github.com/halo-sigs/plugin-hybrid-edit-block](https://github.com/halo-sigs/plugin-hybrid-edit-block)
810 KB
Loading

0 commit comments

Comments
 (0)