import type { ReactElement } from 'react'; import React, { useCallback, useEffect, useState } from 'react'; import { View } from 'react-native'; import { useTheme } from '../../theme'; import { emitter } from './EditorEvent'; import * as Events from './utils/events'; const isEmptyString = (s: string | null): boolean => !s || s.length === 0; interface OnSelectOptionsType { highlighted: boolean; meta?: TMetaData; } export interface MentionListProps { /** * Unique name used to communicate with webview, should be the same with the RichTextEditor component it used with */ name: string; /** * Function used to render mention options */ render: ( searchText: string, onSelect: ( id: string, name: string, options?: OnSelectOptionsType ) => void ) => ReactElement; } const MentionList = ({ name: eventPrefix, render, }: MentionListProps) => { const theme = useTheme(); const [search, setSearch] = useState(''); const [target, setTarget] = useState(null); const normalizeEventName = useCallback( (event: string) => `${eventPrefix}/${event}`, [eventPrefix] ); useEffect(() => { const removeMentionSearchListener = Events.on( emitter, normalizeEventName('mention-search'), ({ search: nextSearch, target: nextTarget, }: { search?: string; target?: string; }) => { setSearch(nextSearch || ''); setTarget(nextTarget || null); } ); return () => { removeMentionSearchListener(); }; }, []); if (isEmptyString(search)) { return null; } return ( {render(search, (id, name, options = { highlighted: false }) => { const { highlighted, meta } = options; const highlightStyle = { color: theme.colors.primary, borderRadius: theme.__hd__.richTextEditor.radii.mention, padding: highlighted ? theme.__hd__.richTextEditor.space.mention : 0, background: highlighted ? theme.colors.highlightedSurface : 'transparent', marginTop: theme.space.xxsmall, marginBottom: theme.space.xxsmall, display: 'inline-flex', }; const data = { id, name, target, meta, style: highlightStyle, }; Events.emit(emitter, normalizeEventName('mention-apply'), data); })} ); }; export default MentionList;