diff --git a/src/management-system-v2/components/ResizableElement.tsx b/src/management-system-v2/components/ResizableElement.tsx index 93f33d7ee..26d82caa1 100644 --- a/src/management-system-v2/components/ResizableElement.tsx +++ b/src/management-system-v2/components/ResizableElement.tsx @@ -1,3 +1,6 @@ +'use client'; + +import { CssSize, cssSizeToPixel } from '@/lib/css-units-helper'; import React, { useState, useEffect, @@ -5,19 +8,17 @@ import React, { CSSProperties, forwardRef, useImperativeHandle, - Dispatch, - SetStateAction, } from 'react'; type ResizableElementProps = PropsWithChildren<{ initialWidth: number; - minWidth: number; - maxWidth: number; + minWidth: CssSize; + maxWidth: CssSize; onWidthChange?: (width: number) => void; style?: CSSProperties; }>; -export type ResizableElementRefType = Dispatch>; +export type ResizableElementRefType = (size: CssSize) => void; let isResizing = false; const ResizableElement = forwardRef( @@ -27,23 +28,26 @@ const ResizableElement = forwardRef setWidth); + useImperativeHandle(ref, () => (size: CssSize) => setWidth(cssSizeToPixel(size))); - const onMouseDown = (e: React.MouseEvent) => { + const onMouseDown = (e: { stopPropagation: () => void; preventDefault: () => void }) => { e.stopPropagation(); e.preventDefault(); isResizing = true; }; - const onMouseUp = (e: MouseEvent) => { + const onMouseUp = () => { isResizing = false; }; - const onMouseMove = (e: MouseEvent) => { + const onUserMovement = (clientX: number) => { if (isResizing) { - let offsetRight = document.body.offsetWidth - (e.clientX - document.body.offsetLeft); + let offsetRight = document.body.offsetWidth - (clientX - document.body.offsetLeft); + + const minPixels = cssSizeToPixel(minWidth); + const maxPixels = cssSizeToPixel(maxWidth); - if (offsetRight > minWidth && offsetRight < maxWidth) { + if (offsetRight > minPixels && offsetRight < maxPixels) { setWidth(offsetRight); if (onWidthChange) onWidthChange(width); } @@ -51,11 +55,17 @@ const ResizableElement = forwardRef { + const onMouseMove = (e: MouseEvent) => onUserMovement(e.clientX); + const onTouchMove = (e: TouchEvent) => + onUserMovement(e.touches[e.touches.length - 1].clientX); + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('touchmove', onTouchMove); document.addEventListener('mouseup', onMouseUp); return () => { document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('touchmove', onTouchMove); document.removeEventListener('mouseup', onMouseUp); }; }); @@ -64,7 +74,9 @@ const ResizableElement = forwardRef
{children}
diff --git a/src/management-system-v2/lib/css-units-helper.ts b/src/management-system-v2/lib/css-units-helper.ts new file mode 100644 index 000000000..791d4fc29 --- /dev/null +++ b/src/management-system-v2/lib/css-units-helper.ts @@ -0,0 +1,35 @@ +'use client'; + +type Unit = 'px' | 'vw' | 'vh' | 'rem' | ''; + +export type CssSize = `${number}${Unit}` | number; + +function convertVwToPixel(valueInVw: number) { + return (valueInVw * window.innerWidth) / 100; +} + +function convertVhToPixel(valueInVh: number) { + return (valueInVh * window.innerHeight) / 100; +} + +function convertRemToPixel(valueInRem: number) { + return valueInRem; +} + +export function cssSizeToPixel(size: CssSize) { + if (typeof size === 'number') return size; + + const unit = size.slice(-2) as Unit; + const value = parseFloat(size); + + switch (unit) { + case 'rem': + return convertRemToPixel(value); + case 'vw': + return convertVwToPixel(value); + case 'vh': + return convertVhToPixel(value); + default: + return value; + } +}