+ {!contracts.length ? (
+
No results...
+ ) : (
+ contracts.map((contract, i) => (
+
+ ))
+ )}
+
+ )
+})
+
+// Just to keep the formatting pretty
+export { M as MentionList }
diff --git a/web/components/editor/contract-mention-suggestion.ts b/web/components/editor/contract-mention-suggestion.ts
new file mode 100644
index 00000000..79525cfc
--- /dev/null
+++ b/web/components/editor/contract-mention-suggestion.ts
@@ -0,0 +1,76 @@
+import type { MentionOptions } from '@tiptap/extension-mention'
+import { ReactRenderer } from '@tiptap/react'
+import { searchInAny } from 'common/util/parse'
+import { orderBy } from 'lodash'
+import tippy from 'tippy.js'
+import { getCachedContracts } from 'web/hooks/use-contracts'
+import { MentionList } from './contract-mention-list'
+import { PluginKey } from 'prosemirror-state'
+
+type Suggestion = MentionOptions['suggestion']
+
+const beginsWith = (text: string, query: string) =>
+ text.toLocaleLowerCase().startsWith(query.toLocaleLowerCase())
+
+// copied from https://tiptap.dev/api/nodes/mention#usage
+// TODO: merge with mention-suggestion.ts?
+export const contractMentionSuggestion: Suggestion = {
+ char: '%',
+ allowSpaces: true,
+ pluginKey: new PluginKey('contract-mention'),
+ items: async ({ query }) =>
+ orderBy(
+ (await getCachedContracts()).filter((c) =>
+ searchInAny(query, c.question)
+ ),
+ [(c) => [c.question].some((s) => beginsWith(s, query))],
+ ['desc', 'desc']
+ ).slice(0, 5),
+ render: () => {
+ let component: ReactRenderer
+ let popup: ReturnType