diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss index e1b04be8095bb9cf5cee747ab9892fb9071eb247..81ed130dd50c04a31a13391837bc6f1d4b2dd2e6 100644 --- a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss +++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss @@ -1,5 +1,47 @@ @import "/src/shared/style/colors.scss"; +.custom-resize-handle { + position: absolute; + right: 0; + bottom: 0; + width: 20px; + height: 20px; + cursor: se-resize; + + .resize-handle-inner { + position: absolute; + right: 4px; + bottom: 4px; + width: 12px; + height: 12px; + border-right: 2px solid rgba(0, 0, 0, 0.2); + border-bottom: 2px solid rgba(0, 0, 0, 0.2); + } +} + +.react-grid-item { + transition: none !important; + + &.resizing { + z-index: 1; + will-change: transform; + } +} + +.react-grid-item { + height: 100px; + /* Hide resize handle by default */ + .custom-resize-handle { + opacity: 0; + transition: opacity 0.2s ease-in-out; + } + + /* Show resize handle on container hover */ + &:hover .custom-resize-handle { + opacity: 1; + } +} + .drag-handle { position: absolute; top: 0; @@ -25,8 +67,6 @@ .react-grid-item { &.react-draggable-dragging { - z-index: 100; - .drag-handle { cursor: grabbing; } diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx index 694c74478f45fb7bc977a7b31e3ad81f1f3f859e..7ec2c4a513dbe1ccad8344c04417a2ec1da8b263 100644 --- a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx +++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx @@ -1,19 +1,18 @@ import React, { ReactElement, useEffect, useRef, useState } from 'react'; -import { Responsive, WidthProvider } from 'react-grid-layout'; +import RGL, { WidthProvider } from "react-grid-layout"; + import 'react-grid-layout/css/styles.css'; import 'react-resizable/css/styles.css'; import './grid.layout.scss'; -const ResponsiveGridLayout = WidthProvider(Responsive); +const ResponsiveGridLayout = WidthProvider(RGL); interface GridLayoutProps { children: ReactElement; } -getComputedStyle const RowCount = 2; -const padding = 80; // in px - +const padding = 80; export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => { const [rowHeight, setRowHeight] = useState<number>(0); @@ -21,81 +20,62 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => { const [mounted, setMounted] = useState<boolean>(false); const containerRef = useRef<HTMLDivElement>(null); - const layouts = { - lg: [ - { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 1, minH: 1 }, - { i: 'device-metadata', x: 0, y: 1, w: 2, h: 1, minW: 1, minH: 1 }, - { i: 'device-details', x: 2, y: 0, w: 2, h: 2, minW: 1, minH: 1 } - ] - }; + const layouts = [ + { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 1, minH: 1 }, + { i: 'device-metadata', x: 0, y: 1, w: 2, h: 1, minW: 1, minH: 1 }, + { i: 'device-details', x: 3, y: 0, w: 2, h: 2, minW: 1, minH: 1 } + ]; const calcHeights = () => { const container = containerRef.current; if (!container) { - // Fallback to body height if container is not available const height = document.body.clientHeight * 0.7; setRowHeight(Math.floor(height / RowCount)); return; } - const { top } = container.getBoundingClientRect(); const height = document.body.clientHeight - (top + padding); setContainerHeight(height); setRowHeight(Math.floor(height / RowCount)); - console.log(Math.floor(height / RowCount)); - }; useEffect(() => { calcHeights(); - }, [containerRef.current]) + }, [containerRef.current]); useEffect(() => { setMounted(true); - - window.addEventListener('resize', calcHeights); return () => window.removeEventListener('resize', calcHeights); }, []); - const gridItems = React.Children.map(children.props.children, (child, index) => { - if (!React.isValidElement(child)) return null; - - return React.cloneElement(child, { - key: index === 0 ? 'device-list' : 'device-details', - 'data-grid': layouts.lg[index] - }); - }); - return ( <div ref={containerRef} style={{ display: mounted ? 'block' : 'none', - height: `${containerHeight}px` + height: `${containerHeight}px`, }} > <ResponsiveGridLayout - className="layout" - layouts={layouts} - breakpoints={{ lg: 996, sm: 480 }} - cols={{ lg: 4, sm: 3 }} + cols={5} + layout={layouts} maxRows={RowCount} rowHeight={rowHeight} margin={[20, 20]} draggableHandle=".drag-handle" isDraggable={true} isResizable={true} - preventCollision={true} - compactType={null} - useCSSTransforms={mounted} resizeHandles={['se']} - + useCSSTransforms={true} + resizeHandle={ + <div className="custom-resize-handle"> + <div className="resize-handle-inner" /> + </div> + } > - {gridItems} + {children.props.children} </ResponsiveGridLayout> </div> ); }; - -export default GridLayout; \ No newline at end of file