Changeset View
Changeset View
Standalone View
Standalone View
web/chat/typeahead-tooltip.react.js
// @flow | // @flow | ||||
import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import type { RelativeMemberInfo } from 'lib/types/thread-types'; | import type { RelativeMemberInfo } from 'lib/types/thread-types'; | ||||
import { leastPositiveResidue } from 'lib/utils/math-utils'; | import { leastPositiveResidue } from 'lib/utils/math-utils'; | ||||
import type { InputState } from '../input/input-state'; | import type { InputState } from '../input/input-state'; | ||||
import { | import { | ||||
getTypeaheadOverlayScroll, | |||||
getTypeaheadTooltipActions, | getTypeaheadTooltipActions, | ||||
getTypeaheadTooltipButtons, | getTypeaheadTooltipButtons, | ||||
getTypeaheadTooltipPosition, | getTypeaheadTooltipPosition, | ||||
} from '../utils/typeahead-utils'; | } from '../utils/typeahead-utils'; | ||||
import type { TypeaheadMatchedStrings } from './chat-input-bar.react'; | import type { TypeaheadMatchedStrings } from './chat-input-bar.react'; | ||||
import css from './typeahead-tooltip.css'; | import css from './typeahead-tooltip.css'; | ||||
export type TypeaheadTooltipProps = { | export type TypeaheadTooltipProps = { | ||||
Show All 12 Lines | const [isVisibleForAnimation, setIsVisibleForAnimation] = React.useState( | ||||
false, | false, | ||||
); | ); | ||||
const [ | const [ | ||||
chosenPositionInOverlay, | chosenPositionInOverlay, | ||||
setChosenPositionInOverlay, | setChosenPositionInOverlay, | ||||
] = React.useState<number>(0); | ] = React.useState<number>(0); | ||||
const overlayRef = React.useRef<?HTMLDivElement>(); | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setChosenPositionInOverlay(0); | setChosenPositionInOverlay(0); | ||||
}, [suggestedUsers]); | }, [suggestedUsers]); | ||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setIsVisibleForAnimation(true); | setIsVisibleForAnimation(true); | ||||
return () => setIsVisibleForAnimation(false); | return () => setIsVisibleForAnimation(false); | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | React.useEffect(() => { | ||||
close, | close, | ||||
accept, | accept, | ||||
moveChoiceUp, | moveChoiceUp, | ||||
moveChoiceDown, | moveChoiceDown, | ||||
actions, | actions, | ||||
inputState.setTypeaheadState, | inputState.setTypeaheadState, | ||||
]); | ]); | ||||
React.useEffect(() => { | |||||
const current = overlayRef.current; | |||||
if (current) { | |||||
const newScrollTop = getTypeaheadOverlayScroll( | |||||
current.scrollTop, | |||||
chosenPositionInOverlay, | |||||
); | |||||
current.scrollTo(0, newScrollTop); | |||||
} | |||||
}, [chosenPositionInOverlay]); | |||||
if (suggestedUsers.length === 0) { | if (suggestedUsers.length === 0) { | ||||
return null; | return null; | ||||
} | } | ||||
const overlayClasses = classNames(css.suggestionsContainer, { | const overlayClasses = classNames(css.suggestionsContainer, { | ||||
[css.notVisible]: !isVisibleForAnimation, | [css.notVisible]: !isVisibleForAnimation, | ||||
[css.visible]: isVisibleForAnimation, | [css.visible]: isVisibleForAnimation, | ||||
}); | }); | ||||
return ( | return ( | ||||
<div className={overlayClasses} style={tooltipPositionStyle}> | <div | ||||
ref={overlayRef} | |||||
className={overlayClasses} | |||||
style={tooltipPositionStyle} | |||||
> | |||||
{tooltipButtons} | {tooltipButtons} | ||||
</div> | </div> | ||||
); | ); | ||||
} | } | ||||
export default TypeaheadTooltip; | export default TypeaheadTooltip; |