I’m trying to select entire words when a user taps on one but my changes end up getting overriden by the native selection logic. Here’s the code I’m using to set it up:
const tapThreshold = 200; // milliseconds
const moveThreshold = 25; // pixels
export const onTap = (callback: OnTapCallback): Extension => {
let touchStartX = 0;
let touchStartY = 0;
let startTime = 0;
return EditorView.domEventHandlers({
touchstart: (event) => {
touchStartX = event.touches[0].clientX;
touchStartY = event.touches[0].clientY;
startTime = Date.now();
},
touchend: (event, view) => {
const touchEndX = event.changedTouches[0].clientX;
const touchEndY = event.changedTouches[0].clientY;
const endTime = Date.now();
const duration = endTime - startTime;
if (duration > tapThreshold) { return; }
const deltaX = touchEndX - touchStartX;
const deltaY = touchEndY - touchStartY;
const moveDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (moveDistance > moveThreshold) { return; }
callback(view.posAtCoords({ x: touchEndX, y: touchEndY }));
},
});
};
// extension on editor state
onTap((position) => {
if (!position) { return; }
const word = editor.state.wordAt(position);
if (!word) { return; }
editor.dispatch({
selection: { anchor: word.from, head: word.to },
});
}),
Is there another way I should be doing this or a way I can prevent the two selection methods from fighting? I tried using a transactionFilter
but I only want this behavior on tap so it turned out being pretty complex to try and do it that way.