-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added simple extra popover to keep other controls out of display (#2880)
* Added simple extra popover to keep other controls out of display * Removed extra change * Fixed part of tests * Added extra comments * Updated version & changelog
- Loading branch information
Boris Sekachev
authored
Mar 1, 2021
1 parent
5bd61a4
commit 55b20e1
Showing
21 changed files
with
200 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
...ents/annotation-page/standard-workspace/controls-side-bar/control-visibility-observer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright (C) 2021 Intel Corporation | ||
// | ||
// SPDX-License-Identifier: MIT | ||
|
||
/// <reference types="resize-observer-browser" /> | ||
|
||
import { SmallDashOutlined } from '@ant-design/icons'; | ||
import Popover from 'antd/lib/popover'; | ||
import React, { useEffect, useRef, useState } from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
const extraControlsContentClassName = 'cvat-extra-controls-control-content'; | ||
|
||
let onUpdateChildren: Function | null = null; | ||
export function ExtraControlsControl(): JSX.Element { | ||
const [hasChildren, setHasChildren] = useState(false); | ||
const [initialized, setInitialized] = useState(false); | ||
|
||
useEffect(() => { | ||
if (!initialized) { | ||
setInitialized(true); | ||
} | ||
|
||
window.document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); | ||
}, []); | ||
|
||
onUpdateChildren = () => { | ||
const contentElement = window.document.getElementsByClassName(extraControlsContentClassName)[0]; | ||
if (contentElement) { | ||
setHasChildren(contentElement.children.length > 0); | ||
} | ||
}; | ||
|
||
return ( | ||
<Popover | ||
defaultVisible // we must render it at least one between using | ||
trigger={initialized ? 'hover' : 'click'} // trigger='hover' allows to close the popover by body click | ||
placement='right' | ||
overlayStyle={{ display: initialized ? '' : 'none' }} | ||
content={<div className={extraControlsContentClassName} />} | ||
> | ||
<SmallDashOutlined | ||
style={{ visibility: hasChildren ? 'visible' : 'hidden' }} | ||
className='cvat-extra-controls-control' | ||
/> | ||
</Popover> | ||
); | ||
} | ||
|
||
export default function ControlVisibilityObserver<P = {}>( | ||
ControlComponent: React.FunctionComponent<P>, | ||
): React.FunctionComponent<P> { | ||
let visibilityHeightThreshold = 0; // minimum value of height when element can be pushed to main panel | ||
|
||
return (props: P): JSX.Element | null => { | ||
const ref = useRef<HTMLDivElement>(null); | ||
const [visible, setVisible] = useState(true); | ||
|
||
useEffect(() => { | ||
if (ref && ref.current) { | ||
const wrapper = ref.current; | ||
const parentElement = ref.current.parentElement as HTMLElement; | ||
|
||
const reservedHeight = 45; // for itself | ||
const observer = new ResizeObserver(() => { | ||
// when parent size was changed, check again can we put the control | ||
// into the side panel or not | ||
const availableHeight = parentElement.offsetHeight; | ||
setVisible(availableHeight - reservedHeight >= visibilityHeightThreshold); | ||
}); | ||
|
||
if (ref && ref.current) { | ||
const availableHeight = parentElement.offsetHeight; | ||
// when first mount, remember bottom coordinate which equal to minimum parent width | ||
// to put the control into side panel | ||
visibilityHeightThreshold = wrapper.offsetTop + wrapper.offsetHeight; | ||
// start observing parent size | ||
observer.observe(ref.current.parentElement as HTMLElement); | ||
// then put it to extra controls if parent height is not enought | ||
setVisible(availableHeight - reservedHeight >= visibilityHeightThreshold); | ||
} | ||
|
||
return () => { | ||
observer.disconnect(); | ||
}; | ||
} | ||
|
||
return () => {}; | ||
}, []); | ||
|
||
useEffect(() => { | ||
// when visibility changed, we notify extra content element because now its children changed | ||
if (onUpdateChildren) { | ||
onUpdateChildren(); | ||
} | ||
}, [visible]); | ||
|
||
if (!visible) { | ||
const extraControlsContent = window.document.getElementsByClassName(extraControlsContentClassName)[0]; | ||
if (extraControlsContent) { | ||
return ReactDOM.createPortal(<ControlComponent {...props} />, extraControlsContent); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
// first mount always to side panel | ||
return ( | ||
<div ref={ref}> | ||
<ControlComponent {...props} /> | ||
</div> | ||
); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.