build: switch from yarn to npm to manage js dependencies and move js contents to root
yarn v1 is being deprecated and starts to have some issues Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
112
src/components/Editor/Mention.ts
Normal file
112
src/components/Editor/Mention.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { SEARCH_PERSONS } from "@/graphql/search";
|
||||
import { VueRenderer } from "@tiptap/vue-3";
|
||||
import tippy from "tippy.js";
|
||||
import MentionList from "./MentionList.vue";
|
||||
import { apolloClient } from "@/vue-apollo";
|
||||
import { IPerson } from "@/types/actor";
|
||||
import pDebounce from "p-debounce";
|
||||
import { MentionOptions } from "@tiptap/extension-mention";
|
||||
import { Editor } from "@tiptap/core";
|
||||
import { provideApolloClient, useLazyQuery } from "@vue/apollo-composable";
|
||||
import { Paginate } from "@/types/paginate";
|
||||
|
||||
const fetchItems = async (query: string): Promise<IPerson[]> => {
|
||||
try {
|
||||
if (query === "") return [];
|
||||
const res = await provideApolloClient(apolloClient)(async () => {
|
||||
const { load: loadSearchPersonsQuery } = useLazyQuery<
|
||||
{ searchPersons: Paginate<IPerson> },
|
||||
{ searchText: string }
|
||||
>(SEARCH_PERSONS);
|
||||
|
||||
return await loadSearchPersonsQuery(SEARCH_PERSONS, {
|
||||
searchText: query,
|
||||
});
|
||||
});
|
||||
if (!res) return [];
|
||||
return res.searchPersons.elements;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedFetchItems = pDebounce(fetchItems, 200);
|
||||
|
||||
const mentionOptions: MentionOptions = {
|
||||
HTMLAttributes: {
|
||||
class: "mention",
|
||||
dir: "ltr",
|
||||
},
|
||||
renderLabel({ options, node }) {
|
||||
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
|
||||
},
|
||||
suggestion: {
|
||||
items: async ({
|
||||
query,
|
||||
}: {
|
||||
query: string;
|
||||
editor: Editor;
|
||||
}): Promise<IPerson[]> => {
|
||||
if (query === "") {
|
||||
return [];
|
||||
}
|
||||
return await debouncedFetchItems(query);
|
||||
},
|
||||
render: () => {
|
||||
let component: VueRenderer;
|
||||
let popup: any;
|
||||
|
||||
return {
|
||||
onStart: (props: Record<string, any>) => {
|
||||
component = new VueRenderer(MentionList, {
|
||||
props,
|
||||
editor: props.editor,
|
||||
});
|
||||
|
||||
if (!props.clientRect) {
|
||||
return;
|
||||
}
|
||||
|
||||
popup = tippy("body", {
|
||||
getReferenceClientRect: props.clientRect,
|
||||
appendTo: () => document.body,
|
||||
content: component.element,
|
||||
showOnCreate: true,
|
||||
interactive: true,
|
||||
trigger: "manual",
|
||||
placement: "bottom-start",
|
||||
});
|
||||
},
|
||||
onUpdate(props: any) {
|
||||
component.updateProps(props);
|
||||
|
||||
popup[0].setProps({
|
||||
getReferenceClientRect: props.clientRect,
|
||||
});
|
||||
},
|
||||
onKeyDown(props: any) {
|
||||
if (props.event.key === "Escape") {
|
||||
popup[0].hide();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
return component.ref?.onKeyDown(props);
|
||||
},
|
||||
onExit() {
|
||||
if (popup && popup[0]) {
|
||||
popup[0].destroy();
|
||||
}
|
||||
if (component) {
|
||||
component.destroy();
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default mentionOptions;
|
||||
Reference in New Issue
Block a user