React IDE page shell (#14988)
* React IDE page shell * Set the maximum height of the symbol palette to 336px * Tidy export * Remove unnecessary destructuring * Update comment * Optimize toggle Co-authored-by: Alf Eaton <alf.eaton@overleaf.com> * Change snap-to-collapse threshold to 5% * Synchronize left column width between history and editor views and remove duplication in ide-page * Replace resizer dots with SVG * Rermove unnecessary import and comment the remaining ones * Use block prepend to avoid duplication * Improve vertical content divider styling * Implement fixed width during container resize on left column * Change IDE page file extension * Refactor fixed-size panel into a hook and use for chat panel --------- Co-authored-by: Alf Eaton <alf.eaton@overleaf.com> GitOrigin-RevId: aa881e48a2838a192b6f8f9e16e561f5cd706bd3
This commit is contained in:
committed by
Copybot
co-authored by
Alf Eaton
parent
afcac7af86
commit
ea1fc5f74e
@@ -0,0 +1,19 @@
|
||||
import { RefObject, useEffect } from 'react'
|
||||
import { ImperativePanelHandle } from 'react-resizable-panels'
|
||||
|
||||
export default function useCollapsiblePanel(
|
||||
panelIsOpen: boolean,
|
||||
panelRef: RefObject<ImperativePanelHandle>
|
||||
) {
|
||||
useEffect(() => {
|
||||
const panel = panelRef.current
|
||||
if (!panel) {
|
||||
return
|
||||
}
|
||||
if (panelIsOpen) {
|
||||
panel.expand()
|
||||
} else {
|
||||
panel.collapse()
|
||||
}
|
||||
}, [panelIsOpen, panelRef])
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { ImperativePanelHandle } from 'react-resizable-panels'
|
||||
import { PanelGroupOnLayout } from 'react-resizable-panels/src/types'
|
||||
|
||||
export default function useFixedSizeColumn(
|
||||
defaultSize: number,
|
||||
isOpen: boolean
|
||||
) {
|
||||
const fixedPanelRef = useRef<ImperativePanelHandle>(null)
|
||||
|
||||
const fixedPanelWidthRef = useRef({ size: defaultSize, pixels: 0 })
|
||||
const [initialLayoutDone, setInitialLayoutDone] = useState(false)
|
||||
|
||||
const measureFixedPanelSizePixels = useCallback(() => {
|
||||
return fixedPanelRef.current?.getSize('pixels') || 0
|
||||
}, [fixedPanelRef])
|
||||
|
||||
const handleLayout = useCallback(
|
||||
sizes => {
|
||||
// Measure the pixel width here because it's not always up to date in the
|
||||
// panel's onResize
|
||||
fixedPanelWidthRef.current = {
|
||||
size: sizes[0],
|
||||
pixels: measureFixedPanelSizePixels(),
|
||||
}
|
||||
setInitialLayoutDone(true)
|
||||
},
|
||||
[measureFixedPanelSizePixels]
|
||||
) as PanelGroupOnLayout
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
// Only start watching for resizes once the initial layout is done,
|
||||
// otherwise we could measure the fixed column while it has zero width and
|
||||
// collapse it
|
||||
if (!initialLayoutDone || !fixedPanelRef.current) {
|
||||
return
|
||||
}
|
||||
|
||||
const fixedPanelElement = document.querySelector(
|
||||
`[data-panel-id="${fixedPanelRef.current.getId()}"]`
|
||||
)
|
||||
|
||||
const panelGroupElement = fixedPanelElement?.closest('[data-panel-group]')
|
||||
if (!panelGroupElement || !fixedPanelElement) {
|
||||
return
|
||||
}
|
||||
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
fixedPanelRef.current?.resize(fixedPanelWidthRef.current.pixels, 'pixels')
|
||||
})
|
||||
|
||||
resizeObserver.observe(panelGroupElement)
|
||||
|
||||
return () => resizeObserver.unobserve(panelGroupElement)
|
||||
}, [fixedPanelRef, measureFixedPanelSizePixels, initialLayoutDone, isOpen])
|
||||
|
||||
return {
|
||||
fixedPanelRef,
|
||||
fixedPanelWidthRef,
|
||||
handleLayout,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user