import type { MentionOptions } from '@tiptap/extension-mention' import { ReactRenderer } from '@tiptap/react' import { User } from 'common/lib/user' import { searchInAny } from 'common/util/parse' import tippy from 'tippy.js' import { MentionList } from './mention-list' type Suggestion = MentionOptions['suggestion'] // copied from https://tiptap.dev/api/nodes/mention#usage export const mentionSuggestion = (users: User[]): Suggestion => ({ items: ({ query }) => users.filter((u) => searchInAny(query, u.username, u.name)).slice(0, 5), render: () => { let component: ReactRenderer let popup: ReturnType return { onStart: (props) => { component = new ReactRenderer(MentionList, { props, editor: props.editor, }) if (!props.clientRect) { return } popup = tippy('body', { getReferenceClientRect: props.clientRect as any, appendTo: () => document.body, content: component.element, showOnCreate: true, interactive: true, trigger: 'manual', placement: 'bottom-start', }) }, onUpdate(props) { component.updateProps(props) if (!props.clientRect) { return } popup[0].setProps({ getReferenceClientRect: props.clientRect as any, }) }, onKeyDown(props) { if (props.event.key === 'Escape') { popup[0].hide() return true } return (component.ref as any)?.onKeyDown(props) }, onExit() { popup[0].destroy() component.destroy() }, } }, })