feat: add mention support

This commit is contained in:
开源海哥 2023-11-12 10:35:54 +08:00
parent c26d72f6e0
commit 563617d272
4 changed files with 50 additions and 29 deletions

View File

@ -12,5 +12,14 @@ new AiEditor({
...config
}
}
},
onMentionQuery:(query)=>{
return [
'Michael Yang', 'Jean Zhou', 'Tom Cruise', 'Madonna', 'Jerry Hall', 'Joan Collins', 'Winona Ryder'
, 'Christina Applegate', 'Alyssa Milano', 'Molly Ringwald', 'Ally Sheedy', 'Debbie Harry', 'Olivia Newton-John'
, 'Elton John', 'Michael J. Fox', 'Axl Rose', 'Emilio Estevez', 'Ralph Macchio', 'Rob Lowe', 'Jennifer Grey'
, 'Mickey Rourke', 'John Cusack', 'Matthew Broderick', 'Justine Bateman', 'Lisa Bonet',
].filter(item => item.toLowerCase().startsWith(query.toLowerCase())).slice(0, 5)
}
})

View File

@ -9,7 +9,7 @@ export const createMention = (onMentionLoad: (query: string) => any[] | Promise<
},
suggestion: {
items: ({query}) => {
return onMentionLoad(query)
return onMentionLoad(query)
},
render: () => {
@ -17,33 +17,41 @@ export const createMention = (onMentionLoad: (query: string) => any[] | Promise<
let popup: Instance[];
let selectIndex: number = 0;
let suggestionProps: SuggestionProps;
const updateElement = () => {
element.innerHTML = `
<div class="items">
${suggestionProps.items.map((item: any, index) => {
return `<button class="item ${index === selectIndex ? 'item-selected' : ''}" data-index="${index}"> @${item.name ? item.name : item}</button>`
}).join("")}
</div>
`
element.addEventListener("click", (e) => {
const closest = (e.target as HTMLElement).closest(".item");
if (closest) {
const selectIndex = Number(closest.getAttribute("data-index"));
const item = suggestionProps.items[selectIndex];
if (item) suggestionProps.command(item)
}
})
}
return {
onStart: (props: SuggestionProps) => {
element = document.createElement("div") as HTMLDivElement;
element.style.width = "200px"
element.style.height = "200px"
element.style.border = "solid 1px #ccc"
element.style.background = "antiquewhite"
element.classList.add("suggestion")
suggestionProps = props;
element.innerHTML = `
<div className="items">
${props.items.map((item: any) => {
return `<button>${item}</button>`
}).join("")}
</div>
`
console.log("onStart: ", props)
if (!props.clientRect) {
return
}
updateElement();
// @ts-ignore
popup = tippy('body', {
getReferenceClientRect: props.clientRect,
appendTo: () => document.body,
appendTo: () => props.editor.view.dom.closest(".aie-container"),
content: element,
showOnCreate: true,
interactive: true,
@ -51,43 +59,42 @@ export const createMention = (onMentionLoad: (query: string) => any[] | Promise<
trigger: 'manual',
placement: 'bottom-start',
})
suggestionProps = props;
},
onUpdate(props) {
suggestionProps = props;
element.innerHTML = `
<div className="items">
${props.items.map((item: any) => {
return `<button>${item}</button>`
}).join("")}
</div>
`
if (!props.clientRect) {
return
}
updateElement()
popup[0].setProps({
getReferenceClientRect: props.clientRect as any,
})
},
onKeyDown(props) {
if (props.event.key === 'Escape') {
popup[0].hide();
return true;
} else if (props.event.key === "ArrowUp") {
selectIndex = (selectIndex + suggestionProps.items.length - 1) % suggestionProps.items.length
updateElement();
return true;
} else if (props.event.key === "ArrowDown") {
selectIndex = (selectIndex + 1) % suggestionProps.items.length
updateElement();
return true;
} else if (props.event.key === "Enter") {
const item = suggestionProps.items[selectIndex];
if (item) suggestionProps.command({id: item})
if (item && item.id) {
suggestionProps.command(item)
} else {
suggestionProps.command({id: item})
}
return true;
}
return false;

View File

@ -171,6 +171,12 @@
.align-center {
text-align: center;
}
span[data-type="mention"]{
border: 1px solid #cccccc;
border-radius: 5px;
padding: 0 3px;
}
}
.tableWrapper {

View File

@ -77,8 +77,7 @@
.suggestion {
background: var(--aie-menus-bg-color);
border: 1px solid var(--aie-dropdown-container-border-color);
height: 146px;
width: 110px;
min-width: 100px;
.items {
.item {
@ -90,7 +89,7 @@
background: var(--aie-menus-bg-color);
border: none;
text-align: left;
padding-left: 20px;
padding: 0 10px;
cursor: pointer;
}