Skip to content

Commit

Permalink
Add touch support for TableCellResizer
Browse files Browse the repository at this point in the history
  • Loading branch information
ibastawisi committed Mar 5, 2025
1 parent 6416a25 commit 6d62b27
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@
.TableCellResizer__resizer {
position: absolute;
}

@media (pointer: coarse) {
.TableCellResizer__resizer {
background-color: #adf;
mix-blend-mode: color;
}
}
94 changes: 60 additions & 34 deletions packages/lexical-playground/src/plugins/TableCellResizer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import {calculateZoomLevel, mergeRegister} from '@lexical/utils';
import {$getNearestNodeFromDOMNode, isHTMLElement} from 'lexical';
import * as React from 'react';
import {
MouseEventHandler,
CSSProperties,
PointerEventHandler,
ReactPortal,
useCallback,
useEffect,
Expand Down Expand Up @@ -106,7 +107,10 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
return;
}

const onMouseMove = (event: MouseEvent) => {
const onPointerMove = (event: PointerEvent) => {
if (event.pointerType === 'touch' && event.type !== 'click') {
return;
}
const target = event.target;
if (!isHTMLElement(target)) {
return;
Expand Down Expand Up @@ -167,19 +171,49 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
updateIsMouseDown(false);
};

const onClick = (event: MouseEvent) => {
const pointerEvent = event as PointerEvent;
if (pointerEvent.pointerType !== 'touch') {
return;
}
updateIsMouseDown(false);
onPointerMove(pointerEvent);
};

const onTouchMove = (event: TouchEvent) => {
event.preventDefault();
event.stopPropagation();
if (!event.touches || event.touches.length === 0) {
return;
}
const touch = event.touches[0];
updateMouseCurrentPos({
x: touch.clientX,
y: touch.clientY,
});
};

const resizerContainer = resizerRef.current;
resizerContainer?.addEventListener('touchmove', onTouchMove, {
capture: true,
});

const removeRootListener = editor.registerRootListener(
(rootElement, prevRootElement) => {
prevRootElement?.removeEventListener('mousemove', onMouseMove);
prevRootElement?.removeEventListener('pointermove', onPointerMove);
prevRootElement?.removeEventListener('click', onClick);
prevRootElement?.removeEventListener('mousedown', onMouseDown);
prevRootElement?.removeEventListener('mouseup', onMouseUp);
rootElement?.addEventListener('mousemove', onMouseMove);
rootElement?.addEventListener('pointermove', onPointerMove);
rootElement?.addEventListener('click', onClick);
rootElement?.addEventListener('mousedown', onMouseDown);
rootElement?.addEventListener('mouseup', onMouseUp);
},
);

return () => {
removeRootListener();
resizerContainer?.removeEventListener('touchmove', onTouchMove);
};
}, [activeCell, draggingDirection, editor, resetState, hasTable]);

Expand Down Expand Up @@ -304,9 +338,9 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
[activeCell, editor],
);

const mouseUpHandler = useCallback(
const pointerUpHandler = useCallback(
(direction: MouseDraggingDirection) => {
const handler = (event: MouseEvent) => {
const handler = (event: PointerEvent) => {
event.preventDefault();
event.stopPropagation();

Expand All @@ -331,7 +365,7 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
}

resetState();
document.removeEventListener('mouseup', handler);
document.removeEventListener('pointerup', handler);
}
};
return handler;
Expand All @@ -340,7 +374,7 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
);

const toggleResize = useCallback(
(direction: MouseDraggingDirection): MouseEventHandler<HTMLDivElement> =>
(direction: MouseDraggingDirection): PointerEventHandler<HTMLDivElement> =>
(event) => {
event.preventDefault();
event.stopPropagation();
Expand All @@ -356,60 +390,52 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
updateMouseCurrentPos(mouseStartPosRef.current);
updateDraggingDirection(direction);

document.addEventListener('mouseup', mouseUpHandler(direction));
document.addEventListener('pointerup', pointerUpHandler(direction));
},
[activeCell, mouseUpHandler],
[activeCell, pointerUpHandler],
);

const getResizers = useCallback(() => {
if (activeCell) {
const tableRect = tableRectRef.current;
if (activeCell && tableRect) {
const {height, width, top, left} =
activeCell.elem.getBoundingClientRect();
const zoom = calculateZoomLevel(activeCell.elem);
const zoneWidth = 10; // Pixel width of the zone where you can drag the edge
const styles = {
const zoneWidth = 16; // Pixel width of the zone where you can drag the edge
const styles: Record<string, CSSProperties> = {
bottom: {
backgroundColor: 'none',
cursor: 'row-resize',
height: `${zoneWidth}px`,
left: `${window.pageXOffset + left}px`,
top: `${window.pageYOffset + top + height - zoneWidth / 2}px`,
width: `${width}px`,
left: `${window.scrollX + tableRect.left}px`,
top: `${window.scrollY + top + height - zoneWidth / 2}px`,
width: `${tableRect.width}px`,
},
right: {
backgroundColor: 'none',
cursor: 'col-resize',
height: `${height}px`,
left: `${window.pageXOffset + left + width - zoneWidth / 2}px`,
top: `${window.pageYOffset + top}px`,
height: `${tableRect.height}px`,
left: `${window.scrollX + left + width - zoneWidth / 2}px`,
top: `${window.scrollY + tableRect.top}px`,
width: `${zoneWidth}px`,
},
};

const tableRect = tableRectRef.current;

if (draggingDirection && mouseCurrentPos && tableRect) {
if (draggingDirection && mouseCurrentPos) {
if (isHeightChanging(draggingDirection)) {
styles[draggingDirection].left = `${
window.pageXOffset + tableRect.left
}px`;
styles[draggingDirection].top = `${
window.pageYOffset + mouseCurrentPos.y / zoom
window.scrollY + mouseCurrentPos.y / zoom
}px`;
styles[draggingDirection].height = '3px';
styles[draggingDirection].width = `${tableRect.width}px`;
} else {
styles[draggingDirection].top = `${
window.pageYOffset + tableRect.top
}px`;
styles[draggingDirection].left = `${
window.pageXOffset + mouseCurrentPos.x / zoom
window.scrollX + mouseCurrentPos.x / zoom
}px`;
styles[draggingDirection].width = '3px';
styles[draggingDirection].height = `${tableRect.height}px`;
}

styles[draggingDirection].backgroundColor = '#adf';
styles[draggingDirection].mixBlendMode = 'unset';
}

return styles;
Expand All @@ -432,12 +458,12 @@ function TableCellResizer({editor}: {editor: LexicalEditor}): JSX.Element {
<div
className="TableCellResizer__resizer TableCellResizer__ui"
style={resizerStyles.right || undefined}
onMouseDown={toggleResize('right')}
onPointerDown={toggleResize('right')}
/>
<div
className="TableCellResizer__resizer TableCellResizer__ui"
style={resizerStyles.bottom || undefined}
onMouseDown={toggleResize('bottom')}
onPointerDown={toggleResize('bottom')}
/>
</>
)}
Expand Down

0 comments on commit 6d62b27

Please sign in to comment.