import React, { useEffect, useState, type HTMLAttributes } from 'react'
import {
autoPlacement,
autoUpdate,
offset,
size,
useFloating,
type UseFloatingOptions,
} from '@floating-ui/react-dom'
import classnames from 'classnames'
import { type OverrideClassName } from '~components/types/OverrideClassName'
import styles from './CalendarPopover.module.scss'
export type CalendarPopoverProps = {
children: React.ReactNode
referenceElement: HTMLElement | null
floatingOptions?: Partial
} & OverrideClassName>
/**
* Only for use with Calendar components.
* @todo: Replace with Popover when we have a reusable one.
*/
export const CalendarPopover = ({
children,
referenceElement,
floatingOptions,
classNameOverride,
...restProps
}: CalendarPopoverProps): JSX.Element => {
const [floatingElement, setFloatingElement] = useState(null)
const { floatingStyles, update } = useFloating({
placement: 'bottom-start',
elements: {
reference: referenceElement,
floating: floatingElement,
},
strategy: 'fixed',
middleware: [
size({
apply({ availableHeight, availableWidth, elements }) {
Object.assign(elements.floating.style, {
// 155 is enough of a minimum to cut off half of the second row of dates.
// This indicates to users that there is more content that is scrollable
maxHeight: `${Math.max(availableHeight - 25, 155)}px`,
maxWidth: `${availableWidth}px`,
})
},
}),
offset(15),
autoPlacement({
allowedPlacements: ['bottom-start', 'bottom', 'top-start', 'top'],
}),
],
whileElementsMounted: autoUpdate,
...floatingOptions,
})
useEffect(() => {
if (floatingElement && referenceElement) {
// @ts-expect-error this can be removed when we update to react 19
referenceElement.popoverTargetElement = floatingElement
floatingElement.showPopover?.()
update()
}
}, [referenceElement, floatingElement, update])
return (
{children}
)
}
CalendarPopover.displayName = 'CalendarPopover'