allotment
allotment copied to clipboard
preferredSize do not work
Hi, i try it to create layout like vscode, but 'preferredSize={280}' don't work at 'E' section.
<Allotment vertical={true}>
<Allotment.Pane maxSize={30} minSize={30}>
<div>A</div>
</Allotment.Pane>
<Allotment.Pane>
<Allotment>
<Allotment.Pane maxSize={48} minSize={48}>
<div>B</div>
</Allotment.Pane>
<Allotment.Pane preferredSize={280} minSize={170} snap={true}>
<div>C</div>
</Allotment.Pane>
<Allotment.Pane>
<Allotment vertical={true}>
<Allotment.Pane>
<div>D</div>
</Allotment.Pane>
{/*at here, preferredSize={280} don't work*/}
<Allotment.Pane preferredSize={280} minSize={120} snap={true}>
<div>E</div>
</Allotment.Pane>
</Allotment>
</Allotment.Pane>
<Allotment.Pane preferredSize={280} minSize={170} snap={true}>
<div>F</div>
</Allotment.Pane>
</Allotment>
</Allotment.Pane>
<Allotment.Pane maxSize={22} minSize={22}>
<div>G</div>
</Allotment.Pane>
</Allotment>
I trace code and debug, found it caused container has no 'width' and 'height'.
useIsomorphicLayoutEffect(() => {
if (!dimensionsInitialized) {
const { height, width } = containerRef.current.getBoundingClientRect(); // here
splitViewRef.current?.layout(vertical ? height : width);
layoutService.current.setSize(vertical ? height : width);
setDimensionsInitialized(true);
}
}, [dimensionsInitialized, vertical]);
Since the mounting of React is from the inside to the outside,so container has no width and height
I fixed it by below code:
diff --git a/src/allotment.tsx b/src/allotment.tsx
index ea2385f..c555e20 100644
--- a/src/allotment.tsx
+++ b/src/allotment.tsx
@@ -29,6 +29,17 @@ function isPane(item: React.ReactNode | typeof Pane): item is typeof Pane {
return (item as any).type.displayName === "Allotment.Pane";
}
+function containAllotment(item: React.ReactNode | typeof Allotment): item is typeof Allotment {
+ let result = false
+ React.Children.toArray((item as any).props?.children).map((child)=>{
+ if((child as any).type.displayName === "Allotment")
+ {
+ result = true
+ }
+ })
+ return result
+}
+
function isPaneProps(props: AllotmentProps | PaneProps): props is PaneProps {
return (
(props as PaneProps).minSize !== undefined ||
@@ -145,6 +156,7 @@ const Allotment = forwardRef<AllotmentHandle, AllotmentProps>(
const splitViewViewRef = useRef(new Map<React.Key, HTMLElement>());
const layoutService = useRef<LayoutService>(new LayoutService());
const views = useRef<PaneView[]>([]);
+ const [paneWithAllotmentInitialized, setPaneWithAllotmentInitialized] = useState(false)
const [dimensionsInitialized, setDimensionsInitialized] = useState(false);
@@ -463,6 +475,7 @@ const Allotment = forwardRef<AllotmentHandle, AllotmentProps>(
const { height, width } = containerRef.current.getBoundingClientRect();
splitViewRef.current?.layout(vertical ? height : width);
layoutService.current.setSize(vertical ? height : width);
+ setPaneWithAllotmentInitialized(true);
setDimensionsInitialized(true);
}
}, [dimensionsInitialized, vertical]);
@@ -503,16 +516,23 @@ const Allotment = forwardRef<AllotmentHandle, AllotmentProps>(
if (isPane(child)) {
splitViewPropsRef.current.set(key, child.props);
- return React.cloneElement(child as React.ReactElement, {
- key: key,
- ref: (el: HTMLElement | null) => {
- if (el) {
- splitViewViewRef.current.set(key, el);
- } else {
- splitViewViewRef.current.delete(key);
- }
- },
- });
+ if(!paneWithAllotmentInitialized && containAllotment(child) && !defaultSizes)
+ {
+ return null
+ }
+ else
+ {
+ return React.cloneElement(child as React.ReactElement, {
+ key: key,
+ ref: (el: HTMLElement | null) => {
+ if (el) {
+ splitViewViewRef.current.set(key, el);
+ } else {
+ splitViewViewRef.current.delete(key);
+ }
+ },
+ });
+ }
} else {
return (
<Pane
@johnwalley would be nice to include it into nearest release
Hey @johnwalley I am also encountering this issue on v1.19.0 and was wondering if you have any plans to include the fix above in the newest release? Cheers!
@johnwalley any updates about it?
Hi, I also encountered the same problem! Here is my solution
const ref = useRef<any>();
useEffect(() => {
setTimeout(() => ref.current.reset(), 0);
}, []);
<Allotment ref={ref}>
<Allotment.Pane
visible={visible}
preferredSize={200}
minSize={200}
maxSize={400}
>
<div></div>
</Allotment.Pane>
<div></div>
</Allotment>
🤷♂️ The preferredSize
does not seem to work anymore at all. Also, @tpc-ht's suggestion did not work for me.
✅ I had better results with a combination of defaultSizes
and proportionalLayout=false
in addition to a onReset
. This is a minimal example (without optimized callbacks etc.)
const ref = useRef<AllotmentHandle>(null)
const sizes = [200, 0]} // Set first size and "ignore" second
const handleReset = () => {
ref.current?.resize(sizes)} // mimics the doubleClick behavior as before
}
return (
<Allotment
ref={ref} // get access to resize(...)
proportionalLayout={false} // use pixel sizes (not percentage)
defaultSizes={sizes} // Set first size and "ignore" second
onReset={handleReset} // override reset to use "defaultSizes"
>
// ... content, panes, ...
</Allotment>
)
Wrapping this into a component actually restores the preferredSize behavior until it is fixed in the lib.
Also seeing that preferredSize is not respected on a nested Allotment
since version 1.18.0 onwards.
Heres a repro of the issue: https://codesandbox.io/p/sandbox/nested-forked-v4j9qz
My simple fix for now was to downgrade to v1.17.1, but I'd like to contribute if possible
Thanks everyone for reporting this.
I've reverted the commit which appears to trigger the problem and published a new package v1.20.2.
If you get a chance to test it and report back that would be super helpful.
@johnwalley v1.20.2 is working for me
@johnwalley same for me. works fine now