Skip to content

Commit 32786bb

Browse files
committed
feat: add resize support to virtual elements
1 parent e497bda commit 32786bb

File tree

1 file changed

+74
-54
lines changed

1 file changed

+74
-54
lines changed

packages/webui/src/client/lib/VirtualElement.tsx

Lines changed: 74 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,11 @@ export function VirtualElement({
6969
const [measurements, setMeasurements] = useState<IElementMeasurements | null>(null)
7070
const [ref, setRef] = useState<HTMLDivElement | null>(null)
7171

72+
// Store the old dashboard height to detect changes:
73+
let oldDashboardHeight: number | undefined
74+
let resizeTimeout: NodeJS.Timeout
75+
7276
const showPlaceholder = !isShowingChildren && !initialShow
73-
//let resizeTimeout: NodeJS.Timeout
7477

7578
// Track the last visibility change to debounce
7679
const lastVisibilityChangeRef = useRef<number>(0)
@@ -121,59 +124,72 @@ export function VirtualElement({
121124
return false
122125
}
123126

124-
// // Handle Viewport width changes:
125-
// useEffect(() => {
126-
// let oldWidth = ref?.clientWidth
127-
128-
// function handleResize() {
129-
// if (ref) {
130-
// // Show children during measurement
131-
// setIsShowingChildren(true)
132-
// if (resizeTimeout) {
133-
// clearTimeout(resizeTimeout)
134-
// }
135-
// resizeTimeout = setTimeout(() => {
136-
// setMeasurements(null)
137-
// requestAnimationFrame(() => {
138-
// const measurements = measureElement(ref, placeholderHeight)
139-
// if (measurements) {
140-
// setMeasurements(measurements)
141-
142-
// // Only hide children again if not in view
143-
// if (!inView) {
144-
// setIsShowingChildren(false)
145-
// }
146-
// }
147-
// })
148-
// }, 50)
149-
// }
150-
// }
151-
152-
// const resizeObserver = new ResizeObserver(() => {
153-
// // Find the segment-timeline-container parent
154-
// const timelineWrapper = ref?.closest('.segment-timeline-wrapper--shelf')?.querySelector('.dashboard-panel')
155-
156-
// // Get width of timeline wrapper
157-
// const containerWidth = timelineWrapper?.clientWidth
158-
159-
// if (containerWidth !== oldWidth) {
160-
// handleResize()
161-
// oldWidth = containerWidth
162-
// }
163-
// })
164-
165-
// if (ref) {
166-
// // Find and observe the segment-timeline-container parent
167-
// const timelineContainer = ref.closest('.segment-timeline-container')
168-
// if (timelineContainer) {
169-
// resizeObserver.observe(timelineContainer)
170-
// }
171-
// }
172-
173-
// return () => {
174-
// resizeObserver.disconnect()
175-
// }
176-
// }, [inView, ref])
127+
// // Handle Viewport heigth changes:
128+
useEffect(() => {
129+
function handleResize() {
130+
if (ref) {
131+
// Show children during measurement
132+
setIsShowingChildren(true)
133+
if (resizeTimeout) {
134+
clearTimeout(resizeTimeout)
135+
}
136+
resizeTimeout = setTimeout(() => {
137+
requestAnimationFrame(() => {
138+
const measurements = measureElement(ref, placeholderHeight)
139+
if (measurements) {
140+
setMeasurements(measurements)
141+
142+
// Only hide children again if not in view
143+
if (!inView && measurements.clientHeight > 0) {
144+
setIsShowingChildren(false)
145+
} else {
146+
setIsShowingChildren(true)
147+
}
148+
}
149+
})
150+
}, 500)
151+
}
152+
}
153+
154+
const findDashboardPanel = (el: HTMLElement | null): HTMLElement | null => {
155+
if (!el) {
156+
return null
157+
}
158+
const timelineWrapper = ref?.closest('.segment-timeline-wrapper--shelf')
159+
const dashboardPanel = timelineWrapper?.querySelector('.dashboard-panel')
160+
if (dashboardPanel) {
161+
return dashboardPanel as HTMLElement
162+
}
163+
return null
164+
}
165+
166+
const resizeObserver = new ResizeObserver(() => {
167+
const dashboardElement = findDashboardPanel(ref)
168+
// Get heigth of timeline wrapper
169+
const containerHeight = dashboardElement?.clientHeight
170+
171+
if (containerHeight && containerHeight !== oldDashboardHeight) {
172+
console.log('dashboard containerHeigth changed to ', containerHeight, 'from', oldDashboardHeight)
173+
oldDashboardHeight = containerHeight
174+
handleResize()
175+
}
176+
})
177+
178+
if (ref) {
179+
// Delay the initial observer to allow the UI to render
180+
setTimeout(() => {
181+
const dashboardElement = findDashboardPanel(ref)
182+
if (dashboardElement) {
183+
oldDashboardHeight = dashboardElement?.clientHeight
184+
resizeObserver.observe(ref)
185+
}
186+
}, 2000)
187+
}
188+
189+
return () => {
190+
resizeObserver.disconnect()
191+
}
192+
}, [inView, ref, placeholderHeight])
177193

178194
useEffect(() => {
179195
if (inView === true) {
@@ -300,6 +316,10 @@ function measureElement(wrapperEl: HTMLDivElement, placeholderHeight?: number):
300316
totalHeight += panelRect.height
301317
}
302318

319+
if (totalHeight < 10) {
320+
totalHeight = placeholderHeight ?? el.clientHeight
321+
}
322+
303323
return {
304324
width: style.width || 'auto',
305325
clientHeight: totalHeight,

0 commit comments

Comments
 (0)