UNPKG

@craftercms/studio-ui

Version:

Services, components, models & utils to build CrafterCMS authoring extensions.

222 lines (220 loc) 6.27 kB
/* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import Drawer from '@mui/material/Drawer'; import React, { useCallback, useRef, useState } from 'react'; import { makeStyles } from 'tss-react/mui'; import palette from '../../styles/palette'; const useStyles = makeStyles()( ( theme, { root, drawerBody, drawerPaper, drawerPaperBelowToolbar, drawerPaperLeft, drawerPaperRight, resizeHandle, resizeHandleLeft, resizeHandleRight, resizeHandleActive, resizingOverlay } = {} ) => ({ root: { flexShrink: 0, ...root }, drawerBody: { width: '100%', height: '100%', overflowY: 'auto', ...drawerBody }, drawerPaper: { bottom: 0, overflow: 'hidden', maxWidth: '95% !important', backgroundColor: theme.palette.background.default, ...drawerPaper }, drawerPaperBelowToolbar: { top: 65, height: 'auto', zIndex: theme.zIndex.appBar - 1, ...drawerPaperBelowToolbar }, drawerPaperLeft: { borderRight: 'none', ...drawerPaperLeft }, drawerPaperRight: { borderLeft: 'none', ...drawerPaperRight }, resizeHandle: { width: '2px', cursor: 'ew-resize', padding: '4px 0 0', position: 'absolute', top: 0, bottom: 0, zIndex: 100, backgroundColor: theme.palette.divider, transition: 'width 200ms', '&:hover': { width: '4px', visibility: 'visible', backgroundColor: palette.blue.tint }, ...resizeHandle }, resizeHandleLeft: { left: 0, ...resizeHandleLeft }, resizeHandleRight: { right: 0, ...resizeHandleRight }, resizeHandleActive: { width: '4px', visibility: 'visible', backgroundColor: palette.blue.tint, ...resizeHandleActive }, resizingOverlay: { '&::before': { content: '""', position: 'fixed', top: 0, bottom: 0, left: 0, right: 0, ...resizingOverlay } } }) ); export function ResizeableDrawer(props) { const { classes, cx } = useStyles(props.styles); const [resizeActive, setResizeActive] = useState(false); const drawerRef = useRef(); const { open, children, width, maxWidth = 500, minWidth = 240, onWidthChange, onResizeStart, onResizeStop, className, classes: propsClasses = {}, PaperProps, anchor = 'left', belowToolbar = false, ...rest } = props; const { root, drawerBody, drawerPaper, drawerPaperBelowToolbar, resizeHandle, resizeHandleActive, resizeHandleLeft, resizeHandleRight, ...drawerClasses } = propsClasses; const handleMouseMove = useCallback( (e) => { if (onWidthChange) { e.preventDefault(); let newWidth = (anchor === 'left' ? e.clientX - drawerRef.current.getBoundingClientRect().left : window.innerWidth - (e.clientX - drawerRef.current.getBoundingClientRect().left)) + 5; newWidth = newWidth < minWidth ? minWidth : newWidth > maxWidth ? maxWidth : newWidth; onWidthChange(newWidth); } }, [anchor, onWidthChange, maxWidth, minWidth] ); const handleMouseDown = onWidthChange ? () => { setResizeActive(true); onResizeStart?.(); const handleMouseUp = () => { setResizeActive(false); onResizeStop?.(); document.removeEventListener('mouseup', handleMouseUp, true); document.removeEventListener('mousemove', handleMouseMove, true); }; document.addEventListener('mouseup', handleMouseUp, true); document.addEventListener('mousemove', handleMouseMove, true); } : null; return React.createElement( Drawer, { open: open, ref: drawerRef, anchor: anchor, variant: 'persistent', className: cx(classes.root, className), classes: { ...drawerClasses, paper: cx( classes.drawerPaper, belowToolbar && classes.drawerPaperBelowToolbar, drawerPaper, belowToolbar && drawerPaperBelowToolbar, onWidthChange && (anchor === 'left' ? classes.drawerPaperLeft : classes.drawerPaperRight), resizeActive && classes.resizingOverlay ) }, PaperProps: { ...PaperProps, style: { width } }, ...rest }, onWidthChange && React.createElement('div', { onMouseDown: handleMouseDown, className: cx( classes.resizeHandle, resizeActive && classes.resizeHandleActive, anchor === 'left' ? classes.resizeHandleRight : classes.resizeHandleLeft ) }), React.createElement('section', { className: cx(classes.drawerBody, drawerBody) }, children) ); } export default ResizeableDrawer;