FormattingMenu.res
1open Tiptap
2
3let submenu = Preact.Signal.make(false)
4
5@jsx.component
6let make = (~doc: string) => {
7 let btn = [
8 "p-1 bg-[var(--color-paper)]",
9 "hover:bg-[var(--color-bg-2)]",
10 "rounded-sm",
11 "cursor-pointer",
12 "text-sm box-border",
13 ]
14
15 let toggle = (mark: string) => {
16 switch State.Editor.get(doc) {
17 | Some(editor) => {
18 let editorState = editor->Tiptap.state
19 let selection = editorState.selection
20 if !selection.empty {
21 editor->Tiptap.Commands.toggleMark(mark)
22 editor->Tiptap.Commands.setTextSelectionToPosition(selection.to)
23 }
24 }
25 | None => ()
26 }
27 }
28
29 let remove = () => {
30 switch State.Editor.get(doc) {
31 | Some(editor) => {
32 let editorState = editor->Tiptap.state
33 let selection = editorState.selection
34 if !selection.empty {
35 editor->Tiptap.Commands.unsetAllMarks
36 editor->Tiptap.Commands.setTextSelectionToPosition(selection.to)
37 }
38 }
39 | None => ()
40 }
41 }
42
43 let heading = (level: int) => {
44 switch State.Editor.get(doc) {
45 | Some(editor) => {
46 let editorState = editor->Tiptap.state
47 let selection = editorState.selection
48 if !selection.empty {
49 editor->Tiptap.Commands.toggleHeading({"level": level})
50 editor->Tiptap.Commands.setTextSelectionToPosition(selection.to)
51 }
52 }
53 | None => ()
54 }
55 }
56
57 <Editor.BubbleMenu
58 className="p-[2px] ring-2 ring-[var(--color-blue)] rounded-sm cursor-pointer box-border"
59 >
60 <button
61 className={btn->Array.join(" ")}
62 onClick={_evt => submenu->Preact.Signal.set(!(submenu->Preact.Signal.get))}
63 >
64 <div className="flex flex-row">
65 <Icons.Heading className="p-[2px]" />
66 <Icons.Triangle className="w-2 rotate-90" />
67 </div>
68 </button>
69 {submenu->Preact.Signal.get
70 ? <>
71 <button className={btn->Array.join(" ")} onClick={_evt => heading(1)}>
72 <Icons.Heading1 className="p-[3px]" />
73 </button>
74 <button className={btn->Array.join(" ")} onClick={_evt => heading(2)}>
75 <Icons.Heading2 className="p-[3px]" />
76 </button>
77 <button className={btn->Array.join(" ")} onClick={_evt => heading(3)}>
78 <Icons.Heading3 className="p-[3px]" />
79 </button>
80 <button className={btn->Array.join(" ")} onClick={_evt => heading(4)}>
81 <Icons.Heading4 className="p-[3px]" />
82 </button>
83 </>
84 : <>
85 <button className={btn->Array.join(" ")} onClick={_evt => toggle("bold")}>
86 <Icons.Bold className="p-[2px]" />
87 </button>
88 <button className={btn->Array.join(" ")} onClick={_evt => toggle("italic")}>
89 <Icons.Italic className="p-[2px]" />
90 </button>
91 <button className={btn->Array.join(" ")} onClick={_evt => toggle("underline")}>
92 <Icons.Underline className="p-[2px]" />
93 </button>
94 <button className={btn->Array.join(" ")} onClick={_evt => remove()}>
95 <Icons.RemoveFormatting className="p-[2px]" />
96 </button>
97 </>}
98 </Editor.BubbleMenu>
99}