diff --git a/packages/react-resizable-panels-website/src/components/ResizeHandle.module.css b/packages/react-resizable-panels-website/src/components/ResizeHandle.module.css index b8ff4bd75..b6cacc266 100644 --- a/packages/react-resizable-panels-website/src/components/ResizeHandle.module.css +++ b/packages/react-resizable-panels-website/src/components/ResizeHandle.module.css @@ -11,7 +11,7 @@ background-color: var(--color-resize-bar-drag); } -@media (max-width: 500px) { +@media (pointer: coarse) { .ResizeHandle { flex: 0 0 1rem; } diff --git a/packages/react-resizable-panels-website/src/components/VisibleCursor.tsx b/packages/react-resizable-panels-website/src/components/VisibleCursor.tsx index 2ac951498..5a729be81 100644 --- a/packages/react-resizable-panels-website/src/components/VisibleCursor.tsx +++ b/packages/react-resizable-panels-website/src/components/VisibleCursor.tsx @@ -1,5 +1,6 @@ import { useLayoutEffect } from "react"; import styles from "./VisibleCursor.module.css"; +import { getResizeEventCoordinates } from "../../../react-resizable-panels/src/utils/events/getResizeEventCoordinates"; export function VisibleCursor() { useLayoutEffect(() => { @@ -13,9 +14,10 @@ export function VisibleCursor() { element.setAttribute("data-state", "down"); }; - const onMouseMove = (event: MouseEvent) => { - element.style.left = event.pageX + "px"; - element.style.top = event.pageY + "px"; + const onMouseMove = (event: MouseEvent | TouchEvent) => { + const { x, y } = getResizeEventCoordinates(event); + element.style.left = x + "px"; + element.style.top = y + "px"; }; const onMouseUp = () => { @@ -25,6 +27,10 @@ export function VisibleCursor() { document.addEventListener("mousedown", onMouseDown, true); document.addEventListener("mousemove", onMouseMove, true); document.addEventListener("mouseup", onMouseUp, true); + document.addEventListener("touchcancel", onMouseUp, true); + document.addEventListener("touchend", onMouseUp, true); + document.addEventListener("touchmove", onMouseMove, true); + document.addEventListener("touchstart", onMouseDown, true); return () => { document.body.removeChild(element); @@ -32,6 +38,10 @@ export function VisibleCursor() { document.removeEventListener("mousedown", onMouseDown, true); document.removeEventListener("mousemove", onMouseMove, true); document.removeEventListener("mouseup", onMouseUp, true); + document.removeEventListener("touchcancel", onMouseUp, true); + document.removeEventListener("touchend", onMouseUp, true); + document.removeEventListener("touchmove", onMouseMove, true); + document.removeEventListener("touchstart", onMouseDown, true); }; }); diff --git a/packages/react-resizable-panels-website/src/routes/examples/Collapsible.module.css b/packages/react-resizable-panels-website/src/routes/examples/Collapsible.module.css index 4c20945fe..f5306ad22 100644 --- a/packages/react-resizable-panels-website/src/routes/examples/Collapsible.module.css +++ b/packages/react-resizable-panels-website/src/routes/examples/Collapsible.module.css @@ -15,7 +15,7 @@ background-color: var(--color-button-background-hover); } -@media (max-width: 500px) { +@media (pointer: coarse) { .ResizeHandle, .ResizeHandleCollapsed { width: 1rem; diff --git a/packages/react-resizable-panels/src/PanelGroup.ts b/packages/react-resizable-panels/src/PanelGroup.ts index 3fa7b7eb8..ac402f462 100644 --- a/packages/react-resizable-panels/src/PanelGroup.ts +++ b/packages/react-resizable-panels/src/PanelGroup.ts @@ -30,7 +30,7 @@ import debounce from "./utils/debounce"; import { determinePivotIndices } from "./utils/determinePivotIndices"; import { getResizeHandleElement } from "./utils/dom/getResizeHandleElement"; import { isKeyDown, isMouseEvent, isTouchEvent } from "./utils/events"; -import { getResizeEventCursorPosition } from "./utils/getResizeEventCursorPosition"; +import { getResizeEventCursorPosition } from "./utils/events/getResizeEventCursorPosition"; import { initializeDefaultStorage } from "./utils/initializeDefaultStorage"; import { loadPanelGroupState, diff --git a/packages/react-resizable-panels/src/PanelResizeHandleRegistry.ts b/packages/react-resizable-panels/src/PanelResizeHandleRegistry.ts index ab42de653..3be54951b 100644 --- a/packages/react-resizable-panels/src/PanelResizeHandleRegistry.ts +++ b/packages/react-resizable-panels/src/PanelResizeHandleRegistry.ts @@ -1,6 +1,6 @@ import { Direction, ResizeEvent } from "./types"; import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor"; -import { isMouseEvent, isTouchEvent } from "./utils/events"; +import { getResizeEventCoordinates } from "./utils/events/getResizeEventCoordinates"; export type ResizeHandlerAction = "down" | "move" | "up"; export type ResizeHandlerState = "drag" | "hover" | "inactive"; @@ -67,33 +67,14 @@ export function registerResizeHandle( }; } -function getEventCoordinates(event: ResizeEvent) { - if (isMouseEvent(event)) { - return { - x: event.pageX, - y: event.pageY, - }; - } else if (isTouchEvent(event)) { - const touch = event.touches[0]; - if (touch && touch.pageX && touch.pageY) { - return { - x: touch.pageX, - y: touch.pageY, - }; - } - } - - return { - x: Infinity, - y: Infinity, - }; -} - function handlePointerDown(event: ResizeEvent) { + const { x, y } = getResizeEventCoordinates(event); + isPointerDown = true; updateResizeHandlerStates("down", event); + recalculateIntersectingHandles({ x, y }); updateListeners(); if (intersectingHandles.length > 0) { @@ -102,7 +83,7 @@ function handlePointerDown(event: ResizeEvent) { } function handlePointerMove(event: ResizeEvent) { - const { x, y } = getEventCoordinates(event); + const { x, y } = getResizeEventCoordinates(event); if (isPointerDown) { intersectingHandles.forEach((data) => { @@ -125,7 +106,7 @@ function handlePointerMove(event: ResizeEvent) { } function handlePointerUp(event: ResizeEvent) { - const { x, y } = getEventCoordinates(event); + const { x, y } = getResizeEventCoordinates(event); panelConstraintFlags.clear(); isPointerDown = false; @@ -232,11 +213,11 @@ function updateListeners() { if (count > 0) { body.addEventListener("contextmenu", handlePointerUp); + body.addEventListener("mouseleave", handlePointerMove); body.addEventListener("mousemove", handlePointerMove); body.addEventListener("touchmove", handlePointerMove, { passive: false, }); - body.addEventListener("mouseleave", handlePointerMove); } }); } diff --git a/packages/react-resizable-panels/src/utils/calculateDragOffsetPercentage.ts b/packages/react-resizable-panels/src/utils/calculateDragOffsetPercentage.ts index 84a5bf75d..f3973dcef 100644 --- a/packages/react-resizable-panels/src/utils/calculateDragOffsetPercentage.ts +++ b/packages/react-resizable-panels/src/utils/calculateDragOffsetPercentage.ts @@ -3,7 +3,7 @@ import { Direction } from "../types"; import { assert } from "./assert"; import { getPanelGroupElement } from "./dom/getPanelGroupElement"; import { getResizeHandleElement } from "./dom/getResizeHandleElement"; -import { getResizeEventCursorPosition } from "./getResizeEventCursorPosition"; +import { getResizeEventCursorPosition } from "./events/getResizeEventCursorPosition"; export function calculateDragOffsetPercentage( event: ResizeEvent, diff --git a/packages/react-resizable-panels/src/utils/events/getResizeEventCoordinates.ts b/packages/react-resizable-panels/src/utils/events/getResizeEventCoordinates.ts new file mode 100644 index 000000000..101cbf6b4 --- /dev/null +++ b/packages/react-resizable-panels/src/utils/events/getResizeEventCoordinates.ts @@ -0,0 +1,24 @@ +import { ResizeEvent } from "../../types"; +import { isMouseEvent, isTouchEvent } from "."; + +export function getResizeEventCoordinates(event: ResizeEvent) { + if (isMouseEvent(event)) { + return { + x: event.pageX, + y: event.pageY, + }; + } else if (isTouchEvent(event)) { + const touch = event.touches[0]; + if (touch && touch.pageX && touch.pageY) { + return { + x: touch.pageX, + y: touch.pageY, + }; + } + } + + return { + x: Infinity, + y: Infinity, + }; +} diff --git a/packages/react-resizable-panels/src/utils/events/getResizeEventCursorPosition.ts b/packages/react-resizable-panels/src/utils/events/getResizeEventCursorPosition.ts new file mode 100644 index 000000000..fae4e3b72 --- /dev/null +++ b/packages/react-resizable-panels/src/utils/events/getResizeEventCursorPosition.ts @@ -0,0 +1,14 @@ +import { ResizeEvent } from "../../PanelGroupContext"; +import { Direction } from "../../types"; +import { getResizeEventCoordinates } from "./getResizeEventCoordinates"; + +export function getResizeEventCursorPosition( + direction: Direction, + event: ResizeEvent +): number { + const isHorizontal = direction === "horizontal"; + + const { x, y } = getResizeEventCoordinates(event); + + return isHorizontal ? x : y; +} diff --git a/packages/react-resizable-panels/src/utils/events.ts b/packages/react-resizable-panels/src/utils/events/index.ts similarity index 86% rename from packages/react-resizable-panels/src/utils/events.ts rename to packages/react-resizable-panels/src/utils/events/index.ts index 7e87d2d58..5425887db 100644 --- a/packages/react-resizable-panels/src/utils/events.ts +++ b/packages/react-resizable-panels/src/utils/events/index.ts @@ -1,4 +1,4 @@ -import { ResizeEvent } from "../PanelGroupContext"; +import { ResizeEvent } from "../../PanelGroupContext"; export function isKeyDown(event: ResizeEvent): event is KeyboardEvent { return event.type === "keydown"; diff --git a/packages/react-resizable-panels/src/utils/getResizeEventCursorPosition.ts b/packages/react-resizable-panels/src/utils/getResizeEventCursorPosition.ts deleted file mode 100644 index 5dbc0f0d3..000000000 --- a/packages/react-resizable-panels/src/utils/getResizeEventCursorPosition.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ResizeEvent } from "../PanelGroupContext"; -import { Direction } from "../types"; -import { assert } from "./assert"; -import { isMouseEvent, isTouchEvent } from "./events"; - -export function getResizeEventCursorPosition( - direction: Direction, - event: ResizeEvent -): number { - const isHorizontal = direction === "horizontal"; - - if (isMouseEvent(event)) { - return isHorizontal ? event.clientX : event.clientY; - } else if (isTouchEvent(event)) { - const firstTouch = event.touches[0]; - assert(firstTouch); - return isHorizontal ? firstTouch.screenX : firstTouch.screenY; - } else { - throw Error(`Unsupported event type "${event.type}"`); - } -}