-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
80 lines (64 loc) · 2.23 KB
/
index.js
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
import { Inline } from "slate";
export const isPrintableChar = event => event.key.length === 1;
export const isCtrlOrCmd = event => event.ctrlKey || event.metaKey;
const isSpace = event => event.key === " ";
const getSelection = change => change.value.fragment.text;
const getLastWordRec = (change, maxIndex, counter = 0) => {
// If first char of the input is found just select everything (single word)
if (counter === maxIndex) {
const selectedWord = getSelection(change);
change.extend(counter);
return selectedWord;
}
// Move selection
const selectedWord = getSelection(change.extend(-1));
// Exit condition
if (selectedWord[0] === " ") {
change.extend(counter + 1); // one more needed because space
return selectedWord.substring(1);
}
return getLastWordRec(change, maxIndex, counter + 1);
};
export const getLastWord = change => {
const offsetCurrentWord = change.value.focusOffset;
return getLastWordRec(change, offsetCurrentWord);
};
const getPreviousNode = change => {
const block = change.value.focusBlock;
const activeKey = change.value.selection.focusKey;
return block.getPreviousSibling(activeKey);
};
export const focusPreviousNode = change => {
const offsetCurrentWord = change.value.focusOffset;
// check if we just started a the node
if (offsetCurrentWord === 0) {
const previousNode = getPreviousNode(change);
if (previousNode && Inline.isInline(previousNode)) {
change.moveToRangeOf(previousNode);
change.collapseToEnd();
}
}
};
const InstantReplace = transforms => ({
onKeyDown(event, change) {
if (!isPrintableChar(event)) return;
// needed to handle space & control + key actions by default
if (!isCtrlOrCmd(event)) {
if (!isSpace(event)) focusPreviousNode(change);
change.insertText(event.key);
// Apply transforms
if (Array.isArray(transforms)) {
transforms.forEach(transform => {
const lastWord = getLastWord(change);
transform(change, lastWord);
});
} else if (transforms) {
const lastWord = getLastWord(change);
transforms(change, lastWord);
}
// Prevent insertion of the char
event.preventDefault();
}
},
});
export default InstantReplace;