improve bubble-menu placement

This commit is contained in:
fantasticit 2022-11-28 17:33:30 +08:00
parent b2a485e513
commit 1d32808335
3 changed files with 26 additions and 8 deletions

View File

@ -19,9 +19,8 @@ export interface BubbleMenuPluginProps {
to?: number; to?: number;
}) => boolean) }) => boolean)
| null; | null;
renderContainerSelector?: string;
matchRenderContainer?: (node: HTMLElement) => boolean;
getRenderContainer?: (node: HTMLElement) => HTMLElement; getRenderContainer?: (node: HTMLElement) => HTMLElement;
defaultAnimation?: boolean;
} }
export type BubbleMenuViewProps = BubbleMenuPluginProps & { export type BubbleMenuViewProps = BubbleMenuPluginProps & {
@ -43,6 +42,8 @@ export class BubbleMenuView {
public getRenderContainer?: BubbleMenuPluginProps['getRenderContainer']; public getRenderContainer?: BubbleMenuPluginProps['getRenderContainer'];
public defaultAnimation?: BubbleMenuPluginProps['defaultAnimation'];
public shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null> = ({ view, state, from, to }) => { public shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null> = ({ view, state, from, to }) => {
const { doc, selection } = state; const { doc, selection } = state;
const { empty } = selection; const { empty } = selection;
@ -59,11 +60,20 @@ export class BubbleMenuView {
return true; return true;
}; };
constructor({ editor, element, view, tippyOptions = {}, shouldShow, getRenderContainer }: BubbleMenuViewProps) { constructor({
editor,
element,
view,
tippyOptions = {},
shouldShow,
getRenderContainer,
defaultAnimation = true,
}: BubbleMenuViewProps) {
this.editor = editor; this.editor = editor;
this.element = element; this.element = element;
this.view = view; this.view = view;
this.getRenderContainer = getRenderContainer; this.getRenderContainer = getRenderContainer;
this.defaultAnimation = defaultAnimation;
if (shouldShow) { if (shouldShow) {
this.shouldShow = shouldShow; this.shouldShow = shouldShow;
@ -133,7 +143,13 @@ export class BubbleMenuView {
placement: 'top', placement: 'top',
hideOnClick: 'toggle', hideOnClick: 'toggle',
...Object.assign( ...Object.assign(
{ zIndex: 999, duration: 200, animation: 'shift-toward-subtle', moveTransition: 'transform 0.2s ease-in-out' }, {
zIndex: 999,
duration: 200,
...(this.defaultAnimation
? { animation: 'shift-toward-subtle', moveTransition: 'transform 0.2s ease-in-out' }
: {}),
},
this.tippyOptions this.tippyOptions
), ),
}); });
@ -159,8 +175,10 @@ export class BubbleMenuView {
// support for CellSelections // support for CellSelections
const { ranges } = selection; const { ranges } = selection;
const cursorAt = selection.$anchor.pos;
const from = Math.min(...ranges.map((range) => range.$from.pos)); const from = Math.min(...ranges.map((range) => range.$from.pos));
const to = Math.max(...ranges.map((range) => range.$to.pos)); const to = Math.max(...ranges.map((range) => range.$to.pos));
const placement = Math.abs(cursorAt - to) <= Math.abs(cursorAt - from) ? 'bottom' : 'top';
const domAtPos = view.domAtPos(from).node as HTMLElement; const domAtPos = view.domAtPos(from).node as HTMLElement;
const nodeDOM = view.nodeDOM(from) as HTMLElement; const nodeDOM = view.nodeDOM(from) as HTMLElement;
const node = nodeDOM || domAtPos; const node = nodeDOM || domAtPos;
@ -183,6 +201,7 @@ export class BubbleMenuView {
} }
this.tippy?.setProps({ this.tippy?.setProps({
placement,
getReferenceClientRect: () => { getReferenceClientRect: () => {
let toMountNode = null; let toMountNode = null;

View File

@ -25,9 +25,8 @@ export const BubbleMenu: React.FC<BubbleMenuProps> = (props) => {
editor, editor,
tippyOptions = {}, tippyOptions = {},
shouldShow = null, shouldShow = null,
// renderContainerSelector,
// matchRenderContainer,
getRenderContainer, getRenderContainer,
defaultAnimation,
} = props; } = props;
const plugin = BubbleMenuPlugin({ const plugin = BubbleMenuPlugin({
@ -36,9 +35,8 @@ export const BubbleMenu: React.FC<BubbleMenuProps> = (props) => {
element, element,
tippyOptions, tippyOptions,
shouldShow, shouldShow,
// renderContainerSelector,
// matchRenderContainer,
getRenderContainer, getRenderContainer,
defaultAnimation,
}); });
editor.registerPlugin(plugin); editor.registerPlugin(plugin);

View File

@ -65,6 +65,7 @@ export const Text = ({ editor }) => {
pluginKey="text-bubble-menu" pluginKey="text-bubble-menu"
shouldShow={shouldShow} shouldShow={shouldShow}
tippyOptions={{ maxWidth: 'calc(100vw - 100px)' }} tippyOptions={{ maxWidth: 'calc(100vw - 100px)' }}
defaultAnimation={false}
> >
<Space spacing={4}> <Space spacing={4}>
<Bold editor={editor} /> <Bold editor={editor} />