Files
TasGrid/src/lib/mention-suggestion.tsx
T

104 lines
3.5 KiB
TypeScript

import { store } from "@/store";
import { render } from "solid-js/web";
import tippy, { type Instance as TippyInstance } from "tippy.js";
import { MentionList } from "@/components/MentionList";
export const userSuggestion = {
items: ({ query }: { query: string }) => {
return store.tagDefinitions
.filter(tag => tag.isUser && tag.name.toLowerCase().substring(1).startsWith(query.toLowerCase()))
.map(tag => ({
id: tag.name, // Use the tag name as ID for sharing logic
label: tag.name.substring(1),
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(
() => <MentionList
items={props.items}
command={props.command}
ref={(h) => 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(
() => <MentionList
items={props.items}
command={props.command}
ref={(h) => 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.title.toLowerCase().includes(query.toLowerCase()))
.map(note => ({
id: note.id,
label: note.title,
sublabel: note.content?.substring(0, 50).replace(/<[^>]*>?/gm, ''),
type: 'note' as const
}));
},
render: userSuggestion.render, // Share the same renderer
};