Skip to content
File

Blob: src/client/components/editor/controllers/emoji/insert-popover.tsx

typescript50 lines
1import { FloatingPortal } from "@floating-ui/react";
2import type { Editor, Range } from "@tiptap/core";
3import { EmojiPicker } from "@/client/components/ui/emoji-picker";
4import { preserveEditorSelectionOnMouseDown, useEditorRectPopover } from "../menu/popover";
5import { insertEmoji } from "../../extensions/emoji";
6 
7export interface EmojiInsertPopoverProps {
8 editor: Editor;
9 range: Range;
10 pos: number;
11 onClose: () => void;
12}
13 
14function getAnchorRect(editor: Editor, pos: number): DOMRect | null {
15 try {
16 const coords = editor.view.coordsAtPos(pos);
17 return new DOMRect(coords.left, coords.top, 0, coords.bottom - coords.top);
18 } catch {
19 return null;
20 }
21}
22 
23export function EmojiInsertPopover({ editor, range, pos, onClose }: EmojiInsertPopoverProps) {
24 const { floatingStyles, setFloating } = useEditorRectPopover({
25 open: true,
26 onClose,
27 getAnchorRect: () => getAnchorRect(editor, pos),
28 contextElement: editor.view.dom,
29 deferOutsidePress: true,
30 });
31 
32 return (
33 <FloatingPortal>
34 <div
35 ref={setFloating}
36 style={{ ...floatingStyles, zIndex: 80 }}
37 aria-label="Insert emoji"
38 onMouseDownCapture={(event) => preserveEditorSelectionOnMouseDown(event)}
39 >
40 <EmojiPicker
41 onSelect={(emoji) => {
42 insertEmoji(editor, emoji, range);
43 onClose();
44 }}
45 />
46 </div>
47 </FloatingPortal>
48 );
49}