Open djyadav opened 1 week ago
Hey there, @djyadav! I'm here to help you with any bugs, questions, or contributions you have. Let's tackle this issue together!
Yes, it is possible to show suggestions in the dropdown when the cursor moves inside the queryString
and not just at the end after the operator. The BeautifulMentionsPlugin
is configured to handle mentions and suggestions based on the cursor position within the queryString
.
The checkForTriggers
function is used to detect triggers based on the cursor's position within the queryString
. This function checks for potential triggers and returns the relevant match information. The ComboboxPlugin
then uses this information to show suggestions dynamically as the user types or moves the cursor within the queryString
.
Here is the relevant part of the code that handles this:
export function checkForTriggers(
text: string,
triggers: string[],
): MenuTextMatch | null {
const last = text.split(/\s/).pop() || text;
const offset = text !== last ? text.lastIndexOf(last) : 0;
const match = triggers.some((t) => t.startsWith(last) && t !== last);
if (match) {
return {
leadOffset: offset,
matchingString: last,
replaceableString: last,
};
}
return null;
}
Additionally, the ComboboxPlugin
listens for updates to the editor state and dynamically updates the suggestions based on the current position of the cursor within the queryString
:
useEffect(() => {
const updateListener = () => {
editor.getEditorState().read(() => {
const text = getQueryTextForSearch(editor);
if (text === null) {
onReset();
setTriggerMatch(null);
setValueMatch(null);
onQueryChange(null);
setTriggerQueryString(null);
return;
}
const triggerMatch = checkForTriggers(text, triggers);
setTriggerMatch(triggerMatch);
if (triggerMatch) {
setTriggerQueryString(triggerMatch.matchingString);
setValueMatch(null);
return;
}
const valueMatch = triggerFn(text, editor);
setValueMatch(valueMatch);
onQueryChange(valueMatch ? valueMatch.matchingString : null);
if (valueMatch && valueMatch.matchingString) {
setTriggerQueryString(valueMatch.matchingString);
return;
}
setTriggerQueryString(null);
});
};
return editor.registerUpdateListener(updateListener);
}, [editor, triggerFn, onQueryChange, onReset, triggers]);
This configuration ensures that suggestions are shown based on the current position of the cursor within the queryString
[1][2][3][4].
To continue talking to Dosu, mention @dosu.
Is this specific to comboBox plugin
If so, I'm not using that.
How can I show cursor aware suggestions in Menu
then ? Is there a way or missing functionality ?
To show cursor-aware suggestions in the Menu
, you can dynamically position the menu based on the cursor's position. This functionality is demonstrated in the test cases provided in the commands.spec.ts
file. Here are some relevant examples:
import { expect, test } from "@playwright/test";
import { testUtils } from "./test-utils";
test.describe("Open Suggestions", () => {
test("should open the menu at the end of the editor", async ({ page, browserName }) => {
const utils = await testUtils(
{ page, browserName },
{
initialValue: "Hey @John, the task is #urgent and due:tomorrow",
},
);
await expect(utils.mentionsMenu).not.toBeVisible();
await page.getByText("Open Suggestions").click();
await expect(utils.mentionsMenu).toBeVisible();
await utils.hasText("Hey [@John], the task is [#urgent] and [due:tomorrow] @");
});
test("should open the menu even if the editor was never focused", async ({ page, browserName }) => {
const utils = await testUtils(
{ page, browserName },
{
autofocus: "none",
initialValue: "Hey",
},
);
await expect(utils.mentionsMenu).not.toBeVisible();
await page.getByText("Open Suggestions").click();
await expect(utils.mentionsMenu).toBeVisible();
await utils.hasText("Hey @");
});
test("should open the menu at the start of the editor", async ({ page, browserName }) => {
const utils = await testUtils(
{ page, browserName },
{
autofocus: "start",
initialValue: "Hey @John, the task is #urgent and due:tomorrow",
},
);
await page.getByText("Open Suggestions").click();
await expect(utils.mentionsMenu).toBeVisible();
await utils.hasText("@ Hey [@John], the task is [#urgent] and [due:tomorrow]");
});
test("should open the menu after a word", async ({ page, browserName }) => {
const utils = await testUtils(
{ page, browserName },
{
autofocus: "start",
initialValue: "Hey @John, the task is #urgent and due:tomorrow",
},
);
await utils.moveCursorForward(3);
await page.getByText("Open Suggestions").click();
await expect(utils.mentionsMenu).toBeVisible();
await utils.hasText("Hey @ [@John], the task is [#urgent] and [due:tomorrow]");
});
test("should open the menu before a mention", async ({ page, browserName }) => {
const utils = await testUtils(
{ page, browserName },
{
autofocus: "start",
initialValue: "Hey @John, the task is #urgent and due:tomorrow",
},
);
await utils.moveCursorForward(4);
await page.getByText("Open Suggestions").click();
await expect(utils.mentionsMenu).toBeVisible();
await utils.hasText("Hey @ [@John], the task is [#urgent] and [due:tomorrow]");
});
});
Additionally, you can use the BeautifulMentionsPlugin
from the lexical-beautiful-mentions
package to handle mentions in a lexical editor. This plugin includes functionality to dynamically position the menu and show cursor-aware suggestions. Here is an example of how to use it:
import { BeautifulMentionsPlugin } from "./BeautifulMentionsPlugin";
export function MyEditor() {
return (
<LexicalComposer initialConfig={initialConfig}>
<RichTextPlugin contentEditable={<ContentEditable />} />
<BeautifulMentionsPlugin
items={mentionItems}
onSearch={handleSearch}
menuComponent={CustomMenuComponent}
menuItemComponent={CustomMenuItemComponent}
/>
</LexicalComposer>
);
}
The BeautifulMentionsPlugin
handles the dynamic positioning of the menu and provides a customizable way to show suggestions based on the cursor's position [1][2].
To continue talking to Dosu, mention @dosu.
Right now, the suggestions
dropdown
shows only when the cursor is at the end ofqueryString
after the operator. But it doesn't show when cursor moves inside the word.This is required if the user edits the query string and not just adds characters at the end. So far, I'm not able to find any alternate or approach to achieve the same. Is that really possible somehow ?
For example:
[operator]queryString[cursor]
-> Shows suggestions dropdown[operator]query[cursor]string
-> Doesn't show suggestions dropdown