Fix inserting accents into the text editor via long-press on MacOS

Related: https://github.com/ianstormtaylor/slate/pull/3041, https://github.com/ianstormtaylor/slate/issues/982
This commit is contained in:
Ben Gotow 2024-01-06 23:32:35 -06:00
parent 1ebaa3d46c
commit 6ab1b642b7

View file

@ -44,3 +44,72 @@ document.addEventListener(
},
true
);
/*
On MacOS, you can press and hold some keys to see available accent characters, and then
press a number or click the option to add the accent. The sequence of events is:
keydown (key=e)
keypress (key=e)
keydown (key=e, repeat=true)
keydown (key=e, repeat=true)
keyup (key=e)
... panel is now open ...
keydown (key=2) // optional
beforeinput (data=é)
input (data=é)
keyup (key=2)
In Slate, the result is "eé" instead of the accented mark replacing the initial e.
This is a patch similar to https://github.com/ianstormtaylor/slate/pull/3041 and is
unfortunately a bit of a state machine. If we see the exact series of steps below,
we delete the preceding character before inserting the new character:
1) a keydown with repeat=true
2) a keyup for the same key
-- no keypress events or non-numeric keydown events --
3) a beforeinput event
Testing notes:
- Verify it works when you click an accent option vs choose it with 1,2,3..
- Verify that it works when your insertion point is at the beginning, middle and end of string
- Verify that it works if the text contains underlined misspellings (fragments)
*/
let repeatingKeyDown = null;
let substitutionsPanelMayBeOpen = false;
document.addEventListener('keydown', e => {
repeatingKeyDown = e.repeat ? e.key : null;
if (!['1', '2', '3', '4', '5', '6', '7', '8', '9'].includes(e.key)) {
substitutionsPanelMayBeOpen = false;
}
});
document.addEventListener('keypress', e => {
substitutionsPanelMayBeOpen = false;
});
document.addEventListener('keyup', e => {
substitutionsPanelMayBeOpen = repeatingKeyDown && repeatingKeyDown === e.key;
repeatingKeyDown = false;
});
document.addEventListener('beforeinput', e => {
if (substitutionsPanelMayBeOpen) {
substitutionsPanelMayBeOpen = false;
if (e.target instanceof HTMLElement && e.target.closest('[data-slate-editor]')) {
console.warn('Manually emitting backspace event for Chrome');
// You would think that firing keydown AND keyup would be best, but doing that
// causes the editor to delete forward if your cursor is not at the end of the text
const t = document.createEvent('TextEvent');
t.initEvent('keyup', true, true);
Object.defineProperty(t, 'keyCode', { value: 8 });
Object.defineProperty(t, 'key', { value: 'Backspace' });
Object.defineProperty(t, 'code', { value: 'Backspace' });
e.target.dispatchEvent(t);
}
}
});