UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Office 365.

182 lines • 8.99 kB
import * as tslib_1 from "tslib"; // Utilities import * as React from 'react'; import { BaseComponent, classNamesFunction, createRef } from '../../Utilities'; import { DefaultPalette } from '../../Styling'; // Component Dependencies import { PositioningContainer } from './PositioningContainer/index'; import { Beak } from './Beak/Beak'; import { getStyles } from './Coachmark.styles'; import { FocusZone } from '../../FocusZone'; var getClassNames = classNamesFunction(); var Coachmark = /** @class */ (function (_super) { tslib_1.__extends(Coachmark, _super); function Coachmark(props) { var _this = _super.call(this, props) || this; /** * The cached HTMLElement reference to the Entity Inner Host * element. */ _this._entityInnerHostElement = createRef(); _this._translateAnimationContainer = createRef(); _this._positioningContainer = createRef(); _this._onFocusHandler = function () { _this._openCoachmark(); }; _this._openCoachmark = function () { _this.setState({ collapsed: false }); _this._translateAnimationContainer.current && _this._translateAnimationContainer.current.addEventListener('animationstart', function () { if (_this.props.onAnimationOpenStart) { _this.props.onAnimationOpenStart(); } }); _this._translateAnimationContainer.current && _this._translateAnimationContainer.current.addEventListener('animationend', function () { if (_this.props.onAnimationOpenEnd) { _this.props.onAnimationOpenEnd(); } }); }; // Set defaults for state _this.state = { collapsed: props.collapsed, isBeaconAnimating: true, isMeasuring: true, entityInnerHostRect: { width: 0, height: 0 }, isMouseInProximity: false }; return _this; } Coachmark.prototype.render = function () { var _a = this.props, children = _a.children, beakWidth = _a.beakWidth, beakHeight = _a.beakHeight, target = _a.target, width = _a.width, height = _a.height, color = _a.color; var classNames = getClassNames(getStyles, { collapsed: this.state.collapsed, isBeaconAnimating: this.state.isBeaconAnimating, isMeasuring: this.state.isMeasuring, entityHostHeight: this.state.entityInnerHostRect.height + 'px', entityHostWidth: this.state.entityInnerHostRect.width + 'px', width: width + 'px', height: height + 'px', color: color }); return (React.createElement(PositioningContainer, { target: target, offsetFromTarget: beakHeight, componentRef: this._positioningContainer }, React.createElement("div", { className: classNames.root }, React.createElement("div", { className: classNames.pulsingBeacon }), React.createElement("div", { className: classNames.translateAnimationContainer, ref: this._translateAnimationContainer }, React.createElement("div", { className: classNames.scaleAnimationLayer }, React.createElement("div", { className: classNames.rotateAnimationLayer }, this._positioningContainer.current && React.createElement(Beak, { width: beakWidth, height: beakHeight, left: this.state.beakLeft, top: this.state.beakTop }), React.createElement(FocusZone, null, React.createElement("div", { className: classNames.entityHost, "data-is-focusable": true, onFocus: this._onFocusHandler }, React.createElement("div", { className: classNames.entityInnerHost, ref: this._entityInnerHostElement }, children))))))))); }; Coachmark.prototype.componentWillReceiveProps = function (newProps) { if (this.props.collapsed && !newProps.collapsed) { // The coachmark is about to open this._openCoachmark(); } }; Coachmark.prototype.componentDidMount = function () { var _this = this; this._async.requestAnimationFrame((function () { if (_this._entityInnerHostElement.current && (_this.state.entityInnerHostRect.width + _this.state.entityInnerHostRect.width) === 0) { // @TODO Eventually we need to add the various directions var beakLeft = (_this.props.width / 2) - (_this.props.beakWidth / 2); var beakTop = 0; _this.setState({ isMeasuring: false, entityInnerHostRect: { width: _this._entityInnerHostElement.current.offsetWidth, height: _this._entityInnerHostElement.current.offsetHeight }, beakLeft: beakLeft + 'px', beakTop: beakTop + 'px' }); _this.forceUpdate(); } // We dont want to the user to immediatley trigger the coachmark when it's opened _this._async.setTimeout(function () { _this._addProximityHandler(100); }, _this.props.delayBeforeMouseOpen); })); }; Coachmark.prototype._addProximityHandler = function (mouseProximityOffset) { var _this = this; if (mouseProximityOffset === void 0) { mouseProximityOffset = 0; } /** * An array of cached ids returned when setTimeout runs during * the window resize event trigger. */ var timeoutIds = []; /** * The target element the mouse would be in * proximity to */ var targetElementRect; // Take the initial measure out of the initial render to prevent // an unnecessary render. this._async.setTimeout(function () { if (_this._entityInnerHostElement.current) { targetElementRect = _this._entityInnerHostElement.current.getBoundingClientRect(); } // When the window resizes we want to async // get the bounding client rectangle. // Every time the event is triggered we want to // setTimeout and then clear any previous instances // of setTimeout. _this._events.on(window, 'resize', function () { timeoutIds.forEach(function (value) { clearInterval(value); }); timeoutIds.push(_this._async.setTimeout(function () { if (_this._entityInnerHostElement.current) { targetElementRect = _this._entityInnerHostElement.current.getBoundingClientRect(); } }, 100)); }); }, 10); // Every time the document's mouse move is triggered // we want to check if inside of an element and // set the state with the result. this._events.on(document, 'mousemove', function (e) { var mouseY = e.pageY; var mouseX = e.pageX; var isMouseInProximity = _this._isInsideElement(mouseX, mouseY, targetElementRect, mouseProximityOffset); if (isMouseInProximity !== _this.state.isMouseInProximity) { // We don't want to update the isMouseInProximtiy state because // The coachmark only opens and does not collapse. // Setting isMouseInProximity here will cause the coachmark to open and close _this.setState({ collapsed: !isMouseInProximity }); } if (_this.props.onMouseMove) { _this.props.onMouseMove(e); } }); }; Coachmark.prototype._isInsideElement = function (mouseX, mouseY, elementRect, mouseProximityOffset) { if (mouseProximityOffset === void 0) { mouseProximityOffset = 0; } return mouseX > (elementRect.left - mouseProximityOffset) && mouseX < ((elementRect.left + elementRect.width) + mouseProximityOffset) && mouseY > (elementRect.top - mouseProximityOffset) && mouseY < ((elementRect.top + elementRect.height) + mouseProximityOffset); }; Coachmark.defaultProps = { collapsed: true, mouseProximityOffset: 100, beakWidth: 26, beakHeight: 12, delayBeforeMouseOpen: 3600, width: 36, height: 36, color: DefaultPalette.themePrimary }; return Coachmark; }(BaseComponent)); export { Coachmark }; //# sourceMappingURL=Coachmark.js.map