Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lovely-pets-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@diceui/mention": minor
---

Allow mention trigger in middle of text
2 changes: 1 addition & 1 deletion packages/mention/src/mention-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ const MentionInput = React.forwardRef<InputElement, MentionInputProps>(
textAfterCursor.length > 0 &&
!isTextAfterCursorSeparated &&
!isTextAfterCursorPartOfMention;

if (hasInterferingText) {
if (context.open) {
context.onOpenChange(false);
Expand Down
34 changes: 34 additions & 0 deletions packages/mention/test/mention.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -381,4 +381,38 @@ describe("Mention", () => {
// Ensure the input now shows only the second mention
expect(input.value).toBe("and @heelflip ");
});

test("allows mention trigger in middle of text and preserves text after", async () => {
const onValueChange = vi.fn();
const onInputValueChange = vi.fn();
renderMention({ onValueChange, onInputValueChange });

const input = screen.getByPlaceholderText(placeholder);

if (!(input instanceof HTMLInputElement)) {
throw new Error("Input element not found");
}

// Add first mention
await userEvent.type(input, "@kickflip");
const kickflipOption = screen.getByRole("option", { name: "Kickflip" });
await waitFor(() => {
fireEvent.click(kickflipOption);
});

// Add some text after the mention
await userEvent.type(input, " and then ");

// Add another mention in the middle (after existing text and mention)
await userEvent.type(input, "@heelflip");
const heelflipOption = screen.getByRole("option", { name: "Heelflip" });
await waitFor(() => {
fireEvent.click(heelflipOption);
});

// Verify both mentions are present and text is preserved
// The second mention should be inserted correctly and existing text after should remain
expect(input.value).toBe("@kickflip and then @heelflip ");
expect(onValueChange).toHaveBeenLastCalledWith(["kickflip", "heelflip"]);
});
});
Loading