Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggestion.ts #5057

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 95 additions & 45 deletions demos/src/Examples/Community/React/suggestion.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,118 @@
import { ReactRenderer } from '@tiptap/react'
import tippy from 'tippy.js'
import { ReactRenderer } from '@tiptap/react';
import tippy from 'tippy.js';
import MentionList from './MentionList'

interface SuggestionProps {
query: string;
editor: any;
clientRect?: (() => DOMRect | null) | null | undefined;
}

import { MentionList } from './MentionList.jsx'

export default {
items: ({ query }) => {
interface MentionListRef {
onKeyDown: (props: { event: KeyboardEvent }) => boolean;
}

const suggestions = {
items: ({ query }: { query: string }) => {
return [
'Lea Thompson', 'Cyndi Lauper', '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)
'Lea Thompson',
'Cyndi Lauper',
'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);
},

render: () => {
let reactRenderer
let popup
let component: ReactRenderer | null = null;
let popup: any; // no types in docs

return {
onStart: props => {
onStart: (props: SuggestionProps) => {
component = new ReactRenderer(MentionList, {
props,
editor: props.editor,
});

if (!props.clientRect) {
return
return;
}

reactRenderer = new ReactRenderer(MentionList, {
props,
editor: props.editor,
})

popup = tippy('body', {
getReferenceClientRect: props.clientRect,
appendTo: () => document.body,
content: reactRenderer.element,
showOnCreate: true,
interactive: true,
trigger: 'manual',
placement: 'bottom-start',
})
popup = tippy(document.body, {
getReferenceClientRect: () => {
// Check if props.clientRect is a function and call it, using the result if it's not null
const rect = props.clientRect ? props.clientRect() : null;
// If the rect is null (either because props.clientRect was not a function or it returned null),
// fallback to the document.body's rect
return rect || document.body.getBoundingClientRect();
},
appendTo: () => document.body,
content: component.element,
showOnCreate: true,
interactive: true,
trigger: 'manual',
placement: 'bottom-start',
});
},

onUpdate(props) {
reactRenderer.updateProps(props)

if (!props.clientRect) {
return
onUpdate: (props: SuggestionProps) => {
if (component) {
component.updateProps(props);
}

popup[0].setProps({
getReferenceClientRect: props.clientRect,
})
if (popup && props.clientRect) {
popup[0].setProps({
getReferenceClientRect: () => props.clientRect,
});
}
},

onKeyDown(props) {
onKeyDown: (props: { event: KeyboardEvent }) => {
if (props.event.key === 'Escape') {
popup[0].hide()

return true
if (popup) {
popup[0].hide();
}
return true;
}

return reactRenderer.ref?.onKeyDown(props)
},

onExit() {
popup[0].destroy()
reactRenderer.destroy()
},
}
// Adjusted to type assert `component.ref` as `MentionListRef`
return component?.ref ? (component.ref as MentionListRef).onKeyDown(props) : false; },

onExit: () => {
// Directly call destroy on popup if it exists, without treating it as an array
if (popup) {
popup.destroy();
}
if (component) {
component.destroy();
}
},
};
},
}
};

export default suggestions;