UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

55 lines (54 loc) 2.45 kB
import { autoPlacement, autoUpdate, flip as flipMw, offset as offsetMw, shift as shiftMw, size as sizeMw, useFloating, } from '@floating-ui/react'; const hasResizeObserver = typeof window !== 'undefined' && 'ResizeObserver' in window; function autoMiddlewareFor(p) { if (!String(p).startsWith('auto')) return null; const alignment = p === 'auto-start' ? 'start' : p === 'auto-end' ? 'end' : undefined; return autoPlacement({ alignment }); } function toOffsetMw(opt) { if (opt == null) return null; if (Array.isArray(opt)) { const [crossAxis, mainAxis] = opt; return offsetMw({ crossAxis, mainAxis }); } if (typeof opt === 'number') return offsetMw(opt); return offsetMw(opt); } export function usePopoverPosition({ allowFlip = true, allowShift = true, autoUpdateOptions, fitAvailableSpace = false, freeze = false, offset, placement = 'bottom-start', }) { const autoMw = autoMiddlewareFor(placement); const offsetMiddleware = toOffsetMw(offset); const isSidePlacement = placement.startsWith('left') || placement.startsWith('right'); const middleware = [ // offset first (mirrors common Popper setups) ...(offsetMiddleware ? [offsetMiddleware] : []), // choose between autoPlacement (Popper's "auto*") OR flip() // only allow flip when not explicitly 'left*' or 'right*' ...(autoMw ? [autoMw] : allowFlip && !isSidePlacement ? [flipMw()] : []), // viewport collision adjustments ...(allowShift ? [shiftMw({ padding: 8 })] : []), // optional size constraining // eslint-disable-next-line @typescript-eslint/no-empty-function ...(fitAvailableSpace ? [sizeMw({ apply: () => { } })] : []), ]; // if placement is 'auto*', seed with any static placement; autoPlacement will pick the final one const seedPlacement = String(placement).startsWith('auto') ? 'bottom' : placement; return useFloating({ middleware, placement: seedPlacement, strategy: 'fixed', whileElementsMounted: freeze ? undefined : (reference, floating, update) => autoUpdate(reference, floating, update, { ancestorResize: true, ancestorScroll: true, animationFrame: false, elementResize: hasResizeObserver, ...autoUpdateOptions, }), }); }