-
Notifications
You must be signed in to change notification settings - Fork 995
Expand file tree
/
Copy pathonMouseDownTable.ts
More file actions
93 lines (68 loc) · 2.33 KB
/
Copy pathonMouseDownTable.ts
File metadata and controls
93 lines (68 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import type React from 'react';
import type { DOMHandler } from 'platejs/react';
import { KEYS } from 'platejs';
import type { TableConfig } from '../lib';
const DATA_SLATE_NODE_SELECTOR = '[data-slate-node]';
const getTargetElement = (target: EventTarget | null) => {
if (target instanceof Element) return target;
if (target instanceof Node) return target.parentElement;
};
const hasMappedSlateTarget = (target: EventTarget | null) => {
const slateNode = getTargetElement(target)?.closest(DATA_SLATE_NODE_SELECTOR);
return !!slateNode && slateNode.getAttribute('data-slate-node') !== 'value';
};
const getClosestEditableChildPath = (
editor: Parameters<DOMHandler<TableConfig>>[0]['editor'],
clientY: number
) => {
let previousPath: number[] | undefined;
for (const [index, node] of editor.children.entries()) {
const path = [index];
const domNode = editor.api.toDOMNode(node);
if (!(domNode instanceof Element)) continue;
const rect = domNode.getBoundingClientRect();
if (clientY < rect.top) {
return previousPath
? { edge: 'end' as const, path: previousPath }
: { edge: 'start' as const, path };
}
if (clientY <= rect.bottom) {
const height = rect.height || rect.bottom - rect.top;
return {
edge: clientY <= rect.top + height / 2 ? 'start' : 'end',
path,
} as const;
}
previousPath = path;
}
if (previousPath) {
return { edge: 'end' as const, path: previousPath };
}
};
export const onMouseDownTable: DOMHandler<TableConfig, React.MouseEvent> = ({
editor,
event,
}) => {
if (event.defaultPrevented || event.button !== 0) return;
if (hasMappedSlateTarget(event.target)) return;
const editable = event.currentTarget;
const target = event.target;
if (!(editable instanceof HTMLElement)) return;
if (!(target instanceof Node) || !editable.contains(target)) return;
if (
!editor.api.some({ at: [], match: { type: editor.getType(KEYS.table) } })
) {
return;
}
const closestPath = getClosestEditableChildPath(editor, event.clientY);
if (!closestPath) return;
const point =
closestPath.edge === 'start'
? editor.api.start(closestPath.path)
: editor.api.end(closestPath.path);
if (!point) return;
event.preventDefault();
event.stopPropagation();
editor.tf.select(point);
return true;
};