@shopify/polaris
Version:
Shopify’s product component library
114 lines (98 loc) • 4.34 kB
JavaScript
import { objectWithoutProperties as _objectWithoutProperties } from '../../_virtual/_rollupPluginBabelHelpers.js';
import React$1, { useState, useRef, useCallback, useEffect, Children } from 'react';
import { useUniqueId } from '../../utilities/unique-id/hooks.js';
import { portal } from '../shared.js';
import { findFirstFocusableNodeIncludingDisabled, focusNextFocusableNode } from '../../utilities/focus.js';
import { Portal as Portal$1 } from '../Portal/Portal.js';
import { Section as Section$1 } from './components/Section/Section.js';
import { Pane as Pane$1 } from './components/Pane/Pane.js';
import { PopoverOverlay as PopoverOverlay$1, PopoverCloseSource } from './components/PopoverOverlay/PopoverOverlay.js';
export { PopoverCloseSource } from './components/PopoverOverlay/PopoverOverlay.js';
import { setActivatorAttributes as setActivatorAttributes$1 } from './set-activator-attributes.js';
// TypeScript can't generate types that correctly infer the typing of
// subcomponents so explicitly state the subcomponents in the type definition.
// Letting this be implicit works in this project but fails in projects that use
// generated *.d.ts files.
var Popover = function Popover(_ref) {
var {
activatorWrapper = 'div',
children,
onClose,
activator,
active,
fixed,
ariaHaspopup,
preferInputActivator = true,
colorScheme
} = _ref,
rest = _objectWithoutProperties(_ref, ["activatorWrapper", "children", "onClose", "activator", "active", "fixed", "ariaHaspopup", "preferInputActivator", "colorScheme"]);
var [activatorNode, setActivatorNode] = useState();
var activatorContainer = useRef(null);
var WrapperComponent = activatorWrapper;
var id = useUniqueId('popover');
var setAccessibilityAttributes = useCallback(() => {
if (activatorContainer.current == null) {
return;
}
var firstFocusable = findFirstFocusableNodeIncludingDisabled(activatorContainer.current);
var focusableActivator = firstFocusable || activatorContainer.current;
var activatorDisabled = 'disabled' in focusableActivator && Boolean(focusableActivator.disabled);
setActivatorAttributes$1(focusableActivator, {
id,
active,
ariaHaspopup,
activatorDisabled
});
}, [id, active, ariaHaspopup]);
var handleClose = source => {
onClose(source);
if (activatorContainer.current == null) {
return;
}
if ((source === PopoverCloseSource.FocusOut || source === PopoverCloseSource.EscapeKeypress) && activatorNode) {
var focusableActivator = findFirstFocusableNodeIncludingDisabled(activatorNode) || findFirstFocusableNodeIncludingDisabled(activatorContainer.current) || activatorContainer.current;
if (!focusNextFocusableNode(focusableActivator, isInPortal)) {
focusableActivator.focus();
}
}
};
useEffect(() => {
if (!activatorNode && activatorContainer.current) {
setActivatorNode(activatorContainer.current.firstElementChild);
} else if (activatorNode && activatorContainer.current && !activatorContainer.current.contains(activatorNode)) {
setActivatorNode(activatorContainer.current.firstElementChild);
}
setAccessibilityAttributes();
}, [activatorNode, setAccessibilityAttributes]);
useEffect(() => {
if (activatorNode && activatorContainer.current) {
setActivatorNode(activatorContainer.current.firstElementChild);
}
setAccessibilityAttributes();
}, [activatorNode, setAccessibilityAttributes]);
var portal = activatorNode ? /*#__PURE__*/React$1.createElement(Portal$1, {
idPrefix: "popover"
}, /*#__PURE__*/React$1.createElement(PopoverOverlay$1, Object.assign({
id: id,
activator: activatorNode,
preferInputActivator: preferInputActivator,
onClose: handleClose,
active: active,
fixed: fixed,
colorScheme: colorScheme
}, rest), children)) : null;
return /*#__PURE__*/React$1.createElement(WrapperComponent, {
ref: activatorContainer
}, Children.only(activator), portal);
};
function isInPortal(element) {
var parentElement = element.parentElement;
while (parentElement) {
if (parentElement.matches(portal.selector)) return false;
parentElement = parentElement.parentElement;
}
return true;
}
Popover.Pane = Pane$1;
Popover.Section = Section$1;
export { Popover };