export function MentionList()

in translate/src/modules/comments/components/MentionList.tsx [17:111]


export function MentionList({
  editor,
  index,
  onSelect,
  suggestedUsers,
  target,
}: Props): React.ReactPortal | null {
  const ref = useRef<HTMLDivElement>(null);
  const [scrollPosition, setScrollPosition] = useState(0);

  // Set position of mentions suggestions
  useLayoutEffect(() => {
    try {
      if (ref.current) {
        const range = ReactEditor.toDOMRange(editor, target);
        setMentionListStyle(ref.current, range);
      }
    } catch (error) {
      // https://github.com/mozilla/pontoon/issues/2298
      // toDOMRange may fail on e.g. paste events, as the onChange may be
      // triggered before the DOM is updated. In that case, ignore the error
      // and let the next render fix things if necessary.
    }
  }, [editor, suggestedUsers.length, target, scrollPosition]);

  // Set scroll position values for Translation and Team Comment containers ~
  // This allows for the mention suggestions to stay properly positioned
  // when the container scrolls.
  useEffect(() => {
    const handleScroll = (e: Event) => {
      const element = e.currentTarget as HTMLElement;
      setScrollPosition(element.scrollTop);
    };

    const historyScroll = document.querySelector('#history-list');
    const teamsScroll = document.querySelector('#react-tabs-3');
    if (historyScroll || teamsScroll) {
      historyScroll?.addEventListener('scroll', handleScroll);
      teamsScroll?.addEventListener('scroll', handleScroll);

      return () => {
        historyScroll?.removeEventListener('scroll', handleScroll);
        teamsScroll?.removeEventListener('scroll', handleScroll);
      };
    }
  }, []);

  const setStyleForHover = (ev: React.MouseEvent<HTMLDivElement>) => {
    ev.preventDefault();
    ev.currentTarget.children[index].className = 'mention';
  };

  const removeStyleForHover = (ev: React.MouseEvent<HTMLDivElement>) => {
    ev.preventDefault();
    ev.currentTarget.children[index].className = 'mention active-mention';
  };

  return document.body && suggestedUsers.length > 0
    ? createPortal(
        <div
          ref={ref}
          className='comments-mention-list'
          onMouseEnter={setStyleForHover}
          onMouseLeave={removeStyleForHover}
        >
          {suggestedUsers.map((user, i) => (
            <div
              key={user.name}
              className={i === index ? 'mention active-mention' : 'mention'}
              onMouseDown={(ev) => {
                ev.preventDefault();
                onSelect(user);
              }}
            >
              <Localized
                id='comments-AddComment--mention-avatar-alt'
                attrs={{ alt: true }}
              >
                <span className='user-avatar'>
                  <img
                    src={user.gravatar}
                    alt='User Avatar'
                    width={22}
                    height={22}
                  />
                </span>
              </Localized>
              <span className='name'>{user.name}</span>
            </div>
          ))}
        </div>,
        document.body,
      )
    : null;
}