UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Microsoft 365.

222 lines • 10.7 kB
import { __assign, __extends } from "tslib"; import * as React from 'react'; import { divProperties, getNativeProps, getId, KeyCodes, getDocument, classNamesFunction, initializeComponentRef, EventGroup, Async, } from '../../Utilities'; import { OpenCardMode, HoverCardType, } from './HoverCard.types'; import { ExpandingCard } from './ExpandingCard'; import { ExpandingCardMode } from './ExpandingCard.types'; import { PlainCard } from './PlainCard/PlainCard'; var getClassNames = classNamesFunction(); var HoverCardBase = /** @class */ (function (_super) { __extends(HoverCardBase, _super); // Constructor function HoverCardBase(props) { var _this = _super.call(this, props) || this; // The wrapping div that gets the hover events _this._hoverCard = React.createRef(); _this.dismiss = function (withTimeOut) { _this._async.clearTimeout(_this._openTimerId); _this._async.clearTimeout(_this._dismissTimerId); if (!withTimeOut) { _this._setDismissedState(); } else { _this._dismissTimerId = _this._async.setTimeout(function () { _this._setDismissedState(); }, _this.props.cardDismissDelay); } }; // Show HoverCard _this._cardOpen = function (ev) { // eslint-disable-next-line deprecation/deprecation if (_this._shouldBlockHoverCard() || (ev.type === 'keydown' && !(ev.which === _this.props.openHotKey))) { return; } _this._async.clearTimeout(_this._dismissTimerId); if (ev.type === 'mouseenter') { _this._currentMouseTarget = ev.currentTarget; } _this._executeCardOpen(ev); }; _this._executeCardOpen = function (ev) { _this._async.clearTimeout(_this._openTimerId); _this._openTimerId = _this._async.setTimeout(function () { _this.setState(function (prevState) { if (!prevState.isHoverCardVisible) { return { isHoverCardVisible: true, mode: ExpandingCardMode.compact, openMode: ev.type === 'keydown' ? OpenCardMode.hotKey : OpenCardMode.hover, }; } return prevState; }); }, _this.props.cardOpenDelay); }; /** * Hide HoverCard * How we dismiss the card depends on where the callback is coming from. * This is provided by the `isNativeEvent` argument. * true: Event is coming from event listeners set up in componentDidMount. * false: Event is coming from the `onLeave` prop from the HoverCard component. */ _this._cardDismiss = function (isNativeEvent, ev) { if (isNativeEvent) { // We expect these to be MouseEvents, If not, return. if (!(ev instanceof MouseEvent)) { return; } // eslint-disable-next-line deprecation/deprecation if (ev.type === 'keydown' && ev.which !== KeyCodes.escape) { return; } // Dismiss if not sticky and currentTarget is the same element that mouse last entered // eslint-disable-next-line deprecation/deprecation if (!_this.props.sticky && (_this._currentMouseTarget === ev.currentTarget || ev.which === KeyCodes.escape)) { _this.dismiss(true); } } else { // If this is a mouseleave event and the component is sticky, do not dismiss. if (_this.props.sticky && !(ev instanceof MouseEvent) && ev.nativeEvent instanceof MouseEvent && ev.type === 'mouseleave') { return; } _this.dismiss(true); } }; _this._setDismissedState = function () { _this.setState({ isHoverCardVisible: false, mode: ExpandingCardMode.compact, openMode: OpenCardMode.hover, }); }; _this._instantOpenAsExpanded = function (ev) { _this._async.clearTimeout(_this._dismissTimerId); _this.setState(function (prevState) { if (!prevState.isHoverCardVisible) { return { isHoverCardVisible: true, mode: ExpandingCardMode.expanded, }; } return prevState; }); }; _this._setEventListeners = function () { var _a = _this.props, trapFocus = _a.trapFocus, instantOpenOnClick = _a.instantOpenOnClick, eventListenerTarget = _a.eventListenerTarget; var target = eventListenerTarget ? _this._getTargetElement(eventListenerTarget) : _this._getTargetElement(_this.props.target); var nativeEventDismiss = _this._nativeDismissEvent; // target can be undefined if ref isn't available, only assign // events when defined to avoid throwing exception. if (target) { _this._events.on(target, 'mouseenter', _this._cardOpen); _this._events.on(target, 'mouseleave', nativeEventDismiss); if (trapFocus) { _this._events.on(target, 'keydown', _this._cardOpen); } else { _this._events.on(target, 'focus', _this._cardOpen); _this._events.on(target, 'blur', nativeEventDismiss); } if (instantOpenOnClick) { _this._events.on(target, 'click', _this._instantOpenAsExpanded); } else { _this._events.on(target, 'mousedown', nativeEventDismiss); _this._events.on(target, 'keydown', nativeEventDismiss); } } }; initializeComponentRef(_this); _this._async = new Async(_this); _this._events = new EventGroup(_this); _this._nativeDismissEvent = _this._cardDismiss.bind(_this, true); _this._childDismissEvent = _this._cardDismiss.bind(_this, false); _this.state = { isHoverCardVisible: false, mode: ExpandingCardMode.compact, openMode: OpenCardMode.hover, }; return _this; } HoverCardBase.prototype.componentDidMount = function () { this._setEventListeners(); }; HoverCardBase.prototype.componentWillUnmount = function () { this._async.dispose(); this._events.dispose(); }; HoverCardBase.prototype.componentDidUpdate = function (prevProps, prevState) { var _this = this; if (prevProps.target !== this.props.target) { this._events.off(); this._setEventListeners(); } if (prevState.isHoverCardVisible !== this.state.isHoverCardVisible) { if (this.state.isHoverCardVisible) { this._async.setTimeout(function () { _this.setState({ mode: ExpandingCardMode.expanded, }, function () { _this.props.onCardExpand && _this.props.onCardExpand(); }); }, this.props.expandedCardOpenDelay); this.props.onCardVisible && this.props.onCardVisible(); } else { this.setState({ mode: ExpandingCardMode.compact, }); this.props.onCardHide && this.props.onCardHide(); } } }; // Render HoverCardBase.prototype.render = function () { var _a = this.props, expandingCardProps = _a.expandingCardProps, children = _a.children, id = _a.id, _b = _a.setAriaDescribedBy, setAriaDescribedBy = _b === void 0 ? true : _b, customStyles = _a.styles, theme = _a.theme, className = _a.className, type = _a.type, plainCardProps = _a.plainCardProps, trapFocus = _a.trapFocus, setInitialFocus = _a.setInitialFocus; var _c = this.state, isHoverCardVisible = _c.isHoverCardVisible, mode = _c.mode, openMode = _c.openMode; var hoverCardId = id || getId('hoverCard'); this._classNames = getClassNames(customStyles, { theme: theme, className: className, }); // Common props for both card types. var commonCardProps = __assign(__assign({}, getNativeProps(this.props, divProperties)), { id: hoverCardId, trapFocus: !!trapFocus, firstFocus: setInitialFocus || openMode === OpenCardMode.hotKey, targetElement: this._getTargetElement(this.props.target), onEnter: this._cardOpen, onLeave: this._childDismissEvent }); var finalExpandedCardProps = __assign(__assign(__assign({}, expandingCardProps), commonCardProps), { mode: mode }); var finalPlainCardProps = __assign(__assign({}, plainCardProps), commonCardProps); return (React.createElement("div", { className: this._classNames.host, ref: this._hoverCard, "aria-describedby": setAriaDescribedBy && isHoverCardVisible ? hoverCardId : undefined, "data-is-focusable": !this.props.target }, children, isHoverCardVisible && (type === HoverCardType.expanding ? (React.createElement(ExpandingCard, __assign({}, finalExpandedCardProps))) : (React.createElement(PlainCard, __assign({}, finalPlainCardProps)))))); }; HoverCardBase.prototype._getTargetElement = function (target) { switch (typeof target) { case 'string': return getDocument().querySelector(target); case 'object': return target; default: return this._hoverCard.current || undefined; } }; HoverCardBase.prototype._shouldBlockHoverCard = function () { return !!(this.props.shouldBlockHoverCard && this.props.shouldBlockHoverCard()); }; HoverCardBase.defaultProps = { cardOpenDelay: 500, cardDismissDelay: 100, expandedCardOpenDelay: 1500, instantOpenOnClick: false, setInitialFocus: false, openHotKey: KeyCodes.c, type: HoverCardType.expanding, }; return HoverCardBase; }(React.Component)); export { HoverCardBase }; //# sourceMappingURL=HoverCard.base.js.map