mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): minimum gallery size
Add `useMinimumPanelSize()` hook to provide minimum resizable panel sizes (in pixels). The library we are using for the gallery panel uses percentages only. To provide a minimum size in pixels, we need to do some math to calculate the percentage of window size that corresponds to the desired min width in pixels.
This commit is contained in:
parent
d9ac36df1d
commit
3aa6a7e7df
@ -36,6 +36,7 @@ import { FaFont, FaImage } from 'react-icons/fa';
|
||||
import ResizeHandle from './tabs/ResizeHandle';
|
||||
import ImageTab from './tabs/ImageToImage/ImageToImageTab';
|
||||
import AuxiliaryProgressIndicator from 'app/components/AuxiliaryProgressIndicator';
|
||||
import { useMinimumPanelSize } from '../hooks/useMinimumPanelSize';
|
||||
|
||||
export interface InvokeTabInfo {
|
||||
id: InvokeTabName;
|
||||
@ -78,6 +79,9 @@ const enabledTabsSelector = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
const MIN_GALLERY_WIDTH = 300;
|
||||
const DEFAULT_GALLERY_PCT = 20;
|
||||
|
||||
const InvokeTabs = () => {
|
||||
const activeTab = useAppSelector(activeTabIndexSelector);
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
@ -150,6 +154,9 @@ const InvokeTabs = () => {
|
||||
[enabledTabs]
|
||||
);
|
||||
|
||||
const { ref: galleryPanelRef, minSizePct: galleryMinSizePct } =
|
||||
useMinimumPanelSize(MIN_GALLERY_WIDTH, DEFAULT_GALLERY_PCT, 'app');
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
defaultIndex={activeTab}
|
||||
@ -175,6 +182,7 @@ const InvokeTabs = () => {
|
||||
<AuxiliaryProgressIndicator />
|
||||
</TabList>
|
||||
<PanelGroup
|
||||
id="app"
|
||||
autoSaveId="app"
|
||||
direction="horizontal"
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
@ -188,11 +196,12 @@ const InvokeTabs = () => {
|
||||
<>
|
||||
<ResizeHandle />
|
||||
<Panel
|
||||
ref={galleryPanelRef}
|
||||
onResize={handleResizeGallery}
|
||||
id="gallery"
|
||||
order={3}
|
||||
defaultSize={10}
|
||||
minSize={10}
|
||||
defaultSize={galleryMinSizePct}
|
||||
minSize={galleryMinSizePct}
|
||||
maxSize={50}
|
||||
>
|
||||
<ImageGalleryContent />
|
||||
|
@ -0,0 +1,70 @@
|
||||
// adapted from https://github.com/bvaughn/react-resizable-panels/issues/141#issuecomment-1540048714
|
||||
|
||||
import {
|
||||
RefObject,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { ImperativePanelHandle } from 'react-resizable-panels';
|
||||
|
||||
export const useMinimumPanelSize = (
|
||||
minSizePx: number,
|
||||
defaultSizePct: number,
|
||||
groupId: string,
|
||||
orientation: 'horizontal' | 'vertical' = 'horizontal'
|
||||
): { ref: RefObject<ImperativePanelHandle>; minSizePct: number } => {
|
||||
const ref = useRef<ImperativePanelHandle>(null);
|
||||
const [minSizePct, setMinSizePct] = useState(defaultSizePct);
|
||||
|
||||
const handleWindowResize = useCallback(() => {
|
||||
const size = ref.current?.getSize();
|
||||
|
||||
if (size !== undefined && size < minSizePct) {
|
||||
ref.current?.resize(minSizePct);
|
||||
}
|
||||
}, [minSizePct]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const panelGroup = document.querySelector(
|
||||
`[data-panel-group-id="${groupId}"]`
|
||||
);
|
||||
const resizeHandles = document.querySelectorAll(
|
||||
'[data-panel-resize-handle-id]'
|
||||
);
|
||||
|
||||
if (!panelGroup) {
|
||||
return;
|
||||
}
|
||||
const observer = new ResizeObserver(() => {
|
||||
let dim =
|
||||
orientation === 'horizontal'
|
||||
? panelGroup.getBoundingClientRect().width
|
||||
: panelGroup.getBoundingClientRect().height;
|
||||
|
||||
resizeHandles.forEach((resizeHandle) => {
|
||||
dim -=
|
||||
orientation === 'horizontal'
|
||||
? resizeHandle.getBoundingClientRect().width
|
||||
: resizeHandle.getBoundingClientRect().height;
|
||||
});
|
||||
|
||||
// Minimum size in pixels is a percentage of the PanelGroup's width/height
|
||||
setMinSizePct((minSizePx / dim) * 100);
|
||||
});
|
||||
observer.observe(panelGroup);
|
||||
resizeHandles.forEach((resizeHandle) => {
|
||||
observer.observe(resizeHandle);
|
||||
});
|
||||
|
||||
window.addEventListener('resize', handleWindowResize);
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
window.removeEventListener('resize', handleWindowResize);
|
||||
};
|
||||
}, [groupId, handleWindowResize, minSizePct, minSizePx, orientation]);
|
||||
|
||||
return { ref, minSizePct };
|
||||
};
|
Loading…
Reference in New Issue
Block a user