Skip to content
Snippets Groups Projects
Commit 6069e4e1 authored by Matthias Feyll's avatar Matthias Feyll :cookie:
Browse files

(ui): improve grid layout

parent 17c852ea
No related branches found
No related tags found
2 merge requests!1196[renovate] Update module golang.org/x/net to v0.32.0,!1195UI: implement add device functionality
@import "/src/shared/style/colors.scss"; @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 { .drag-handle {
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -25,8 +67,6 @@ ...@@ -25,8 +67,6 @@
.react-grid-item { .react-grid-item {
&.react-draggable-dragging { &.react-draggable-dragging {
z-index: 100;
.drag-handle { .drag-handle {
cursor: grabbing; cursor: grabbing;
} }
......
import React, { ReactElement, useEffect, useRef, useState } from 'react'; 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-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css'; import 'react-resizable/css/styles.css';
import './grid.layout.scss'; import './grid.layout.scss';
const ResponsiveGridLayout = WidthProvider(Responsive); const ResponsiveGridLayout = WidthProvider(RGL);
interface GridLayoutProps { interface GridLayoutProps {
children: ReactElement; children: ReactElement;
} }
getComputedStyle
const RowCount = 2; const RowCount = 2;
const padding = 80; // in px const padding = 80;
export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => { export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
const [rowHeight, setRowHeight] = useState<number>(0); const [rowHeight, setRowHeight] = useState<number>(0);
...@@ -21,81 +20,62 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => { ...@@ -21,81 +20,62 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
const [mounted, setMounted] = useState<boolean>(false); const [mounted, setMounted] = useState<boolean>(false);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const layouts = { const layouts = [
lg: [ { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 1, minH: 1 },
{ 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-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 }
{ i: 'device-details', x: 2, y: 0, w: 2, h: 2, minW: 1, minH: 1 } ];
]
};
const calcHeights = () => { const calcHeights = () => {
const container = containerRef.current; const container = containerRef.current;
if (!container) { if (!container) {
// Fallback to body height if container is not available
const height = document.body.clientHeight * 0.7; const height = document.body.clientHeight * 0.7;
setRowHeight(Math.floor(height / RowCount)); setRowHeight(Math.floor(height / RowCount));
return; return;
} }
const { top } = container.getBoundingClientRect(); const { top } = container.getBoundingClientRect();
const height = document.body.clientHeight - (top + padding); const height = document.body.clientHeight - (top + padding);
setContainerHeight(height); setContainerHeight(height);
setRowHeight(Math.floor(height / RowCount)); setRowHeight(Math.floor(height / RowCount));
console.log(Math.floor(height / RowCount));
}; };
useEffect(() => { useEffect(() => {
calcHeights(); calcHeights();
}, [containerRef.current]) }, [containerRef.current]);
useEffect(() => { useEffect(() => {
setMounted(true); setMounted(true);
window.addEventListener('resize', calcHeights); window.addEventListener('resize', calcHeights);
return () => window.removeEventListener('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 ( return (
<div <div
ref={containerRef} ref={containerRef}
style={{ style={{
display: mounted ? 'block' : 'none', display: mounted ? 'block' : 'none',
height: `${containerHeight}px` height: `${containerHeight}px`,
}} }}
> >
<ResponsiveGridLayout <ResponsiveGridLayout
className="layout" cols={5}
layouts={layouts} layout={layouts}
breakpoints={{ lg: 996, sm: 480 }}
cols={{ lg: 4, sm: 3 }}
maxRows={RowCount} maxRows={RowCount}
rowHeight={rowHeight} rowHeight={rowHeight}
margin={[20, 20]} margin={[20, 20]}
draggableHandle=".drag-handle" draggableHandle=".drag-handle"
isDraggable={true} isDraggable={true}
isResizable={true} isResizable={true}
preventCollision={true}
compactType={null}
useCSSTransforms={mounted}
resizeHandles={['se']} resizeHandles={['se']}
useCSSTransforms={true}
resizeHandle={
<div className="custom-resize-handle">
<div className="resize-handle-inner" />
</div>
}
> >
{gridItems} {children.props.children}
</ResponsiveGridLayout> </ResponsiveGridLayout>
</div> </div>
); );
}; };
export default GridLayout;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment