| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- import { type JSX, memo, useCallback, useRef } from 'react';
- import type { ResizableAreaProps } from './props';
- import styles from './ResizableArea.module.scss';
- export const ResizableArea = memo((props: ResizableAreaProps): JSX.Element => {
- const {
- className,
- width,
- minWidth = 0,
- disabled,
- children,
- onResize,
- onResizeDone,
- onCollapsed,
- } = props;
- const resizableContainer = useRef<HTMLDivElement>(null);
- const draggableAreaMoveHandler = useCallback(
- (event: MouseEvent) => {
- event.preventDefault();
- const widthByMousePos = event.pageX;
- const newWidth = Math.max(widthByMousePos, minWidth);
- onResize?.(newWidth);
- resizableContainer.current?.classList.add('dragging');
- },
- [minWidth, onResize],
- );
- const dragableAreaMouseUpHandler = useCallback(
- (event: MouseEvent) => {
- if (resizableContainer.current == null) {
- return;
- }
- const widthByMousePos = event.pageX;
- if (widthByMousePos < minWidth / 2) {
- // force collapsed
- onCollapsed?.();
- } else {
- const newWidth = resizableContainer.current.clientWidth;
- onResizeDone?.(newWidth);
- }
- resizableContainer.current.classList.remove('dragging');
- },
- [minWidth, onCollapsed, onResizeDone],
- );
- const dragableAreaMouseDownHandler = useCallback(
- (event: React.MouseEvent) => {
- if (disabled) {
- return;
- }
- event.preventDefault();
- const removeEventListeners = () => {
- document.removeEventListener('mousemove', draggableAreaMoveHandler);
- document.removeEventListener('mouseup', dragableAreaMouseUpHandler);
- document.removeEventListener('mouseup', removeEventListeners);
- };
- document.addEventListener('mousemove', draggableAreaMoveHandler);
- document.addEventListener('mouseup', dragableAreaMouseUpHandler);
- document.addEventListener('mouseup', removeEventListeners);
- },
- [dragableAreaMouseUpHandler, draggableAreaMoveHandler, disabled],
- );
- return (
- <>
- <div
- ref={resizableContainer}
- className={`${styles['grw-resizable-area']} ${className}`}
- style={{ width }}
- >
- {children}
- </div>
- <div className={styles['grw-navigation-draggable']}>
- {!disabled && (
- <>
- <button
- type="button"
- className="grw-navigation-draggable-hitarea"
- aria-label="Resize sidebar"
- onMouseDown={dragableAreaMouseDownHandler}
- />
- <div className="grw-navigation-draggable-line"></div>
- </>
- )}
- </div>
- </>
- );
- });
|