( props: MenuPlacerProps<Option, IsMulti, Group> )
| 310 | |
| 311 | // NOTE: internal only |
| 312 | export const MenuPlacer = < |
| 313 | Option, |
| 314 | IsMulti extends boolean, |
| 315 | Group extends GroupBase<Option> |
| 316 | >( |
| 317 | props: MenuPlacerProps<Option, IsMulti, Group> |
| 318 | ) => { |
| 319 | const { |
| 320 | children, |
| 321 | minMenuHeight, |
| 322 | maxMenuHeight, |
| 323 | menuPlacement, |
| 324 | menuPosition, |
| 325 | menuShouldScrollIntoView, |
| 326 | theme, |
| 327 | } = props; |
| 328 | |
| 329 | const { setPortalPlacement } = useContext(PortalPlacementContext) || {}; |
| 330 | const ref = useRef<HTMLDivElement | null>(null); |
| 331 | const [maxHeight, setMaxHeight] = useState(maxMenuHeight); |
| 332 | const [placement, setPlacement] = useState<CoercedMenuPlacement | null>(null); |
| 333 | const { controlHeight } = theme.spacing; |
| 334 | |
| 335 | useLayoutEffect(() => { |
| 336 | const menuEl = ref.current; |
| 337 | if (!menuEl) return; |
| 338 | |
| 339 | // DO NOT scroll if position is fixed |
| 340 | const isFixedPosition = menuPosition === 'fixed'; |
| 341 | const shouldScroll = menuShouldScrollIntoView && !isFixedPosition; |
| 342 | |
| 343 | const state = getMenuPlacement({ |
| 344 | maxHeight: maxMenuHeight, |
| 345 | menuEl, |
| 346 | minHeight: minMenuHeight, |
| 347 | placement: menuPlacement, |
| 348 | shouldScroll, |
| 349 | isFixedPosition, |
| 350 | controlHeight, |
| 351 | }); |
| 352 | |
| 353 | setMaxHeight(state.maxHeight); |
| 354 | setPlacement(state.placement); |
| 355 | setPortalPlacement?.(state.placement); |
| 356 | }, [ |
| 357 | maxMenuHeight, |
| 358 | menuPlacement, |
| 359 | menuPosition, |
| 360 | menuShouldScrollIntoView, |
| 361 | minMenuHeight, |
| 362 | setPortalPlacement, |
| 363 | controlHeight, |
| 364 | ]); |
| 365 | |
| 366 | return children({ |
| 367 | ref, |
| 368 | placerProps: { |
| 369 | ...props, |
nothing calls this directly
no test coverage detected
searching dependent graphs…