Enhance DashboardOverviewFlexColumns with Vertical Layout Support
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Added functionality to toggle between vertical and horizontal layouts in the DashboardOverviewFlexColumns component, improving responsiveness based on available space. - Implemented useLayoutEffect to manage layout changes dynamically, ensuring optimal display of child components. - Updated CSS styles to support the new vertical layout, enhancing the overall user experience in the dashboard.
This commit is contained in:
parent
e3a20e6b48
commit
b347ec3637
@ -2005,6 +2005,12 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.overview-flex-columns.is-vertical .overview-flex-columns-item {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.overview-flex-columns-empty {
|
||||
flex: 1;
|
||||
min-height: 48px;
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
isValidElement,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState
|
||||
@ -55,8 +56,114 @@ const DashboardOverviewFlexColumns = ({
|
||||
[childList.length, proportions]
|
||||
)
|
||||
const dragRef = useRef(null)
|
||||
const rowRef = useRef(null)
|
||||
const onProportionsChangeRef = useRef(onProportionsChange)
|
||||
const stackAtWidthRef = useRef(null)
|
||||
const isVerticalRef = useRef(false)
|
||||
const [activeSeparator, setActiveSeparator] = useState(null)
|
||||
const [isVertical, setIsVertical] = useState(false)
|
||||
|
||||
const setVertical = useCallback((next) => {
|
||||
isVerticalRef.current = next
|
||||
setIsVertical((previous) => (previous === next ? previous : next))
|
||||
}, [])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const row = rowRef.current
|
||||
if (!row || isEmpty) {
|
||||
stackAtWidthRef.current = null
|
||||
setVertical(false)
|
||||
return undefined
|
||||
}
|
||||
|
||||
const hasHorizontalOverflow = (items) => {
|
||||
if (row.scrollWidth > row.clientWidth + 1) {
|
||||
return true
|
||||
}
|
||||
|
||||
return items.some((item) => item.scrollWidth > item.clientWidth + 1)
|
||||
}
|
||||
|
||||
let frame = null
|
||||
|
||||
const update = () => {
|
||||
const rowWidth = row.clientWidth
|
||||
if (rowWidth < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
const flexEl = row.firstElementChild
|
||||
if (!flexEl) {
|
||||
return
|
||||
}
|
||||
|
||||
const items = [...row.querySelectorAll('.overview-flex-columns-item')]
|
||||
if (!items.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const stackState = stackAtWidthRef.current
|
||||
|
||||
if (!isVerticalRef.current) {
|
||||
if (
|
||||
stackState &&
|
||||
stackState.childCount === items.length &&
|
||||
rowWidth > stackState.width
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
if (hasHorizontalOverflow(items)) {
|
||||
stackAtWidthRef.current = {
|
||||
width: rowWidth,
|
||||
childCount: items.length
|
||||
}
|
||||
setVertical(true)
|
||||
return
|
||||
}
|
||||
|
||||
stackAtWidthRef.current = null
|
||||
setVertical(false)
|
||||
return
|
||||
}
|
||||
|
||||
if (!stackState || stackState.childCount !== items.length) {
|
||||
stackAtWidthRef.current = null
|
||||
setVertical(false)
|
||||
return
|
||||
}
|
||||
|
||||
if (rowWidth > stackState.width) {
|
||||
setVertical(false)
|
||||
}
|
||||
}
|
||||
|
||||
const scheduleUpdate = () => {
|
||||
if (frame != null) {
|
||||
cancelAnimationFrame(frame)
|
||||
}
|
||||
frame = requestAnimationFrame(() => {
|
||||
frame = null
|
||||
update()
|
||||
})
|
||||
}
|
||||
|
||||
scheduleUpdate()
|
||||
|
||||
const resizeObserver = new ResizeObserver(scheduleUpdate)
|
||||
resizeObserver.observe(row)
|
||||
|
||||
row.querySelectorAll('.overview-flex-columns-item').forEach((item) => {
|
||||
resizeObserver.observe(item)
|
||||
})
|
||||
|
||||
return () => {
|
||||
if (frame != null) {
|
||||
cancelAnimationFrame(frame)
|
||||
}
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
}, [childList, isEmpty, resolvedProportions, setVertical])
|
||||
|
||||
useEffect(() => {
|
||||
onProportionsChangeRef.current = onProportionsChange
|
||||
@ -170,7 +277,9 @@ const DashboardOverviewFlexColumns = ({
|
||||
isLayoutEditing ? 'is-editing' : ''
|
||||
} ${isDragOver ? 'is-drag-over' : ''} ${
|
||||
isEmpty && isLayoutEditing ? 'is-empty' : ''
|
||||
} ${activeSeparator != null ? 'is-resizing' : ''}`}
|
||||
} ${activeSeparator != null ? 'is-resizing' : ''} ${
|
||||
isVertical ? 'is-vertical' : ''
|
||||
}`}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={onDrop}
|
||||
onDragLeave={onDragLeave}
|
||||
@ -195,11 +304,13 @@ const DashboardOverviewFlexColumns = ({
|
||||
</Flex>
|
||||
</Card>
|
||||
)}
|
||||
<div ref={rowRef} className='overview-flex-columns-row'>
|
||||
<Flex
|
||||
vertical={isVertical}
|
||||
gap='large'
|
||||
align='stretch'
|
||||
className='overview-flex-columns-row'
|
||||
wrap='nowrap'
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{isEmpty && isLayoutEditing ? (
|
||||
<div className='overview-flex-columns-empty'>Drop sections here</div>
|
||||
@ -208,12 +319,13 @@ const DashboardOverviewFlexColumns = ({
|
||||
if (!isValidElement(child)) return child
|
||||
const proportion = resolvedProportions[index] ?? 0
|
||||
const showSeparator =
|
||||
isLayoutEditing && index < childList.length - 1
|
||||
!isVertical && isLayoutEditing && index < childList.length - 1
|
||||
return cloneElement(child, {
|
||||
style: {
|
||||
...child.props.style,
|
||||
flex: `${proportion} 1 0`,
|
||||
minWidth: 0,
|
||||
...(isVertical
|
||||
? { width: '100%', flex: 'none' }
|
||||
: { flex: `${proportion} 1 0`, minWidth: 0 }),
|
||||
position: 'relative'
|
||||
},
|
||||
children: (
|
||||
@ -234,6 +346,7 @@ const DashboardOverviewFlexColumns = ({
|
||||
)}
|
||||
</Flex>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user