Browse Source

fix mentions

imwald
Silberengel 1 month ago
parent
commit
ffb10ac645
  1. 15
      src/components/PostEditor/PostTextarea/Emoji/EmojiList.tsx
  2. 17
      src/components/PostEditor/PostTextarea/Mention/MentionList.tsx
  3. 3
      src/components/PostEditor/PostTextarea/Mention/suggestion.ts
  4. 5
      src/components/TextareaWithMentionAutocomplete/index.tsx

15
src/components/PostEditor/PostTextarea/Emoji/EmojiList.tsx

@ -14,10 +14,11 @@ export interface EmojiListHandler {
} }
export const EmojiList = forwardRef<EmojiListHandler, EmojiListProps>((props, ref) => { export const EmojiList = forwardRef<EmojiListHandler, EmojiListProps>((props, ref) => {
const items = props.items ?? []
const [selectedIndex, setSelectedIndex] = useState(0) const [selectedIndex, setSelectedIndex] = useState(0)
const selectItem = (index: number): void => { const selectItem = (index: number): void => {
const item = props.items[index] const item = items[index]
if (item) { if (item) {
props.command({ name: item }) props.command({ name: item })
@ -27,18 +28,20 @@ export const EmojiList = forwardRef<EmojiListHandler, EmojiListProps>((props, re
} }
const upHandler = (): void => { const upHandler = (): void => {
setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length) if (!items.length) return
setSelectedIndex((selectedIndex + items.length - 1) % items.length)
} }
const downHandler = (): void => { const downHandler = (): void => {
setSelectedIndex((selectedIndex + 1) % props.items.length) if (!items.length) return
setSelectedIndex((selectedIndex + 1) % items.length)
} }
const enterHandler = (): void => { const enterHandler = (): void => {
selectItem(selectedIndex) selectItem(selectedIndex)
} }
useEffect(() => setSelectedIndex(props.items.length ? 0 : -1), [props.items]) useEffect(() => setSelectedIndex(items.length ? 0 : -1), [items])
useImperativeHandle(ref, () => { useImperativeHandle(ref, () => {
return { return {
@ -63,7 +66,7 @@ export const EmojiList = forwardRef<EmojiListHandler, EmojiListProps>((props, re
} }
}, [upHandler, downHandler, enterHandler]) }, [upHandler, downHandler, enterHandler])
if (!props.items?.length) { if (!items.length) {
return null return null
} }
@ -74,7 +77,7 @@ export const EmojiList = forwardRef<EmojiListHandler, EmojiListProps>((props, re
onTouchMove={(e) => e.stopPropagation()} onTouchMove={(e) => e.stopPropagation()}
> >
<div className="p-1"> <div className="p-1">
{props.items.map((item, index) => { {items.map((item, index) => {
return ( return (
<EmojiListItem <EmojiListItem
key={item} key={item}

17
src/components/PostEditor/PostTextarea/Mention/MentionList.tsx

@ -22,6 +22,7 @@ export interface MentionListHandle {
} }
const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref) => { const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref) => {
const items = props.items ?? []
const inDialog = Boolean(props.editor?.view?.dom?.closest?.('[role="dialog"]')) const inDialog = Boolean(props.editor?.view?.dom?.closest?.('[role="dialog"]'))
const [internalIndex, setInternalIndex] = useState<number>(0) const [internalIndex, setInternalIndex] = useState<number>(0)
const isControlled = props.selectedIndex !== undefined const isControlled = props.selectedIndex !== undefined
@ -29,7 +30,7 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
const setSelectedIndex = isControlled ? (n: number) => props.onSelectIndex?.(n) : setInternalIndex const setSelectedIndex = isControlled ? (n: number) => props.onSelectIndex?.(n) : setInternalIndex
const selectItem = (index: number) => { const selectItem = (index: number) => {
const item = props.items[index] const item = items[index]
if (item) { if (item) {
props.command({ id: item, label: formatNpub(item) }) props.command({ id: item, label: formatNpub(item) })
@ -37,11 +38,13 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
} }
const upHandler = () => { const upHandler = () => {
setSelectedIndex((selectedIndex + props.items.length - 1) % props.items.length) if (!items.length) return
setSelectedIndex((selectedIndex + items.length - 1) % items.length)
} }
const downHandler = () => { const downHandler = () => {
setSelectedIndex((selectedIndex + 1) % props.items.length) if (!items.length) return
setSelectedIndex((selectedIndex + 1) % items.length)
} }
const enterHandler = () => { const enterHandler = () => {
@ -50,9 +53,9 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
useEffect(() => { useEffect(() => {
if (!isControlled) { if (!isControlled) {
setInternalIndex(props.items.length ? 0 : -1) setInternalIndex(items.length ? 0 : -1)
} }
}, [props.items, isControlled]) }, [items, isControlled])
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
onKeyDown: ({ event }: SuggestionKeyDownProps) => { onKeyDown: ({ event }: SuggestionKeyDownProps) => {
@ -75,7 +78,7 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
} }
})) }))
if (!props.items?.length) { if (!items.length) {
return null return null
} }
@ -88,7 +91,7 @@ const MentionList = forwardRef<MentionListHandle, MentionListProps>((props, ref)
onWheel={(e: React.WheelEvent) => e.stopPropagation()} onWheel={(e: React.WheelEvent) => e.stopPropagation()}
onTouchMove={(e: React.TouchEvent) => e.stopPropagation()} onTouchMove={(e: React.TouchEvent) => e.stopPropagation()}
> >
{props.items.map((item, index) => ( {items.map((item, index) => (
<button <button
className={cn( className={cn(
'cursor-pointer text-start items-center m-1 p-2 outline-none transition-colors [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 rounded-md', 'cursor-pointer text-start items-center m-1 p-2 outline-none transition-colors [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 rounded-md',

3
src/components/PostEditor/PostTextarea/Mention/suggestion.ts

@ -8,7 +8,8 @@ import MentionList, { MentionListHandle, MentionListProps } from './MentionList'
const suggestion = { const suggestion = {
items: async ({ query }: { query: string }) => { items: async ({ query }: { query: string }) => {
return await client.searchNpubsFromLocal(query, 20) const result = await client.searchNpubsFromLocal(query, 20)
return result ?? []
}, },
render: () => { render: () => {

5
src/components/TextareaWithMentionAutocomplete/index.tsx

@ -69,8 +69,9 @@ const TextareaWithMentionAutocomplete = forwardRef<HTMLTextAreaElement, Textarea
client client
.searchNpubsFromLocal(mentionQuery.trim(), MENTION_LIMIT) .searchNpubsFromLocal(mentionQuery.trim(), MENTION_LIMIT)
.then((npubs) => { .then((npubs) => {
setMentionItems(npubs) const list = npubs ?? []
setMentionOpen(npubs.length > 0) setMentionItems(list)
setMentionOpen(list.length > 0)
setSelectedIndex(0) setSelectedIndex(0)
}) })
.catch(() => { .catch(() => {

Loading…
Cancel
Save