mirror of https://github.com/fantasticit/think.git
support multi bubble-menu
parent
5a1a5c7c1a
commit
d25ad50117
|
@ -27,6 +27,8 @@ export type BubbleMenuViewProps = BubbleMenuPluginProps & {
|
|||
view: EditorView;
|
||||
};
|
||||
|
||||
const ACTIVE_BUBBLE_MENUS: Instance[] = [];
|
||||
|
||||
export class BubbleMenuView {
|
||||
public editor: Editor;
|
||||
|
||||
|
@ -178,7 +180,11 @@ export class BubbleMenuView {
|
|||
const cursorAt = selection.$anchor.pos;
|
||||
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
||||
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
||||
const placement = Math.abs(cursorAt - to) <= Math.abs(cursorAt - from) ? 'bottom' : 'top';
|
||||
const placement = isNodeSelection(selection)
|
||||
? 'top'
|
||||
: Math.abs(cursorAt - to) <= Math.abs(cursorAt - from)
|
||||
? 'bottom-start'
|
||||
: 'top-start';
|
||||
const domAtPos = view.domAtPos(from).node as HTMLElement;
|
||||
const nodeDOM = view.nodeDOM(from) as HTMLElement;
|
||||
const node = nodeDOM || domAtPos;
|
||||
|
@ -200,7 +206,28 @@ export class BubbleMenuView {
|
|||
return;
|
||||
}
|
||||
|
||||
const otherBubbleMenus = ACTIVE_BUBBLE_MENUS.filter(
|
||||
(instance) => instance.id !== this.tippy?.id && instance.popperInstance && instance.popperInstance.state
|
||||
);
|
||||
const offsetX = this.tippyOptions?.offset?.[0] ?? 0;
|
||||
const offsetY = otherBubbleMenus.length
|
||||
? otherBubbleMenus.reduce((prev, instance, currentIndex, array) => {
|
||||
const prevY = array[currentIndex - 1]
|
||||
? array[currentIndex - 1]?.popperInstance?.state?.modifiersData?.popperOffsets?.y ?? 0
|
||||
: 0;
|
||||
const currentY = instance?.popperInstance?.state?.modifiersData?.popperOffsets?.y ?? 0;
|
||||
const currentHeight = instance?.popperInstance?.state?.rects?.popper?.height ?? 40;
|
||||
|
||||
if (Math.abs(prevY - currentY) <= currentHeight) {
|
||||
prev += currentHeight;
|
||||
}
|
||||
|
||||
return prev;
|
||||
}, 0)
|
||||
: this.tippyOptions?.offset?.[1] ?? 10;
|
||||
|
||||
this.tippy?.setProps({
|
||||
offset: [offsetX, offsetY],
|
||||
placement,
|
||||
getReferenceClientRect: () => {
|
||||
let toMountNode = null;
|
||||
|
@ -230,15 +257,31 @@ export class BubbleMenuView {
|
|||
this.show();
|
||||
}
|
||||
|
||||
addActiveBubbleMenu = () => {
|
||||
const idx = ACTIVE_BUBBLE_MENUS.findIndex((instance) => instance?.id === this.tippy?.id);
|
||||
if (idx < 0) {
|
||||
ACTIVE_BUBBLE_MENUS.push(this.tippy);
|
||||
}
|
||||
};
|
||||
|
||||
removeActiveBubbleMenu = () => {
|
||||
const idx = ACTIVE_BUBBLE_MENUS.findIndex((instance) => instance?.id === this.tippy?.id);
|
||||
if (idx > -1) {
|
||||
ACTIVE_BUBBLE_MENUS.splice(idx, 1);
|
||||
}
|
||||
};
|
||||
show() {
|
||||
this.addActiveBubbleMenu();
|
||||
this.tippy?.show();
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.removeActiveBubbleMenu();
|
||||
this.tippy?.hide();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.removeActiveBubbleMenu();
|
||||
this.tippy?.destroy();
|
||||
this.element.removeEventListener('mousedown', this.mousedownHandler, {
|
||||
capture: true,
|
||||
|
|
Loading…
Reference in New Issue