@itwin/itwinui-react
Version:
A react component library for iTwinUI
354 lines (353 loc) • 10.3 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', {
value: true,
});
function _export(target, all) {
for (var name in all)
Object.defineProperty(target, name, {
enumerable: true,
get: all[name],
});
}
_export(exports, {
Popover: function () {
return Popover;
},
PopoverInitialFocusContext: function () {
return PopoverInitialFocusContext;
},
PopoverOpenContext: function () {
return PopoverOpenContext;
},
usePopover: function () {
return usePopover;
},
});
const _interop_require_default = require('@swc/helpers/_/_interop_require_default');
const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
const _react = /*#__PURE__*/ _interop_require_wildcard._(require('react'));
const _classnames = /*#__PURE__*/ _interop_require_default._(
require('classnames'),
);
const _react1 = require('@floating-ui/react');
const _index = require('../../utils/index.js');
const _Portal = require('../../utils/components/Portal.js');
const _ThemeProvider = require('../ThemeProvider/ThemeProvider.js');
const PopoverOpenContext = _react.createContext(void 0);
const PopoverInitialFocusContext = _react.createContext(void 0);
const usePopover = (options) => {
let {
placement = 'bottom-start',
visible,
onVisibleChange,
closeOnOutsideClick,
autoUpdateOptions,
matchWidth,
interactions: interactionsProp,
role,
...rest
} = options;
let mergedInteractions = _react.useMemo(
() => ({
...interactionsProp,
...{
click: interactionsProp?.click ?? true,
dismiss: interactionsProp?.dismiss ?? true,
hover: interactionsProp?.hover ?? false,
focus: interactionsProp?.focus ?? false,
},
}),
[interactionsProp],
);
let tree = (0, _react1.useFloatingTree)();
let middleware = _react.useMemo(
() => ({
...options.middleware,
flip: options.middleware?.flip ?? true,
shift: options.middleware?.shift ?? true,
size: options.middleware?.size ?? true,
hide: options.middleware?.hide || !_index.isUnitTest,
}),
[options.middleware],
);
let maxHeight =
'boolean' == typeof middleware.size ? '400px' : middleware.size?.maxHeight;
let [open, onOpenChange] = (0, _index.useControlledState)(
false,
visible,
onVisibleChange,
);
let floating = (0, _react1.useFloating)({
placement,
open,
onOpenChange,
strategy: 'fixed',
whileElementsMounted: _react.useMemo(
() =>
open
? (...args) => (0, _react1.autoUpdate)(...args, autoUpdateOptions)
: void 0,
[autoUpdateOptions, open],
),
...rest,
middleware: _react.useMemo(
() =>
[
void 0 !== middleware.offset &&
(0, _react1.offset)(middleware.offset),
middleware.flip &&
(0, _react1.flip)({
padding: 5,
}),
middleware.shift &&
(0, _react1.shift)({
padding: 4,
}),
(matchWidth || middleware.size) &&
(0, _react1.size)({
padding: 4,
apply: ({ rects, availableHeight }) => {
if (middleware.size)
setAvailableHeight(Math.round(availableHeight));
if (matchWidth) setReferenceWidth(rects.reference.width);
},
}),
middleware.autoPlacement &&
(0, _react1.autoPlacement)({
padding: 4,
}),
middleware.inline && (0, _react1.inline)(),
middleware.hide &&
(0, _react1.hide)({
padding: 4,
}),
].filter(Boolean),
[matchWidth, middleware],
),
});
let interactions = (0, _react1.useInteractions)([
(0, _react1.useClick)(floating.context, {
enabled: !!mergedInteractions.click,
...mergedInteractions.click,
}),
(0, _react1.useDismiss)(floating.context, {
enabled: !!mergedInteractions.dismiss,
outsidePress: closeOnOutsideClick,
bubbles: null != tree,
...mergedInteractions.dismiss,
}),
(0, _react1.useHover)(floating.context, {
enabled: !!mergedInteractions.hover,
delay: 100,
handleClose: (0, _react1.safePolygon)({
buffer: 1,
blockPointerEvents: true,
}),
move: false,
...mergedInteractions.hover,
}),
(0, _react1.useFocus)(floating.context, {
enabled: !!mergedInteractions.focus,
...mergedInteractions.focus,
}),
(0, _react1.useRole)(floating.context, {
role: 'dialog',
enabled: !!role,
}),
]);
let [referenceWidth, setReferenceWidth] = _react.useState();
let [availableHeight, setAvailableHeight] = _react.useState();
let getFloatingProps = _react.useCallback(
(userProps) =>
interactions.getFloatingProps({
...userProps,
style: {
...floating.floatingStyles,
...(middleware.size &&
availableHeight && {
maxBlockSize: `min(${availableHeight}px, ${maxHeight})`,
}),
zIndex: 999,
...(matchWidth && referenceWidth
? {
minInlineSize: `${referenceWidth}px`,
maxInlineSize: `min(${2 * referenceWidth}px, 90vw)`,
}
: {}),
...(middleware.hide &&
floating.middlewareData.hide?.referenceHidden && {
visibility: 'hidden',
}),
...userProps?.style,
},
}),
[
interactions,
floating.floatingStyles,
floating.middlewareData.hide?.referenceHidden,
middleware.size,
middleware.hide,
availableHeight,
maxHeight,
matchWidth,
referenceWidth,
],
);
let getReferenceProps = _react.useCallback(
(userProps) =>
interactions.getReferenceProps({
...userProps,
onClick: (0, _index.mergeEventHandlers)(userProps?.onClick, () => {
if (!!mergedInteractions.click && visible) onOpenChange(false);
}),
}),
[interactions, mergedInteractions.click, visible, onOpenChange],
);
return _react.useMemo(
() => ({
open,
onOpenChange,
getReferenceProps,
getFloatingProps,
...floating,
}),
[open, onOpenChange, getFloatingProps, floating, getReferenceProps],
);
};
const Popover = _react.forwardRef((props, forwardedRef) => {
let {
portal = true,
visible,
placement = 'bottom-start',
onVisibleChange,
closeOnOutsideClick = true,
middleware,
positionReference,
className,
children,
content,
applyBackground = false,
...rest
} = props;
let popover = usePopover({
visible,
placement,
onVisibleChange,
closeOnOutsideClick,
role: 'dialog',
middleware,
transform: false,
});
let [popoverElement, setPopoverElement] = _react.useState(null);
let popoverRef = (0, _index.useMergedRefs)(
popover.refs.setFloating,
forwardedRef,
setPopoverElement,
);
let triggerId = `${(0, _index.useId)()}-trigger`;
let hasAriaLabel = !!props['aria-labelledby'] || !!props['aria-label'];
(0, _index.useLayoutEffect)(() => {
if (!positionReference) return;
popover.refs.setPositionReference(positionReference);
return () => void popover.refs.setPositionReference(null);
}, [popover.refs, positionReference]);
let [initialFocus, setInitialFocus] = _react.useState();
let initialFocusContextValue = _react.useMemo(
() => ({
setInitialFocus,
}),
[],
);
return _react.createElement(
_react.Fragment,
null,
_react.createElement(
PopoverOpenContext.Provider,
{
value: popover.open,
},
(0, _index.cloneElementWithRef)(children, (children) => ({
id: children.props.id || triggerId,
...popover.getReferenceProps(children.props),
ref: popover.refs.setReference,
})),
),
popover.open
? _react.createElement(
PopoverInitialFocusContext.Provider,
{
value: initialFocusContextValue,
},
_react.createElement(
PopoverPortal,
{
portal: portal,
},
_react.createElement(
_ThemeProvider.ThemeProvider,
null,
_react.createElement(
_Portal.PortalContainerContext.Provider,
{
value: popoverElement,
},
_react.createElement(DisplayContents, null),
_react.createElement(
_react1.FloatingFocusManager,
{
context: popover.context,
modal: false,
initialFocus: initialFocus,
},
_react.createElement(
_index.Box,
{
className: (0, _classnames.default)(
'iui-popover',
{
'iui-popover-surface': applyBackground,
},
className,
),
'aria-labelledby': hasAriaLabel
? void 0
: popover.refs.domReference.current?.id,
...popover.getFloatingProps(rest),
ref: popoverRef,
},
content,
),
),
),
),
),
)
: null,
);
});
if ('development' === process.env.NODE_ENV) Popover.displayName = 'Popover';
const PopoverPortal = ({ children, portal = true }) => {
let portalTo = (0, _Portal.usePortalTo)(portal);
return _react.createElement(
_react1.FloatingPortal,
{
key: portalTo?.id,
root: portalTo ?? void 0,
},
_react.createElement(DisplayContents, null),
children,
);
};
const DisplayContents = _react.memo(() =>
_react.createElement(
_index.ShadowRoot,
{
css: `
:host {
display: contents;
}
`,
},
_react.createElement('slot', null),
),
);