office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
176 lines • 9.63 kB
JavaScript
define(["require", "exports", "tslib", "react", "../../Utilities", "../../Styling", "./PositioningContainer/PositioningContainer", "./Beak/Beak", "./Coachmark.styles", "../../FocusZone"], function (require, exports, tslib_1, React, Utilities_1, Styling_1, PositioningContainer_1, Beak_1, Coachmark_styles_1, FocusZone_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var getClassNames = Utilities_1.classNamesFunction();
var Coachmark = /** @class */ (function (_super) {
tslib_1.__extends(Coachmark, _super);
function Coachmark(props) {
var _this = _super.call(this, props) || this;
// 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, beaconColorOne = _a.beaconColorOne, beaconColorTwo = _a.beaconColorTwo;
var classNames = getClassNames(Coachmark_styles_1.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,
beaconColorOne: beaconColorOne,
beaconColorTwo: beaconColorTwo
});
return (React.createElement(PositioningContainer_1.PositioningContainer, { target: target, offsetFromTarget: beakHeight, componentRef: this._resolveRef('_positioningContainer') },
React.createElement("div", { className: classNames.root },
React.createElement("div", { className: classNames.pulsingBeacon }),
React.createElement("div", { className: classNames.translateAnimationContainer, ref: this._resolveRef('_translateAnimationContainer') },
React.createElement("div", { className: classNames.scaleAnimationLayer },
React.createElement("div", { className: classNames.rotateAnimationLayer },
this._positioningContainer && React.createElement(Beak_1.Beak, { width: beakWidth, height: beakHeight, left: this.state.beakLeft, top: this.state.beakTop }),
React.createElement(FocusZone_1.FocusZone, null,
React.createElement("div", { className: classNames.entityHost, ref: this._resolveRef('_entityHost'), "data-is-focusable": true, onFocus: this._onFocusHandler },
React.createElement("div", { className: classNames.entityInnerHost, ref: this._resolveRef('_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.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.offsetWidth,
height: _this._entityInnerHostElement.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._onFocusHandler = function () {
this._openCoachmark();
};
Coachmark.prototype._openCoachmark = function () {
var _this = this;
this.setState({
collapsed: false
});
this._translateAnimationContainer.addEventListener('animationstart', function () {
if (_this.props.onAnimationOpenStart) {
_this.props.onAnimationOpenStart();
}
});
this._translateAnimationContainer.addEventListener('animationend', function () {
if (_this.props.onAnimationOpenEnd) {
_this.props.onAnimationOpenEnd();
}
});
};
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 unnessecary render.
this._async.setTimeout(function () {
targetElementRect = _this._entityInnerHostElement.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 () {
targetElementRect = _this._entityInnerHostElement.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,
beaconColorOne: '#00FFEC',
beaconColorTwo: '#005EDD',
color: Styling_1.DefaultPalette.themePrimary
};
tslib_1.__decorate([
Utilities_1.autobind
], Coachmark.prototype, "_onFocusHandler", null);
tslib_1.__decorate([
Utilities_1.autobind
], Coachmark.prototype, "_openCoachmark", null);
return Coachmark;
}(Utilities_1.BaseComponent));
exports.Coachmark = Coachmark;
});
//# sourceMappingURL=Coachmark.js.map