move suggestion list code to separate file

This commit is contained in:
Sinclair Chen 2022-07-20 17:02:23 -07:00
parent c04e36e3fe
commit 3a61ddaee7
3 changed files with 65 additions and 58 deletions

View File

@ -7,7 +7,6 @@ import {
JSONContent, JSONContent,
Content, Content,
Editor, Editor,
ReactRenderer,
} from '@tiptap/react' } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit' import StarterKit from '@tiptap/starter-kit'
import { Image } from '@tiptap/extension-image' import { Image } from '@tiptap/extension-image'
@ -18,12 +17,11 @@ import { useEffect } from 'react'
import { Linkify } from './linkify' import { Linkify } from './linkify'
import { uploadImage } from 'web/lib/firebase/storage' import { uploadImage } from 'web/lib/firebase/storage'
import { useMutation } from 'react-query' import { useMutation } from 'react-query'
import { exhibitExts, searchInAny } from 'common/util/parse' import { exhibitExts } from 'common/util/parse'
import { FileUploadButton } from './file-upload-button' import { FileUploadButton } from './file-upload-button'
import { linkClass } from './site-link' import { linkClass } from './site-link'
import { useUsers } from 'web/hooks/use-users' import { useUsers } from 'web/hooks/use-users'
import { MentionList } from './editor/mention-list' import { mentionSuggestion } from './editor/mention-suggestion'
import tippy from 'tippy.js'
const proseClass = clsx( const proseClass = clsx(
'prose prose-p:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless leading-relaxed', 'prose prose-p:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless leading-relaxed',
@ -75,59 +73,7 @@ export function useTextEditor(props: {
{ href: node.attrs.label }, { href: node.attrs.label },
`${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`, `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`,
] as any, ] as any,
suggestion: { suggestion: mentionSuggestion(users),
items: ({ query }) =>
users
.filter((u) => searchInAny(query, u.username, u.name))
.slice(0, 5),
render: () => {
let component: any
let popup: any
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,
})
},
onKeyDown(props) {
if (props.event.key === 'Escape') {
popup[0].hide()
return true
}
return component.ref?.onKeyDown(props)
},
onExit() {
popup[0].destroy()
component.destroy()
},
}
},
},
}), }),
], ],
content: defaultValue, content: defaultValue,

View File

@ -4,7 +4,7 @@ import { User } from 'common/user'
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react' import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
import { Avatar } from '../avatar' import { Avatar } from '../avatar'
// copied from https://tiptap.dev/api/nodes/mention // copied from https://tiptap.dev/api/nodes/mention#usage
export const MentionList = forwardRef((props: SuggestionProps<User>, ref) => { export const MentionList = forwardRef((props: SuggestionProps<User>, ref) => {
const { items: users, command } = props const { items: users, command } = props

View File

@ -0,0 +1,61 @@
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: any
let popup: any
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,
})
},
onKeyDown(props) {
if (props.event.key === 'Escape') {
popup[0].hide()
return true
}
return component.ref?.onKeyDown(props)
},
onExit() {
popup[0].destroy()
component.destroy()
},
}
},
})