Editor User Mention Provider

Hello Community,

I’m using the atlaskit editor within my own confluence cloud application. I followed the examples on Editor core and tried to use the editor with mentions. At the example on the page and in the source files the mentionProvider is always a mocked object i.E

const mentionProvider = Promise.resolve({
  shouldHighlightMention(mention: { id: string }) {
    return mention.id === 'ABCDE-ABCDE-ABCDE-ABCDE';
  },
} as MentionProvider);

i copied the code above and pass it as an argument to the editors mentionProvider prop, but nothing happend.
Is there a way to provide an example implementation which uses Ap.request() to fetch users from the current instance.

I would be very grateful if you can can help me.

kind regards :slight_smile:

1 Like

bump !!

Hi @NikoReimann,

Here is a minimal example of a mention provider that should actually give you a dropdown menu when you type @

You should be able to update this to make requests for mention users in the filter function (I’m not sure what Ap.request() is, but I am going to assume some API request to get a list of mention users)

interface Mention {
  id: string;
  avatarUrl: string;
  name: string;
  mentionName: string;
  nickname: string;
}

type MentionResultCallback = (result: Mention[], query: string) => void;
type ErrorCallback = (error: Error, query: string) => void;

const mockMentions: Mention[] = [
  {
    id: 'abcd',
    avatarUrl: 'https://ichef.bbci.co.uk/images/ic/640x360/p05cljhh.jpg',
    name: 'Taylor Swift',
    mentionName: 'tay',
    nickname: 'taytay',
  },
];

class MyMentionProvider {
  private changeListeners: Map<string, MentionResultCallback>;
  private errorListeners: Map<string, ErrorCallback>;

  constructor() {
    this.changeListeners = new Map<string, MentionResultCallback>();
    this.errorListeners = new Map<string, ErrorCallback>();
  }

  subscribe(
    key: string,
    mentionResultCallback?: MentionResultCallback,
    errorCallback?: ErrorCallback,
  ) {
    if (mentionResultCallback) {
      this.changeListeners.set(key, mentionResultCallback);
    }
    if (errorCallback) {
      this.errorListeners.set(key, errorCallback);
    }
  }

  unsubscribe(key: string) {
    this.changeListeners.delete(key);
    this.errorListeners.delete(key);
  }

  filter = (query: string) => {
    // this must be async, mocking that here
    setTimeout(() => {
      let results: Mention[];
      if (!query) {
        results = mockMentions;
      } else {
        results = mockMentions.filter(
          mention =>
            mention.name.indexOf(query) || mention.mentionName.indexOf(query),
        );
      }
      this.changeListeners.forEach(listener => {
        listener(results, query);
      });
    }, 0);
    return Promise.resolve();
  };
}

And then can set the prop on the editor component like

const myMentionProvider = new MyMentionProvider();
const mentionProvider = Promise.resolve(myMentionProvider);

<Editor ...
  mentionProvider={mentionProvider}
/>
2 Likes

Thank you so much @heather. What should be the behaviour of recordMentionSelection, it throw a error if the provider doesn’t have this one.

Hi @CarlosSandoval, there are a few methods I left out that you’ll need for typescript to not complain, but these can just be left as empty methods:

  recordMentionSelection(mention: Mention): void {}

  shouldHighlightMention(mention: Mention): boolean {
    return false;
  }

  isFiltering(query: string): boolean {
    return false;
  }
2 Likes

Thank you @heather, It is really helpful.