@blueprintjs/core
Version:
Core styles & components
570 lines • 32.2 kB
JavaScript
"use strict";
/*
* Copyright 2021 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Popover = exports.PopoverInteractionKind = void 0;
const tslib_1 = require("tslib");
const classnames_1 = tslib_1.__importDefault(require("classnames"));
const React = tslib_1.__importStar(require("react"));
const react_popper_1 = require("react-popper");
const common_1 = require("../../common");
const Errors = tslib_1.__importStar(require("../../common/errors"));
const overlay2_1 = require("../overlay2/overlay2");
const resizeSensor_1 = require("../resize-sensor/resizeSensor");
// eslint-disable-next-line import/no-cycle
const tooltip_1 = require("../tooltip/tooltip");
const customModifiers_1 = require("./customModifiers");
const popoverArrow_1 = require("./popoverArrow");
const popoverPlacementUtils_1 = require("./popoverPlacementUtils");
const popperUtils_1 = require("./popperUtils");
exports.PopoverInteractionKind = {
CLICK: "click",
CLICK_TARGET_ONLY: "click-target",
HOVER: "hover",
HOVER_TARGET_ONLY: "hover-target",
};
/**
* Popover component, used to display a floating UI next to and tethered to a target element.
*
* @template T target element props interface. Consumers wishing to stay in sync with Blueprint's default target HTML
* props interface should use the `DefaultPopoverTargetHTMLProps` type (although this is already the default type for
* this type param).
* @see https://blueprintjs.com/docs/#core/components/popover
*/
class Popover extends common_1.AbstractPureComponent {
constructor() {
super(...arguments);
this.state = {
hasDarkParent: false,
isClosingViaEscapeKeypress: false,
isOpen: this.getIsOpen(this.props),
};
/**
* DOM element that contains the popover.
* When `usePortal={true}`, this element will be portaled outside the usual DOM flow,
* so this reference can be very useful for testing.
*
* @public for testing
*/
this.popoverElement = null;
/** Popover ref handler */
this.popoverRef = (0, common_1.refHandler)(this, "popoverElement", this.props.popoverRef);
/**
* Target DOM element ref.
*
* N.B. this must be a ref object since we pass it to `<ResizeSensor>`, which needs to know about the target
* DOM element in order to observe its dimensions.
*
* @public for testing
*/
this.targetRef = React.createRef();
/**
* Overlay2 transition container element ref.
*/
this.transitionContainerElement = React.createRef();
// a flag that lets us detect mouse movement between the target and popover,
// now that mouseleave is triggered when you cross the gap between the two.
this.isMouseInTargetOrPopover = false;
// a flag that indicates whether the target previously lost focus to another
// element on the same page.
this.lostFocusOnSamePage = true;
this.isControlled = () => this.props.isOpen !== undefined;
// arrow is disabled if minimal, or if the arrow modifier was explicitly disabled
this.isArrowEnabled = () => { var _a, _b; return !this.props.minimal && ((_b = (_a = this.props.modifiers) === null || _a === void 0 ? void 0 : _a.arrow) === null || _b === void 0 ? void 0 : _b.enabled) !== false; };
this.isHoverInteractionKind = () => {
return (this.props.interactionKind === exports.PopoverInteractionKind.HOVER ||
this.props.interactionKind === exports.PopoverInteractionKind.HOVER_TARGET_ONLY);
};
/**
* Instance method to instruct the `Popover` to recompute its position.
*
* This method should only be used if you are updating the target in a way
* that does not cause it to re-render, such as changing its _position_
* without changing its _size_ (since `Popover` already repositions when it
* detects a resize).
*/
this.reposition = () => { var _a; return (_a = this.popperScheduleUpdate) === null || _a === void 0 ? void 0 : _a.call(this); };
this.renderTarget = ({ ref: popperChildRef }) => {
var _a, _b;
const { children, className, disabled, fill, openOnTargetFocus, renderTarget } = this.props;
const { isOpen } = this.state;
const isControlled = this.isControlled();
const isHoverInteractionKind = this.isHoverInteractionKind();
let { targetTagName } = this.props;
if (fill) {
targetTagName = "div";
}
// N.B. react-popper has a wide type for this ref, but we can narrow it based on the source,
// see https://github.com/floating-ui/react-popper/blob/beac280d61082852c4efc302be902911ce2d424c/src/Reference.js#L17
const ref = (0, common_1.mergeRefs)(popperChildRef, this.targetRef);
const targetEventHandlers = isHoverInteractionKind
? {
// HOVER handlers
onBlur: this.handleTargetBlur,
onContextMenu: this.handleTargetContextMenu,
onFocus: this.handleTargetFocus,
onMouseEnter: this.handleMouseEnter,
onMouseLeave: this.handleMouseLeave,
}
: {
// CLICK needs only one handler
onClick: this.handleTargetClick,
// For keyboard accessibility, trigger the same behavior as a click event upon pressing ENTER/SPACE
onKeyDown: this.handleKeyDown,
};
// Ensure target is focusable if relevant prop enabled
const targetTabIndex = !this.getIsContentEmpty() && !disabled && openOnTargetFocus && isHoverInteractionKind ? 0 : undefined;
const ownTargetProps = {
// N.B. this.props.className is passed along to renderTarget even though the user would have access to it.
// If, instead, renderTarget is undefined and the target is provided as a child, this.props.className is
// applied to the generated target wrapper element.
className: (0, classnames_1.default)(className, common_1.Classes.POPOVER_TARGET, {
[common_1.Classes.POPOVER_OPEN]: isOpen,
// this class is mainly useful for button targets
[common_1.Classes.ACTIVE]: isOpen && !isControlled && !isHoverInteractionKind,
}),
ref,
...targetEventHandlers,
};
const childTargetProps = {
"aria-expanded": isHoverInteractionKind ? undefined : isOpen,
"aria-haspopup": this.props.interactionKind === exports.PopoverInteractionKind.HOVER_TARGET_ONLY
? undefined
: (_a = this.props.popupKind) !== null && _a !== void 0 ? _a : "menu",
};
const targetModifierClasses = {
// this class is mainly useful for Blueprint <Button> targets; we should only apply it for
// uncontrolled popovers when they are opened by a user interaction
[common_1.Classes.ACTIVE]: isOpen && !isControlled && !isHoverInteractionKind,
// similarly, this class is mainly useful for targets like <Button>, <InputGroup>, etc.
[common_1.Classes.FILL]: fill,
};
let target;
if (renderTarget !== undefined) {
target = renderTarget({
...ownTargetProps,
...childTargetProps,
className: (0, classnames_1.default)(ownTargetProps.className, targetModifierClasses),
// if the consumer renders a tooltip target, it's their responsibility to disable that tooltip
// when *this* popover is open
isOpen,
tabIndex: targetTabIndex,
});
}
else {
const childTarget = common_1.Utils.ensureElement(React.Children.toArray(children)[0]);
if (childTarget === undefined) {
return null;
}
const clonedTarget = React.cloneElement(childTarget, {
...childTargetProps,
className: (0, classnames_1.default)(childTarget.props.className, targetModifierClasses),
// force disable single Tooltip child when popover is open
disabled: isOpen && common_1.Utils.isElementOfType(childTarget, tooltip_1.Tooltip) ? true : childTarget.props.disabled,
tabIndex: (_b = childTarget.props.tabIndex) !== null && _b !== void 0 ? _b : targetTabIndex,
});
const wrappedTarget = React.createElement(targetTagName, {
...ownTargetProps,
...this.props.targetProps,
}, clonedTarget);
target = wrappedTarget;
}
// No need to use the merged `ref` here, that only needs to be forwarded to the child node so that React can
// notify both popper.js and our components about the mounted DOM element.
return (React.createElement(resizeSensor_1.ResizeSensor, { targetRef: this.targetRef, onResize: this.reposition }, target));
};
this.renderPopover = (popperProps) => {
const { autoFocus, enforceFocus, backdropProps, canEscapeKeyClose, hasBackdrop, interactionKind, usePortal } = this.props;
const { isClosingViaEscapeKeypress, isOpen } = this.state;
// compute an appropriate transform origin so the scale animation points towards target
const transformOrigin = (0, popperUtils_1.getTransformOrigin)(popperProps.placement, this.isArrowEnabled() ? popperProps.arrowProps.style : undefined);
// need to update our reference to this function on every render as it will change.
this.popperScheduleUpdate = popperProps.update;
const popoverHandlers = {
// always check popover clicks for dismiss class
onClick: this.handlePopoverClick,
// treat ENTER/SPACE keys the same as a click for accessibility
onKeyDown: event => common_1.Utils.isKeyboardClick(event) && this.handlePopoverClick(event),
};
if (interactionKind === exports.PopoverInteractionKind.HOVER ||
(!usePortal && interactionKind === exports.PopoverInteractionKind.HOVER_TARGET_ONLY)) {
popoverHandlers.onMouseEnter = this.handleMouseEnter;
popoverHandlers.onMouseLeave = this.handleMouseLeave;
}
const basePlacement = (0, popperUtils_1.getBasePlacement)(popperProps.placement);
const popoverClasses = (0, classnames_1.default)(common_1.Classes.POPOVER, {
[common_1.Classes.DARK]: this.props.inheritDarkTheme && this.state.hasDarkParent,
[common_1.Classes.MINIMAL]: this.props.minimal,
[common_1.Classes.POPOVER_CAPTURING_DISMISS]: this.props.captureDismiss,
[common_1.Classes.POPOVER_MATCH_TARGET_WIDTH]: this.props.matchTargetWidth,
[common_1.Classes.POPOVER_REFERENCE_HIDDEN]: popperProps.isReferenceHidden === true,
[common_1.Classes.POPOVER_POPPER_ESCAPED]: popperProps.hasPopperEscaped === true,
}, `${common_1.Classes.POPOVER_CONTENT_PLACEMENT}-${basePlacement}`, this.props.popoverClassName);
const defaultAutoFocus = this.isHoverInteractionKind() ? false : undefined;
// if hover interaction, it doesn't make sense to take over focus control
const shouldReturnFocusOnClose = this.isHoverInteractionKind()
? false
: isClosingViaEscapeKeypress
? true
: this.props.shouldReturnFocusOnClose;
return (React.createElement(overlay2_1.Overlay2, { autoFocus: autoFocus !== null && autoFocus !== void 0 ? autoFocus : defaultAutoFocus, backdropClassName: common_1.Classes.POPOVER_BACKDROP, backdropProps: backdropProps, canEscapeKeyClose: canEscapeKeyClose, canOutsideClickClose: interactionKind === exports.PopoverInteractionKind.CLICK, childRef: this.transitionContainerElement, enforceFocus: enforceFocus, hasBackdrop: hasBackdrop, isOpen: isOpen, lazy: this.props.lazy, onClose: this.handleOverlayClose, onClosed: this.props.onClosed, onClosing: this.props.onClosing, onOpened: this.props.onOpened, onOpening: this.props.onOpening, transitionDuration: this.props.transitionDuration, transitionName: common_1.Classes.POPOVER, usePortal: usePortal, portalClassName: this.props.portalClassName, portalContainer: this.props.portalContainer,
// eslint-disable-next-line @typescript-eslint/no-deprecated
portalStopPropagationEvents: this.props.portalStopPropagationEvents, shouldReturnFocusOnClose: shouldReturnFocusOnClose },
React.createElement("div", { className: common_1.Classes.POPOVER_TRANSITION_CONTAINER,
// We need to attach a ref that notifies both react-popper and our Popover component about the DOM
// element inside the Overlay2. We cannot re-use `PopperChildrenProps.ref` because Overlay2 only
// accepts a ref object (not a callback) due to a CSSTransition API limitation.
// N.B. react-popper has a wide type for this ref, but we can narrow it based on the source,
// see https://github.com/floating-ui/react-popper/blob/beac280d61082852c4efc302be902911ce2d424c/src/Popper.js#L94
ref: (0, common_1.mergeRefs)(popperProps.ref, this.transitionContainerElement), style: popperProps.style },
React.createElement(resizeSensor_1.ResizeSensor, { onResize: this.reposition },
React.createElement("div", { className: popoverClasses, style: { transformOrigin }, ref: this.popoverRef, ...popoverHandlers },
this.isArrowEnabled() && (React.createElement(popoverArrow_1.PopoverArrow, { arrowProps: popperProps.arrowProps, placement: popperProps.placement })),
React.createElement("div", { className: common_1.Classes.POPOVER_CONTENT }, this.props.content))))));
};
this.handleTargetFocus = (e) => {
if (this.props.openOnTargetFocus && this.isHoverInteractionKind()) {
if (e.relatedTarget == null && !this.lostFocusOnSamePage) {
// ignore this focus event -- the target was already focused but the page itself
// lost focus (e.g. due to switching tabs).
return;
}
this.handleMouseEnter(e);
}
};
this.handleTargetBlur = (e) => {
if (this.props.openOnTargetFocus && this.isHoverInteractionKind()) {
if (e.relatedTarget != null) {
// if the next element to receive focus is within the popover, we'll want to leave the
// popover open.
if (e.relatedTarget !== this.popoverElement &&
!this.isElementInPopover(e.relatedTarget)) {
this.handleMouseLeave(e);
}
}
else {
this.handleMouseLeave(e);
}
}
this.lostFocusOnSamePage = e.relatedTarget != null;
};
this.handleTargetContextMenu = (e) => {
// we assume that when someone prevents the default interaction on this event (a browser native context menu),
// they are showing a custom context menu (as ContextMenu2 does); in this case, we should close this popover/tooltip
if (e.defaultPrevented) {
this.setOpenState(false, e);
}
};
this.handleMouseEnter = (e) => {
this.isMouseInTargetOrPopover = true;
// if we're entering the popover, and the mode is set to be HOVER_TARGET_ONLY, we want to manually
// trigger the mouse leave event, as hovering over the popover shouldn't count.
if (!this.props.usePortal &&
this.isElementInPopover(e.target) &&
this.props.interactionKind === exports.PopoverInteractionKind.HOVER_TARGET_ONLY &&
!this.props.openOnTargetFocus) {
this.handleMouseLeave(e);
}
else if (!this.props.disabled) {
// only begin opening popover when it is enabled
this.setOpenState(true, e, this.props.hoverOpenDelay);
}
};
this.handleMouseLeave = (e) => {
this.isMouseInTargetOrPopover = false;
// Wait until the event queue is flushed, because we want to leave the
// popover open if the mouse entered the popover immediately after
// leaving the target (or vice versa). Make sure to persist the event since
// we need to access `nativeEvent` in `this.setOpenState()`.
e.persist();
this.setTimeout(() => {
if (this.isMouseInTargetOrPopover) {
return;
}
// user-configurable closing delay is helpful when moving mouse from target to popover
this.setOpenState(false, e, this.props.hoverCloseDelay);
});
};
this.handlePopoverClick = (e) => {
var _a, _b, _c;
const eventTarget = e.target;
const eventPopover = eventTarget.closest(`.${common_1.Classes.POPOVER}`);
const eventPopoverV1 = eventTarget.closest(`.${common_1.Classes.POPOVER}`);
const isEventFromSelf = (eventPopover !== null && eventPopover !== void 0 ? eventPopover : eventPopoverV1) === this.getPopoverElement();
const isEventPopoverCapturing = (_b = (_a = eventPopover === null || eventPopover === void 0 ? void 0 : eventPopover.classList.contains(common_1.Classes.POPOVER_CAPTURING_DISMISS)) !== null && _a !== void 0 ? _a : eventPopoverV1 === null || eventPopoverV1 === void 0 ? void 0 : eventPopoverV1.classList.contains(common_1.Classes.POPOVER_CAPTURING_DISMISS)) !== null && _b !== void 0 ? _b : false;
// an OVERRIDE inside a DISMISS does not dismiss, and a DISMISS inside an OVERRIDE will dismiss.
const dismissElement = eventTarget.closest(`.${common_1.Classes.POPOVER_DISMISS}, .${common_1.Classes.POPOVER_DISMISS_OVERRIDE}`);
const shouldDismiss = (_c = dismissElement === null || dismissElement === void 0 ? void 0 : dismissElement.classList.contains(common_1.Classes.POPOVER_DISMISS)) !== null && _c !== void 0 ? _c : false;
const isDisabled = eventTarget.closest(`:disabled, .${common_1.Classes.DISABLED}`) != null;
if (shouldDismiss && !isDisabled && (!isEventPopoverCapturing || isEventFromSelf)) {
this.setOpenState(false, e);
}
};
this.handleOverlayClose = (e) => {
var _a;
if (this.targetRef.current == null || e === undefined) {
return;
}
const event = ((_a = e.nativeEvent) !== null && _a !== void 0 ? _a : e);
const eventTarget = (event.composed ? event.composedPath()[0] : event.target);
// if click was in target, target event listener will handle things, so don't close
if (!common_1.Utils.elementIsOrContains(this.targetRef.current, eventTarget) || e.nativeEvent instanceof KeyboardEvent) {
this.setOpenState(false, e);
}
};
this.handleKeyDown = (e) => {
const isKeyboardClick = common_1.Utils.isKeyboardClick(e);
// For keyboard accessibility, trigger the same behavior as a click event upon pressing ENTER/SPACE
if (isKeyboardClick) {
this.handleTargetClick(e);
}
};
this.handleTargetClick = (e) => {
// Target element(s) may fire simulated click event upon pressing ENTER/SPACE, which we should ignore
// see: https://github.com/palantir/blueprint/issues/5775
const shouldIgnoreClick = this.state.isOpen && this.isSimulatedButtonClick(e);
if (!shouldIgnoreClick) {
// ensure click did not originate from within inline popover before closing
if (!this.props.disabled && !this.isElementInPopover(e.target)) {
if (this.props.isOpen == null) {
this.setState(prevState => ({ isOpen: !prevState.isOpen }));
}
else {
this.setOpenState(!this.props.isOpen, e);
}
}
}
};
this.isSimulatedButtonClick = (e) => {
return !e.isTrusted && e.target.matches(`.${common_1.Classes.BUTTON}`);
};
}
// popper innerRef gives us a handle on the transition container, since that's what we render as the overlay child,
// so if we want to look at our actual popover element, we need to reach inside a bit
getPopoverElement() {
var _a;
return (_a = this.popoverElement) === null || _a === void 0 ? void 0 : _a.querySelector(`.${common_1.Classes.POPOVER}`);
}
getIsOpen(props) {
var _a;
// disabled popovers should never be allowed to open.
if (props.disabled) {
return false;
}
else {
return (_a = props.isOpen) !== null && _a !== void 0 ? _a : props.defaultIsOpen;
}
}
render() {
const { disabled, placement, position = "auto", positioningStrategy } = this.props;
const { isOpen } = this.state;
if (this.getIsContentEmpty()) {
// need to do this check in render(), because `isOpen` is derived from
// state, and state can't necessarily be accessed in validateProps.
if (!disabled && isOpen !== false && !common_1.Utils.isNodeEnv("production")) {
console.warn(Errors.POPOVER_WARN_EMPTY_CONTENT);
}
// just render the target without a content overlay if there is no content to display
return this.renderTarget({ ref: noop });
}
// Important: do not use <Reference innerRef> since it has a bug when used in React 18 strict mode
// see https://github.com/floating-ui/react-popper/pull/459
return (React.createElement(react_popper_1.Manager, null,
React.createElement(react_popper_1.Reference, null, this.renderTarget),
React.createElement(react_popper_1.Popper, { innerRef: this.popoverRef, placement: placement !== null && placement !== void 0 ? placement : (0, popoverPlacementUtils_1.positionToPlacement)(position), strategy: positioningStrategy, modifiers: this.getPopperModifiers() }, this.renderPopover)));
}
componentDidMount() {
this.updateDarkParent();
}
componentDidUpdate(props, state) {
super.componentDidUpdate(props, state);
this.updateDarkParent();
const nextIsOpen = this.getIsOpen(this.props);
if (this.props.isOpen != null && nextIsOpen !== this.state.isOpen) {
this.setOpenState(nextIsOpen);
// tricky: setOpenState calls setState only if this.props.isOpen is
// not controlled, so we need to invoke setState manually here.
this.setState({ isOpen: nextIsOpen });
}
else if (this.props.disabled && this.state.isOpen && this.props.isOpen == null) {
// special case: close an uncontrolled popover when disabled is set to true
this.setOpenState(false);
}
}
validateProps(props) {
if (props.isOpen == null && props.onInteraction != null) {
console.warn(Errors.POPOVER_WARN_UNCONTROLLED_ONINTERACTION);
}
if (props.hasBackdrop && !props.usePortal) {
console.warn(Errors.POPOVER_WARN_HAS_BACKDROP_INLINE);
}
if (props.hasBackdrop && props.interactionKind !== exports.PopoverInteractionKind.CLICK) {
console.warn(Errors.POPOVER_HAS_BACKDROP_INTERACTION);
}
if (props.placement !== undefined && props.position !== undefined) {
console.warn(Errors.POPOVER_WARN_PLACEMENT_AND_POSITION_MUTEX);
}
const childrenCount = React.Children.count(props.children);
const hasRenderTargetProp = props.renderTarget !== undefined;
const hasTargetPropsProp = props.targetProps !== undefined;
if (childrenCount === 0 && !hasRenderTargetProp) {
console.warn(Errors.POPOVER_REQUIRES_TARGET);
}
if (childrenCount > 1) {
console.warn(Errors.POPOVER_WARN_TOO_MANY_CHILDREN);
}
if (childrenCount > 0 && hasRenderTargetProp) {
console.warn(Errors.POPOVER_WARN_DOUBLE_TARGET);
}
if (hasRenderTargetProp && hasTargetPropsProp) {
console.warn(Errors.POPOVER_WARN_TARGET_PROPS_WITH_RENDER_TARGET);
}
}
getPopperModifiers() {
var _a, _b, _c, _d;
const { matchTargetWidth, modifiers, modifiersCustom } = this.props;
const popperModifiers = [
{
enabled: this.isArrowEnabled(),
name: "arrow",
...modifiers === null || modifiers === void 0 ? void 0 : modifiers.arrow,
},
{
name: "computeStyles",
...modifiers === null || modifiers === void 0 ? void 0 : modifiers.computeStyles,
options: {
adaptive: true,
// We disable the built-in gpuAcceleration so that
// Popper.js will return us easy to interpolate values
// (top, left instead of transform: translate3d)
// We'll then use these values to generate the needed
// css transform values blended with the react-spring values
gpuAcceleration: false,
...(_a = modifiers === null || modifiers === void 0 ? void 0 : modifiers.computeStyles) === null || _a === void 0 ? void 0 : _a.options,
},
},
{
enabled: this.isArrowEnabled(),
name: "offset",
...modifiers === null || modifiers === void 0 ? void 0 : modifiers.offset,
options: {
offset: [0, popoverArrow_1.POPOVER_ARROW_SVG_SIZE / 2],
...(_b = modifiers === null || modifiers === void 0 ? void 0 : modifiers.offset) === null || _b === void 0 ? void 0 : _b.options,
},
},
{
name: "flip",
...modifiers === null || modifiers === void 0 ? void 0 : modifiers.flip,
options: {
boundary: this.props.boundary,
rootBoundary: this.props.rootBoundary,
...(_c = modifiers === null || modifiers === void 0 ? void 0 : modifiers.flip) === null || _c === void 0 ? void 0 : _c.options,
},
},
{
name: "preventOverflow",
...modifiers === null || modifiers === void 0 ? void 0 : modifiers.preventOverflow,
options: {
boundary: this.props.boundary,
rootBoundary: this.props.rootBoundary,
...(_d = modifiers === null || modifiers === void 0 ? void 0 : modifiers.preventOverflow) === null || _d === void 0 ? void 0 : _d.options,
},
},
];
if (matchTargetWidth) {
popperModifiers.push(customModifiers_1.matchReferenceWidthModifier);
}
if (modifiersCustom !== undefined) {
popperModifiers.push(...modifiersCustom);
}
return popperModifiers;
}
// a wrapper around setState({ isOpen }) that will call props.onInteraction instead when in controlled mode.
// starts a timeout to delay changing the state if a non-zero duration is provided.
setOpenState(isOpen, e, timeout) {
var _a, _b, _c, _d, _e;
// cancel any existing timeout because we have new state
(_a = this.cancelOpenTimeout) === null || _a === void 0 ? void 0 : _a.call(this);
if (timeout !== undefined && timeout > 0) {
// Persist the react event since it will be used in a later macrotask.
e === null || e === void 0 ? void 0 : e.persist();
this.cancelOpenTimeout = this.setTimeout(() => {
this.setOpenState(isOpen, e);
}, timeout);
}
else {
if (this.props.isOpen == null) {
this.setState({ isOpen });
}
else {
(_c = (_b = this.props).onInteraction) === null || _c === void 0 ? void 0 : _c.call(_b, isOpen, e);
}
if (!isOpen) {
// non-null assertion because the only time `e` is undefined is when in controlled mode
// or the rare special case in uncontrolled mode when the `disabled` flag is toggled true
(_e = (_d = this.props).onClose) === null || _e === void 0 ? void 0 : _e.call(_d, e);
this.setState({ isClosingViaEscapeKeypress: isEscapeKeypressEvent(e === null || e === void 0 ? void 0 : e.nativeEvent) });
}
}
}
updateDarkParent() {
var _a;
if (this.props.usePortal && this.state.isOpen) {
const hasDarkParent = ((_a = this.targetRef.current) === null || _a === void 0 ? void 0 : _a.closest(`.${common_1.Classes.DARK}`)) != null;
this.setState({ hasDarkParent });
}
}
isElementInPopover(element) {
var _a, _b;
return (_b = (_a = this.getPopoverElement()) === null || _a === void 0 ? void 0 : _a.contains(element)) !== null && _b !== void 0 ? _b : false;
}
getIsContentEmpty() {
const { content } = this.props;
return content == null || common_1.Utils.isEmptyString(content);
}
}
exports.Popover = Popover;
Popover.displayName = `${common_1.DISPLAYNAME_PREFIX}.Popover`;
Popover.defaultProps = {
boundary: "clippingParents",
captureDismiss: false,
defaultIsOpen: false,
disabled: false,
fill: false,
hasBackdrop: false,
hoverCloseDelay: 300,
hoverOpenDelay: 150,
inheritDarkTheme: true,
interactionKind: exports.PopoverInteractionKind.CLICK,
matchTargetWidth: false,
minimal: false,
openOnTargetFocus: true,
// N.B. we don't set a default for `placement` or `position` here because that would trigger
// a warning in validateProps if the other prop is specified by a user of this component
positioningStrategy: "absolute",
renderTarget: undefined,
shouldReturnFocusOnClose: false,
targetTagName: "span",
transitionDuration: 300,
usePortal: true,
};
function isEscapeKeypressEvent(e) {
return e instanceof KeyboardEvent && e.key === "Escape";
}
function noop() {
// no-op
}
//# sourceMappingURL=popover.js.map