import { store, isCurrentUserContextTag } from "@/store"; import { render } from "solid-js/web"; import tippy, { type Instance as TippyInstance } from "tippy.js"; import { MentionList } from "@/components/MentionList"; import { buildShareTag } from "@/lib/tags"; export const userSuggestion = { items: ({ query }: { query: string }) => { return store.contexts .filter(context => context.kind === "user" && !context.deletedAt) .filter(context => !isCurrentUserContextTag(buildShareTag(context.displayName))) .filter(context => context.displayName.toLowerCase().startsWith(query.toLowerCase())) .map(context => ({ id: buildShareTag(context.displayName), label: context.displayName, type: 'user' as const })); }, render: () => { let componentDispose: (() => void) | undefined; let popup: TippyInstance | undefined; let container: HTMLDivElement | undefined; let componentHandlers: { onKeyDown: (e: KeyboardEvent) => boolean } | undefined; return { onStart: (props: any) => { container = document.createElement("div"); componentDispose = render( () => componentHandlers = h} />, container ); popup = tippy("body", { getReferenceClientRect: props.clientRect, appendTo: () => props.editor.options.element || document.body, content: container, showOnCreate: true, interactive: true, trigger: "manual", placement: "bottom-start", })[0]; }, onUpdate(props: any) { if (componentDispose) componentDispose(); componentDispose = render( () => componentHandlers = h} />, container! ); if (props.clientRect) { popup?.setProps({ getReferenceClientRect: props.clientRect, }); } }, onKeyDown(props: any) { if (props.event.key === "Escape") { popup?.hide(); return true; } return componentHandlers?.onKeyDown(props.event) ?? false; }, onExit() { if (popup && !popup.state.isDestroyed) { popup.destroy(); } popup = undefined; if (componentDispose) { componentDispose(); componentDispose = undefined; } }, }; }, }; export const noteSuggestion = { char: '#', items: ({ query }: { query: string }) => { return store.notes .filter(note => !(note.tags || []).some(t => t.startsWith("child-of-"))) .filter(note => (note.key || note.title).toLowerCase().includes(query.toLowerCase())) .map(note => ({ id: note.id, label: note.key || note.title, sublabel: note.content?.substring(0, 50).replace(/<[^>]*>?/gm, ''), type: 'note' as const })); }, render: userSuggestion.render, // Share the same renderer };