mirror of
https://github.com/documenso/documenso.git
synced 2026-07-05 18:44:54 +10:00
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
|
|
import { useCallback } from 'react';
|
|
|
|
export const useDocumentElement = () => {
|
|
/**
|
|
* Given a mouse event, find the nearest element found by the provided selector.
|
|
*/
|
|
const getPage = (event: MouseEvent, pageSelector: string) => {
|
|
if (!(event.target instanceof HTMLElement)) {
|
|
return null;
|
|
}
|
|
|
|
const target = event.target;
|
|
|
|
const $page =
|
|
target.closest<HTMLElement>(pageSelector) ??
|
|
document.elementsFromPoint(event.clientX, event.clientY).find((el) => el.matches(pageSelector));
|
|
|
|
if (!$page) {
|
|
return null;
|
|
}
|
|
|
|
return $page;
|
|
};
|
|
|
|
/**
|
|
* Provided a page and a field, calculate the position of the field
|
|
* as a percentage of the page width and height.
|
|
*/
|
|
const getFieldPosition = (page: HTMLElement, field: HTMLElement) => {
|
|
const { top: pageTop, left: pageLeft, height: pageHeight, width: pageWidth } = getBoundingClientRect(page);
|
|
|
|
const { top: fieldTop, left: fieldLeft, height: fieldHeight, width: fieldWidth } = getBoundingClientRect(field);
|
|
|
|
return {
|
|
x: ((fieldLeft - pageLeft) / pageWidth) * 100,
|
|
y: ((fieldTop - pageTop) / pageHeight) * 100,
|
|
width: (fieldWidth / pageWidth) * 100,
|
|
height: (fieldHeight / pageHeight) * 100,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Given a mouse event, determine if the mouse is within the bounds of the
|
|
* nearest element found by the provided selector.
|
|
*
|
|
* @param mouseWidth The artifical width of the mouse.
|
|
* @param mouseHeight The artifical height of the mouse.
|
|
*/
|
|
const isWithinPageBounds = useCallback((event: MouseEvent, pageSelector: string, mouseWidth = 0, mouseHeight = 0) => {
|
|
const $page = getPage(event, pageSelector);
|
|
|
|
if (!$page) {
|
|
return false;
|
|
}
|
|
|
|
const { top, left, height, width } = $page.getBoundingClientRect();
|
|
|
|
const halfMouseWidth = mouseWidth / 2;
|
|
const halfMouseHeight = mouseHeight / 2;
|
|
|
|
if (event.clientY > top + height - halfMouseHeight || event.clientY < top + halfMouseHeight) {
|
|
return false;
|
|
}
|
|
|
|
if (event.clientX > left + width - halfMouseWidth || event.clientX < left + halfMouseWidth) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}, []);
|
|
|
|
return {
|
|
getPage,
|
|
getFieldPosition,
|
|
isWithinPageBounds,
|
|
};
|
|
};
|