@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
120 lines (117 loc) • 4.81 kB
JavaScript
'use client';
import { placementMap } from "../utils/placement.mjs";
import { useDestroyOnInvalidActiveTriggerElement, useHidePopupWhenPositionerAtOrigin } from "../utils/destroyOnInvalidActiveTriggerElement.mjs";
import { parseTrigger } from "../utils/parseTrigger.mjs";
import { PopoverArrowIcon } from "./ArrowIcon.mjs";
import { usePopoverPortalContainer } from "./PopoverPortal.mjs";
import { PopoverArrow, PopoverPopup, PopoverPortal, PopoverPositioner, PopoverViewport } from "./atoms.mjs";
import { PopoverProvider } from "./context.mjs";
import { PopoverGroupHandleContext, PopoverGroupPropsContext } from "./groupContext.mjs";
import { useCallback, useMemo, useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
import { Popover } from "@base-ui/react/popover";
//#region src/Popover/PopoverGroup.tsx
const PopoverGroup = ({ children, contentLayoutAnimation = false, disableDestroyOnInvalidTrigger = false, disableZeroOriginGuard = false, ...sharedProps }) => {
const [{ handle, key }, setHandleState] = useState(() => ({
handle: Popover.createHandle(),
key: 0
}));
const activeItemRef = useRef(null);
const destroy = useCallback(() => {
activeItemRef.current = null;
setHandleState(({ key: key$1 }) => ({
handle: Popover.createHandle(),
key: key$1 + 1
}));
}, []);
const close = useCallback(() => {
handle.close();
}, [handle]);
const contextValue = useMemo(() => ({ close }), [close]);
const handleOpenChange = useCallback((open) => {
activeItemRef.current?.onOpenChange?.(open);
}, []);
useDestroyOnInvalidActiveTriggerElement(handle.store, destroy, { enabled: !disableDestroyOnInvalidTrigger });
useHidePopupWhenPositionerAtOrigin(handle.store, { enabled: !disableZeroOriginGuard });
const portalContainer = usePopoverPortalContainer();
return /* @__PURE__ */ jsx(PopoverGroupHandleContext.Provider, {
value: handle,
children: /* @__PURE__ */ jsxs(PopoverGroupPropsContext.Provider, {
value: sharedProps,
children: [children, /* @__PURE__ */ jsx(Popover.Root, {
handle,
onOpenChange: handleOpenChange,
children: ({ payload }) => {
const item = payload ?? null;
activeItemRef.current = item;
if (!item?.content) return null;
const arrow = item.inset ? false : item.arrow ?? false;
const placement = item.placement ?? "top";
const { openOnHover } = parseTrigger(item.trigger ?? "hover");
const placementConfig = placementMap[placement] ?? placementMap.top;
const baseSideOffset = arrow ? 10 : 6;
const resolvedSideOffset = item.inset ? ({ side, positioner }) => {
if (side === "left" || side === "right" || side === "inline-start" || side === "inline-end") return -positioner.width;
return -positioner.height;
} : baseSideOffset;
const resolvedClassNames = {
arrow: item.classNames?.arrow,
popup: item.className,
positioner: item.classNames?.root,
viewport: item.classNames?.content
};
const resolvedStyles = {
arrow: item.styles?.arrow,
positioner: {
...item.styles?.root,
zIndex: item.zIndex ?? 1100
},
viewport: item.styles?.content
};
const contentNode = /* @__PURE__ */ jsx(PopoverProvider, {
value: contextValue,
children: item.content
});
const popup = /* @__PURE__ */ jsx(PopoverPositioner, {
align: placementConfig.align,
className: resolvedClassNames.positioner,
"data-layout-animation": contentLayoutAnimation || void 0,
hoverTrigger: openOnHover,
placement,
side: placementConfig.side,
sideOffset: resolvedSideOffset,
style: resolvedStyles.positioner,
...item.positionerProps,
children: /* @__PURE__ */ jsxs(PopoverPopup, {
className: resolvedClassNames.popup,
"data-layout-animation": contentLayoutAnimation || void 0,
...item.popupProps,
children: [arrow && /* @__PURE__ */ jsx(PopoverArrow, {
className: resolvedClassNames.arrow,
style: resolvedStyles.arrow,
children: PopoverArrowIcon
}), contentLayoutAnimation ? /* @__PURE__ */ jsx(PopoverViewport, {
className: resolvedClassNames.viewport,
style: resolvedStyles.viewport,
children: contentNode
}) : /* @__PURE__ */ jsx("div", {
className: resolvedClassNames.viewport,
style: resolvedStyles.viewport,
children: contentNode
})]
})
});
return portalContainer ? /* @__PURE__ */ jsx(PopoverPortal, {
container: portalContainer,
children: popup
}) : null;
}
}, key)]
})
});
};
PopoverGroup.displayName = "PopoverGroup";
var PopoverGroup_default = PopoverGroup;
//#endregion
export { PopoverGroup_default as default };
//# sourceMappingURL=PopoverGroup.mjs.map