@wix/design-system
Version:
@wix/design-system
144 lines • 5.79 kB
JavaScript
import { useEffect, useMemo } from 'react';
import { useFloating, autoUpdate, flip, shift, useClick, useDismiss, useRole, useInteractions, size, offset, autoPlacement, } from '@floating-ui/react';
import { APPEND_TO } from '../PopoverNext.constants';
import { ZIndex } from '../../common/ZIndex';
import { usePositioning } from './usePositioning';
import deprecationLog from '../../utils/deprecationLog';
import { useTransition } from './useTransition';
const formatWidth = (value) => typeof value === 'number' ? `${value}px` : value;
export function usePopover({ dataHook, open = false, onOpenChange, focusManagerEnabled = true, appendTo = APPEND_TO.parent, dynamicWidth = false, zIndex = ZIndex.popover, width, minWidth, maxWidth, excludeClass, moveBy, flip: shouldFlip = true, placement = 'bottom', fixed = false, rootRef, showDelay = 0, hideDelay = 0, timeout: duration = 0, skin, transitionSettings, onClickOutside, overlay = false, }) {
useEffect(() => {
if (showDelay) {
deprecationLog('<PopoverNext /> - prop `showDelay` is deprecated. Use transitionSettings instead.');
}
if (hideDelay) {
deprecationLog('<PopoverNext /> - prop `hideDelay` is deprecated. Use transitionSettings instead.');
}
if (duration) {
deprecationLog('<PopoverNext /> - prop `timeout` is deprecated. Use transitionSettings instead.');
}
}, [showDelay, hideDelay, duration]);
const positioning = usePositioning({
flip: shouldFlip,
fixed,
placement,
appendTo,
rootRef,
});
const data = useFloating({
open,
onOpenChange: (newOpen, _, reason) => onOpenChange(newOpen, reason),
whileElementsMounted: (referenceEl, floatingEl, update) => autoUpdate(referenceEl, floatingEl, update, {
animationFrame: true,
}),
placement: positioning.placement,
middleware: [
size({
apply({ rects, elements }) {
const styles = {
overflow: 'hidden',
wordBreak: 'normal',
};
if (width) {
styles.width = formatWidth(width);
if (minWidth) {
styles.minWidth = formatWidth(minWidth);
}
if (maxWidth) {
styles.maxWidth = formatWidth(maxWidth);
}
}
else if (dynamicWidth) {
styles.minWidth = `${rects.reference.width}px`;
if (maxWidth) {
styles.maxWidth = formatWidth(maxWidth);
}
}
else {
if (minWidth) {
styles.minWidth = formatWidth(minWidth);
}
if (maxWidth) {
styles.maxWidth = formatWidth(maxWidth);
}
}
if (appendTo === 'window') {
styles.minWidth = !!minWidth
? formatWidth(minWidth)
: 'fit-content';
styles.width = !!width
? formatWidth(width)
: formatWidth(rects.reference.width);
if (maxWidth) {
styles.maxWidth = formatWidth(maxWidth);
}
}
Object.assign(elements.floating.style, styles);
},
}),
!!positioning.flip ? flip(positioning.flip) : undefined,
!!positioning.autoPlacement
? autoPlacement(positioning.autoPlacement)
: undefined,
shift(positioning.shift),
offset({ mainAxis: moveBy?.y, crossAxis: moveBy?.x }),
].filter(Boolean),
});
const context = data.context;
const click = useClick(context);
const dismiss = useDismiss(context, {
outsidePress: event => {
const classes = event.target.classList;
if (excludeClass && classes.contains(excludeClass)) {
return false;
}
onClickOutside?.(event);
return true;
},
escapeKey: true,
});
const role = useRole(context);
const interactions = useInteractions([click, dismiss, role]);
const convertToTransitionSettings = (duration) => {
if (!duration || typeof duration === 'number') {
return duration;
}
return { open: duration.enter, close: duration.exit };
};
const { isMounted, styles: transitionStyles } = useTransition({
...transitionSettings,
duration: transitionSettings?.duration ?? convertToTransitionSettings(duration),
closeDelay: transitionSettings?.closeDelay ?? hideDelay,
openDelay: transitionSettings?.openDelay ?? showDelay,
context,
});
return useMemo(() => ({
dataHook,
focusManagerEnabled,
interactions,
context,
appendTo,
zIndex,
open: isMounted,
popoverStyles: {
...context.floatingStyles,
},
transitionStyles,
portalRoot: positioning.portalRoot,
skin,
overlay,
}), [
dataHook,
focusManagerEnabled,
interactions,
context,
isMounted,
zIndex,
appendTo,
positioning,
transitionStyles,
skin,
overlay,
]);
}
//# sourceMappingURL=usePopover.js.map