]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/framework/helpers/task-list-handler.ts
da8c0eae3dd0bc5dcd95e2a1757c1d8c03ad45e4
[bookstack] / resources / js / wysiwyg / ui / framework / helpers / task-list-handler.ts
1 import {$getNearestNodeFromDOMNode, LexicalEditor} from "lexical";
2 import {$isCustomListItemNode} from "../../../nodes/custom-list-item";
3
4 class TaskListHandler {
5     protected editorContainer: HTMLElement;
6     protected editor: LexicalEditor;
7
8     constructor(editor: LexicalEditor, editorContainer: HTMLElement) {
9         this.editor = editor;
10         this.editorContainer = editorContainer;
11         this.setupListeners();
12     }
13
14     protected setupListeners() {
15         this.handleClick = this.handleClick.bind(this);
16         this.editorContainer.addEventListener('click', this.handleClick);
17     }
18
19     handleClick(event: MouseEvent) {
20         const target = event.target;
21         if (target instanceof HTMLElement && target.nodeName === 'LI' && target.classList.contains('task-list-item')) {
22             this.handleTaskListItemClick(target, event);
23             event.preventDefault();
24         }
25     }
26
27     handleTaskListItemClick(listItem: HTMLElement, event: MouseEvent) {
28         const bounds = listItem.getBoundingClientRect();
29         const withinBounds = event.clientX <= bounds.right
30             && event.clientX >= bounds.left
31             && event.clientY >= bounds.top
32             && event.clientY <= bounds.bottom;
33
34         // Outside task list item bounds means we're probably clicking the pseudo-element
35         if (withinBounds) {
36             return;
37         }
38
39         this.editor.update(() => {
40             const node = $getNearestNodeFromDOMNode(listItem);
41             if ($isCustomListItemNode(node)) {
42                 node.setChecked(!node.getChecked());
43             }
44         });
45     }
46
47     teardown() {
48         this.editorContainer.removeEventListener('click', this.handleClick);
49     }
50 }
51
52
53 export function registerTaskListHandler(editor: LexicalEditor, editorContainer: HTMLElement): (() => void) {
54     const handler = new TaskListHandler(editor, editorContainer);
55
56     return () => {
57         handler.teardown();
58     };
59 }