Skip to content

Instantly share code, notes, and snippets.

@pushred
Last active October 1, 2018 18:00
Show Gist options
  • Save pushred/7d8a4df145a2cc137b47e21bf4436c4b to your computer and use it in GitHub Desktop.
Save pushred/7d8a4df145a2cc137b47e21bf4436c4b to your computer and use it in GitHub Desktop.
react-joyride build issue
import ReactDOM from 'react-dom';
import ExecutionEnvironment from 'exenv';
import is from 'is-lite';
import scroll from 'scroll';
import scrollDoc from 'scroll-doc';
import getScrollParent from 'scrollparent';
import deepmerge from 'deepmerge';
import React from 'react';
import PropTypes from 'prop-types';
import treeChanges from 'tree-changes';
import isRequiredIf from 'react-proptype-conditional-require';
import Floater from 'react-floater';
var STATUS = {
IDLE: 'idle',
READY: 'ready',
WAITING: 'waiting',
RUNNING: 'running',
PAUSED: 'paused',
SKIPPED: 'skipped',
FINISHED: 'finished',
ERROR: 'error'
};
var ACTIONS = {
INIT: 'init',
START: 'start',
STOP: 'stop',
RESET: 'reset',
RESTART: 'restart',
PREV: 'prev',
NEXT: 'next',
GO: 'go',
INDEX: 'index',
CLOSE: 'close',
SKIP: 'skip',
UPDATE: 'update'
};
var LIFECYCLE = {
INIT: 'init',
READY: 'ready',
BEACON: 'beacon',
TOOLTIP: 'tooltip',
COMPLETE: 'complete',
ERROR: 'error'
};
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var canUseDOM = ExecutionEnvironment.canUseDOM;
var isReact16 = ReactDOM.createPortal !== undefined;
/**
* Convert hex to RGB
*
* @param {string} hex
* @returns {Array}
*/
function hexToRGB(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
var properHex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(properHex);
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null;
}
/**
* Get the current browser
*
* @returns {String}
*/
function getBrowser() {
/* istanbul ignore if */
if (typeof window === 'undefined') {
return 'node';
}
if (document.documentMode) {
return 'ie';
}
if (/Edge/.test(navigator.userAgent)) {
return 'edge';
}
// Opera 8.0+
if (Boolean(window.opera) || navigator.userAgent.indexOf(' OPR/') >= 0) {
return 'opera';
}
// Firefox 1.0+
if (typeof window.InstallTrigger !== 'undefined') {
return 'firefox';
}
// Chrome 1+
if (window.chrome) {
return 'chrome';
}
// Safari (and Chrome iOS, Firefox iOS)
if (/(Version\/([0-9._]+).*Safari|CriOS|FxiOS| Mobile\/)/.test(navigator.userAgent)) {
return 'safari';
}
return navigator.userAgent;
}
/**
* Detect legacy browsers
*
* @returns {boolean}
*/
function isLegacy() {
return !(['chrome', 'safari', 'firefox', 'opera'].indexOf(getBrowser()) !== -1);
}
/**
* Log method calls if debug is enabled
*
* @private
* @param {Object} arg
* @param {string} arg.title - The title the logger was called from
* @param {Object|Array} [arg.data] - The data to be logged
* @param {boolean} [arg.warn] - If true, the message will be a warning
* @param {boolean} [arg.debug] - Nothing will be logged unless debug is true
*/
function log(_ref) {
var title = _ref.title,
data = _ref.data,
_ref$warn = _ref.warn,
warn = _ref$warn === undefined ? false : _ref$warn,
_ref$debug = _ref.debug,
debug = _ref$debug === undefined ? false : _ref$debug;
/* eslint-disable no-console */
var logFn = warn ? console.warn || console.error : console.log;
if (debug && title && data) {
console.groupCollapsed('%creact-joyride: ' + title, 'color: #ff0044; font-weight: bold; font-size: 12px;');
if (Array.isArray(data)) {
data.forEach(function (d) {
if (is.plainObject(d) && d.key) {
logFn.apply(console, [d.key, d.value]);
} else {
logFn.apply(console, [d]);
}
});
} else {
logFn.apply(console, [data]);
}
console.groupEnd();
}
/* eslint-enable */
}
function hasValidKeys(value, keys) {
if (!is.plainObject(value) || !is.array(keys)) {
return false;
}
var validKeys = keys;
if (is.string(keys)) {
validKeys = [keys];
}
return Object.keys(value).every(function (d) {
return validKeys.indexOf(d) !== -1;
});
}
function isEqual(a, b) {
var p = void 0;
var t = void 0;
for (p in a) {
if (Object.prototype.hasOwnProperty.call(a, p)) {
if (typeof b[p] === 'undefined') {
return false;
}
if (b[p] && !a[p]) {
return false;
}
t = _typeof(a[p]);
if (t === 'object' && !isEqual(a[p], b[p])) {
return false;
}
if (t === 'function' && (typeof b[p] === 'undefined' || a[p].toString() !== b[p].toString())) {
return false;
}
if (a[p] !== b[p]) {
return false;
}
}
}
for (p in b) {
if (typeof a[p] === 'undefined') {
return false;
}
}
return true;
}
var defaultState = {
action: '',
controlled: false,
index: 0,
lifecycle: LIFECYCLE.INIT,
size: 0,
status: STATUS.IDLE
};
var validKeys = ['action', 'index', 'lifecycle', 'status'];
function createStore(props) {
var store = new Map();
var data = new Map();
var Store = function () {
function Store() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$continuous = _ref.continuous,
continuous = _ref$continuous === undefined ? false : _ref$continuous,
stepIndex = _ref.stepIndex,
_ref$steps = _ref.steps,
steps = _ref$steps === undefined ? [] : _ref$steps;
classCallCheck(this, Store);
_initialiseProps.call(this);
this.setState({
action: ACTIONS.INIT,
controlled: is.number(stepIndex),
continuous: continuous,
index: is.number(stepIndex) ? stepIndex : 0,
lifecycle: LIFECYCLE.INIT,
status: steps.length ? STATUS.READY : STATUS.IDLE
}, true);
this.setSteps(steps);
}
createClass(Store, [{
key: 'addListener',
value: function addListener(listener) {
this.listener = listener;
}
}, {
key: 'setState',
value: function setState(nextState) {
var initial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var state = this.getState();
var _state$nextState = _extends({}, state, nextState),
action = _state$nextState.action,
index = _state$nextState.index,
lifecycle = _state$nextState.lifecycle,
status = _state$nextState.status;
store.set('action', action);
store.set('index', index);
store.set('lifecycle', lifecycle);
store.set('status', status);
if (initial) {
store.set('controlled', nextState.controlled);
store.set('continuous', nextState.continuous);
}
/* istanbul ignore else */
if (this.listener && this.hasUpdatedState(state)) {
// console.log('▶ ▶ ▶ NEW STATE', this.getState());
this.listener(this.getState());
}
}
}, {
key: 'getState',
value: function getState() {
if (!store.size) {
return _extends({}, defaultState);
}
var index = parseInt(store.get('index'), 10);
var steps = this.getSteps();
var size = steps.length;
return {
action: store.get('action'),
controlled: store.get('controlled'),
index: index,
lifecycle: store.get('lifecycle'),
size: size,
status: store.get('status')
};
}
}, {
key: 'getNextState',
value: function getNextState(state) {
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var _getState = this.getState(),
action = _getState.action,
controlled = _getState.controlled,
index = _getState.index,
size = _getState.size,
status = _getState.status;
var newIndex = is.number(state.index) ? state.index : index;
var nextIndex = controlled && !force ? index : Math.min(Math.max(newIndex, 0), size);
return {
action: state.action || action,
index: nextIndex,
lifecycle: state.lifecycle || LIFECYCLE.INIT,
status: nextIndex === size ? STATUS.FINISHED : state.status || status
};
}
}, {
key: 'hasUpdatedState',
value: function hasUpdatedState(oldState) {
var before = JSON.stringify(oldState);
var after = JSON.stringify(this.getState());
return before !== after;
}
}, {
key: 'getSteps',
value: function getSteps() {
var steps = data.get('steps');
return Array.isArray(steps) ? steps : [];
}
}, {
key: 'getHelpers',
value: function getHelpers() {
return {
start: this.start,
stop: this.stop,
restart: this.restart,
reset: this.reset,
prev: this.prev,
next: this.next,
go: this.go,
index: this.index,
close: this.close,
skip: this.skip,
info: this.info
};
}
}]);
return Store;
}();
var _initialiseProps = function _initialiseProps() {
var _this = this;
this.setSteps = function (steps) {
var _getState2 = _this.getState(),
size = _getState2.size,
status = _getState2.status;
data.set('steps', steps);
if (status === STATUS.WAITING && !size && steps.length) {
_this.setState({ status: STATUS.RUNNING });
}
};
this.update = function (state) {
if (!hasValidKeys(state, validKeys)) {
throw new Error('state is not valid');
}
_this.setState(_extends({}, _this.getNextState(_extends({}, _this.getState(), state, {
action: state.action || ACTIONS.UPDATE
}), true)));
};
this.steps = function (nextSteps) {
if (!is.array(nextSteps)) return;
_this.setSteps(nextSteps);
};
this.start = function (nextIndex) {
var _getState3 = _this.getState(),
index = _getState3.index,
size = _getState3.size;
_this.setState(_extends({}, _this.getNextState({
action: ACTIONS.START,
index: is.number(nextIndex) ? nextIndex : index
}, true), {
status: size ? STATUS.RUNNING : STATUS.WAITING
}));
};
this.stop = function () {
var advance = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var _getState4 = _this.getState(),
index = _getState4.index,
status = _getState4.status;
if ([STATUS.FINISHED, STATUS.SKIPPED].indexOf(status) !== -1) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }), {
status: STATUS.PAUSED
}));
};
this.restart = function () {
var _getState5 = _this.getState(),
controlled = _getState5.controlled;
if (controlled) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.RESTART, index: 0 }), {
status: STATUS.RUNNING
}));
};
this.reset = function () {
var _getState6 = _this.getState(),
controlled = _getState6.controlled;
if (controlled) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.RESET, index: 0 }), {
status: STATUS.READY
}));
};
this.prev = function () {
var _getState7 = _this.getState(),
index = _getState7.index,
status = _getState7.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.PREV, index: index - 1 })));
};
this.next = function () {
var _getState8 = _this.getState(),
index = _getState8.index,
status = _getState8.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_this.getNextState({ action: ACTIONS.NEXT, index: index + 1 }));
};
this.go = function (number) {
var _getState9 = _this.getState(),
index = _getState9.index,
status = _getState9.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.GO, index: index + number })));
};
this.index = function (nextIndex) {
var _getState10 = _this.getState(),
status = _getState10.status;
if (status !== STATUS.RUNNING) return;
var step = _this.getSteps()[nextIndex];
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.INDEX, index: nextIndex }), {
status: step ? status : STATUS.FINISHED
}));
};
this.close = function () {
var _getState11 = _this.getState(),
index = _getState11.index,
status = _getState11.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.CLOSE, index: index + 1 })));
};
this.skip = function () {
var _getState12 = _this.getState(),
status = _getState12.status;
if (status !== STATUS.RUNNING) return;
_this.setState({
action: ACTIONS.SKIP,
lifecycle: LIFECYCLE.INIT,
status: STATUS.SKIPPED
});
};
this.info = function () {
return _this.getState();
};
};
return new Store(props);
}
/**
* Find the bounding client rect
*
* @private
* @param {HTMLElement} element - The target element
* @returns {Object}
*/
function getClientRect(element) {
if (!element) {
return {};
}
return element.getBoundingClientRect();
}
/**
* Helper function to get the browser-normalized "document height"
* @returns {Number}
*/
function getDocumentHeight() {
var _document = document,
body = _document.body,
html = _document.documentElement;
if (!body || !html) {
return 0;
}
return Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
}
function getStyleComputedProperty(el) {
if (!el || el.nodeType !== 1) {
return {};
}
return getComputedStyle(el);
}
function hasCustomScrollParent(element) {
if (!element) {
return false;
}
return getScrollParent(element) !== scrollDoc();
}
function hasCustomOffsetParent(element) {
return element.offsetParent !== document.body;
}
function isFixed(el) {
if (!el || !(el instanceof HTMLElement)) {
return false;
}
var nodeName = el.nodeName;
if (nodeName === 'BODY' || nodeName === 'HTML') {
return false;
}
if (getStyleComputedProperty(el).position === 'fixed') {
return true;
}
return isFixed(el.parentNode);
}
/**
* Get the scrollTop position
*
* @param {HTMLElement} element
* @param {number} offset
*
* @returns {number}
*/
function getScrollTo(element, offset) {
if (!element) {
return 0;
}
var parent = getScrollParent(element);
var top = element.offsetTop;
if (hasCustomScrollParent(element) && !hasCustomOffsetParent(element)) {
top -= parent.offsetTop;
}
return Math.floor(top - offset);
}
/**
* Find and return the target DOM element based on a step's 'target'.
*
* @private
* @param {string|HTMLElement} element
*
* @returns {HTMLElement|undefined}
*/
function getElement(element) {
if (typeof element !== 'string') {
return element;
}
return element ? document.querySelector(element) : null;
}
/**
* Find and return the target DOM element based on a step's 'target'.
*
* @private
* @param {string|HTMLElement} element
* @param {number} offset
*
* @returns {HTMLElement|undefined}
*/
function getElementPosition(element, offset) {
var elementRect = getClientRect(element);
var scrollParent = getScrollParent(element);
var hasScrollParent = hasCustomScrollParent(element);
var top = elementRect.top + (!hasScrollParent && !isFixed(element) ? scrollParent.scrollTop : 0);
return Math.floor(top - offset);
}
function scrollTo(value) {
var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scrollDoc();
return new Promise(function (resolve, reject) {
var scrollTop = element.scrollTop;
var limit = value > scrollTop ? value - scrollTop : scrollTop - value;
scroll.top(element, value, { duration: limit < 100 ? 50 : 300 }, function (error) {
if (error && error.message !== 'Element already at target scroll position') {
return reject(error);
}
return resolve();
});
});
}
var defaultOptions = {
arrowColor: '#fff',
backgroundColor: '#fff',
beaconSize: 36,
overlayColor: 'rgba(0, 0, 0, 0.5)',
primaryColor: '#f04',
spotlightShadow: '0 0 15px rgba(0, 0, 0, 0.5)',
textColor: '#333',
zIndex: 100
};
var buttonReset = {
backgroundColor: 'transparent',
border: 0,
borderRadius: 0,
color: '#555',
cursor: 'pointer',
lineHeight: 1,
padding: 8,
WebkitAppearance: 'none'
};
var spotlight = {
borderRadius: 4,
position: 'absolute'
};
function getStyles(stepStyles) {
var options = deepmerge(defaultOptions, stepStyles.options || {});
var width = 290;
if (window.innerWidth > 480) {
width = 380;
} else if (window.innerWidth > 768) {
width = 490;
}
if (options.width) {
if (window.innerWidth < options.width) {
width = window.innerWidth - 30;
} else {
width = options.width; //eslint-disable-line prefer-destructuring
}
}
var overlay = {
bottom: 0,
left: 0,
overflow: 'hidden',
position: 'absolute',
right: 0,
top: 0,
zIndex: options.zIndex
};
var defaultStyles = {
beacon: _extends({}, buttonReset, {
display: 'inline-block',
height: options.beaconSize,
position: 'relative',
width: options.beaconSize,
zIndex: options.zIndex
}),
beaconInner: {
animation: 'joyride-beacon-inner 1.2s infinite ease-in-out',
backgroundColor: options.primaryColor,
borderRadius: '50%',
display: 'block',
height: '50%',
left: '50%',
opacity: 0.7,
position: 'absolute',
top: '50%',
transform: 'translate(-50%, -50%)',
width: '50%'
},
beaconOuter: {
animation: 'joyride-beacon-outer 1.2s infinite ease-in-out',
backgroundColor: 'rgba(' + hexToRGB(options.primaryColor).join(',') + ', 0.2)',
border: '2px solid ' + options.primaryColor,
borderRadius: '50%',
boxSizing: 'border-box',
display: 'block',
height: '100%',
left: 0,
opacity: 0.9,
position: 'absolute',
top: 0,
transformOrigin: 'center',
width: '100%'
},
tooltip: {
backgroundColor: options.backgroundColor,
borderRadius: 5,
boxSizing: 'border-box',
color: options.textColor,
fontSize: 16,
maxWidth: '100%',
padding: 15,
position: 'relative',
width: width
},
tooltipContainer: {
lineHeight: 1.4,
textAlign: 'center'
},
tooltipTitle: {
fontSize: 18,
margin: '0 0 10px 0'
},
tooltipContent: {
padding: '20px 10px'
},
tooltipFooter: {
alignItems: 'center',
display: 'flex',
justifyContent: 'space-between',
marginTop: 15
},
buttonNext: _extends({}, buttonReset, {
backgroundColor: options.primaryColor,
borderRadius: 4,
color: '#fff'
}),
buttonBack: _extends({}, buttonReset, {
color: options.primaryColor,
marginLeft: 'auto',
marginRight: 5
}),
buttonClose: _extends({}, buttonReset, {
color: options.textColor,
height: 14,
padding: 15,
position: 'absolute',
right: 0,
top: 0,
width: 14
}),
buttonSkip: _extends({}, buttonReset, {
color: options.textColor,
fontSize: 14
}),
overlay: _extends({}, overlay, {
backgroundColor: options.overlayColor,
mixBlendMode: 'hard-light'
}),
overlayLegacy: _extends({}, overlay),
spotlight: _extends({}, spotlight, {
backgroundColor: 'gray'
}),
spotlightLegacy: _extends({}, spotlight, {
boxShadow: '0 0 0 9999px ' + options.overlayColor + ', ' + options.spotlightShadow
}),
floaterStyles: {
arrow: {
color: options.arrowColor
},
floater: {
zIndex: options.zIndex
}
},
options: options
};
return deepmerge(defaultStyles, stepStyles || {});
}
var DEFAULTS = {
floaterProps: {
options: {
preventOverflow: {
boundariesElement: 'scrollParent'
}
},
wrapperOptions: {
offset: -18,
position: true
}
},
locale: {
back: 'Back',
close: 'Close',
last: 'Last',
next: 'Next',
open: 'Open',
skip: 'Skip'
},
step: {
event: 'click',
placement: 'bottom',
offset: 10
}
};
/**
* Validate if a step is valid
*
* @param {Object} step - A step object
* @param {boolean} debug
*
* @returns {boolean} - True if the step is valid, false otherwise
*/
function validateStep(step) {
var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (!is.plainObject(step)) {
log({
title: 'validateStep',
data: 'step must be an object',
warn: true,
debug: debug
});
return false;
}
if (!step.target) {
log({
title: 'validateStep',
data: 'target is missing from the step',
warn: true,
debug: debug
});
return false;
}
return true;
}
/**
* Validate if steps is valid
*
* @param {Array} steps - A steps array
* @param {boolean} debug
*
* @returns {boolean} - True if the steps are valid, false otherwise
*/
function validateSteps(steps) {
var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (!is.array(steps)) {
log({
title: 'validateSteps',
data: 'steps must be an array',
warn: true,
debug: debug
});
return false;
}
return steps.every(function (d) {
return validateStep(d, debug);
});
}
function getTourProps(props) {
var sharedTourProps = ['beaconComponent', 'disableCloseOnEsc', 'disableOverlay', 'disableOverlayClose', 'disableScrolling', 'floaterProps', 'hideBackButton', 'locale', 'showProgress', 'showSkipButton', 'spotlightClicks', 'spotlightPadding', 'styles', 'tooltipComponent'];
return Object.keys(props).filter(function (d) {
return sharedTourProps.indexOf(d) !== -1;
}).reduce(function (acc, i) {
acc[i] = props[i]; //eslint-disable-line react/destructuring-assignment
return acc;
}, {});
}
function getMergedStep(step, props) {
if (!step) return undefined;
var mergedStep = deepmerge.all([getTourProps(props), DEFAULTS.step, step]);
var mergedStyles = getStyles(deepmerge(props.styles || {}, step.styles || {}));
var scrollParent = hasCustomScrollParent(getElement(step.target));
var floaterProps = deepmerge.all([props.floaterProps || {}, DEFAULTS.floaterProps, mergedStep.floaterProps || {}]);
// Set react-floater props
floaterProps.offset = mergedStep.offset;
floaterProps.styles = deepmerge(floaterProps.styles || {}, mergedStyles.floaterStyles || {});
delete mergedStyles.floaterStyles;
if (mergedStep.floaterProps && mergedStep.floaterProps.offset) {
floaterProps.offset = mergedStep.floaterProps.offset;
}
if (!mergedStep.disableScrolling) {
floaterProps.offset += props.spotlightPadding || step.spotlightPadding || 0;
}
if (step.placementBeacon) {
floaterProps.wrapperOptions.placement = step.placementBeacon;
}
if (scrollParent) {
floaterProps.options.preventOverflow.boundariesElement = 'window';
}
return _extends({}, mergedStep, {
locale: deepmerge.all([DEFAULTS.locale, props.locale || {}, mergedStep.locale || {}]),
floaterProps: floaterProps,
styles: mergedStyles
});
}
var EVENTS = {
TOUR_START: 'tour:start',
STEP_BEFORE: 'step:before',
BEACON: 'beacon',
TOOLTIP: 'tooltip',
TOOLTIP_CLOSE: 'close',
STEP_AFTER: 'step:after',
TOUR_END: 'tour:end',
TOUR_STATUS: 'tour:status',
TARGET_NOT_FOUND: 'error:target_not_found',
ERROR: 'error'
};
var validTabNodes = /input|select|textarea|button|object/;
var TAB_KEY = 9;
var modalElement = null;
function isHidden(element) {
var noSize = element.offsetWidth <= 0 && element.offsetHeight <= 0;
if (noSize && !element.innerHTML) return true;
var style = window.getComputedStyle(element);
return noSize ? style.getPropertyValue('overflow') !== 'visible' : style.getPropertyValue('display') === 'none';
}
function isVisible(element) {
var parentElement = element;
while (parentElement) {
if (parentElement === document.body) break;
if (isHidden(parentElement)) return false;
parentElement = parentElement.parentNode;
}
return true;
}
function canHaveFocus(element, isTabIndexNotNaN) {
var nodeName = element.nodeName.toLowerCase();
var res = validTabNodes.test(nodeName) && !element.disabled || (nodeName === 'a' ? element.href || isTabIndexNotNaN : isTabIndexNotNaN);
return res && isVisible(element);
}
function canBeTabbed(element) {
var tabIndex = element.getAttribute('tabindex');
if (tabIndex === null) tabIndex = undefined;
var isTabIndexNaN = isNaN(tabIndex);
return (isTabIndexNaN || tabIndex >= 0) && canHaveFocus(element, !isTabIndexNaN);
}
function findValidTabElements(element) {
return [].slice.call(element.querySelectorAll('*'), 0).filter(canBeTabbed);
}
function interceptTab(node, event) {
var elements = findValidTabElements(node);
var shiftKey = event.shiftKey;
if (!elements.length) {
event.preventDefault();
return;
}
var x = elements.indexOf(document.activeElement);
if (x === -1 || !shiftKey && x + 1 === elements.length) {
x = 0;
} else {
x += shiftKey ? -1 : 1;
}
event.preventDefault();
elements[x].focus();
}
function handleKeyDown(e) {
if (!modalElement) {
return;
}
if (e.keyCode === TAB_KEY) {
interceptTab(modalElement, e);
}
}
function setScope(element) {
modalElement = element;
window.addEventListener('keydown', handleKeyDown, false);
}
function removeScope() {
modalElement = null;
window.removeEventListener('keydown', handleKeyDown);
}
var JoyrideBeacon = function (_React$Component) {
inherits(JoyrideBeacon, _React$Component);
function JoyrideBeacon(props) {
classCallCheck(this, JoyrideBeacon);
var _this = possibleConstructorReturn(this, (JoyrideBeacon.__proto__ || Object.getPrototypeOf(JoyrideBeacon)).call(this, props));
if (!props.beaconComponent) {
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
var css = '\n@keyframes joyride-beacon-inner {\n 20% {\n opacity: 0.9;\n }\n\n 90% {\n opacity: 0.7;\n }\n}\n\n@keyframes joyride-beacon-outer {\n 0% {\n transform: scale(1);\n }\n\n 45% {\n opacity: 0.7;\n transform: scale(0.75);\n }\n\n 100% {\n opacity: 0.9;\n transform: scale(1);\n }\n}\n ';
style.type = 'text/css';
style.id = 'joyride-beacon-animation';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
}
return _this;
}
createClass(JoyrideBeacon, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var style = document.getElementById('joyride-beacon-animation');
if (style) {
style.parentNode.removeChild(style);
}
}
}, {
key: 'render',
value: function render() {
var _props = this.props,
beaconComponent = _props.beaconComponent,
locale = _props.locale,
onClickOrHover = _props.onClickOrHover,
styles = _props.styles;
var props = {
'aria-label': locale.open,
onClick: onClickOrHover,
onMouseEnter: onClickOrHover,
title: locale.open
};
var component = void 0;
if (beaconComponent) {
if (React.isValidElement(beaconComponent)) {
component = React.cloneElement(beaconComponent, props);
} else {
component = beaconComponent(props);
}
} else {
component = React.createElement(
'button',
_extends({
key: 'JoyrideBeacon',
className: 'joyride-beacon',
style: styles.beacon,
type: 'button'
}, props),
React.createElement('span', { style: styles.beaconInner }),
React.createElement('span', { style: styles.beaconOuter })
);
}
return component;
}
}]);
return JoyrideBeacon;
}(React.Component);
JoyrideBeacon.propTypes = {
beaconComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
locale: PropTypes.object.isRequired,
onClickOrHover: PropTypes.func.isRequired,
styles: PropTypes.object.isRequired
};
var JoyrideSpotlight = function JoyrideSpotlight(_ref) {
var styles = _ref.styles;
return React.createElement('div', {
key: 'JoyrideSpotlight',
className: 'joyride-spotlight',
style: styles
});
};
JoyrideSpotlight.propTypes = {
styles: PropTypes.object.isRequired
};
var Overlay = function (_React$Component) {
inherits(Overlay, _React$Component);
function Overlay(props) {
classCallCheck(this, Overlay);
var _this = possibleConstructorReturn(this, (Overlay.__proto__ || Object.getPrototypeOf(Overlay)).call(this, props));
_this.handleMouseMove = function (e) {
var mouseOverSpotlight = _this.state.mouseOverSpotlight;
var _this$stylesSpotlight = _this.stylesSpotlight,
height = _this$stylesSpotlight.height,
left = _this$stylesSpotlight.left,
position = _this$stylesSpotlight.position,
top = _this$stylesSpotlight.top,
width = _this$stylesSpotlight.width;
var offsetY = position === 'fixed' ? e.clientY : e.pageY;
var offsetX = position === 'fixed' ? e.clientX : e.pageX;
var inSpotlightHeight = offsetY >= top && offsetY <= top + height;
var inSpotlightWidth = offsetX >= left && offsetX <= left + width;
var inSpotlight = inSpotlightWidth && inSpotlightHeight;
if (inSpotlight !== mouseOverSpotlight) {
_this.setState({ mouseOverSpotlight: inSpotlight });
}
};
_this.handleScroll = function () {
var isScrolling = _this.state.isScrolling;
if (!isScrolling) {
_this.setState({ isScrolling: true, showSpotlight: false });
}
clearTimeout(_this.scrollTimeout);
_this.scrollTimeout = setTimeout(function () {
clearTimeout(_this.scrollTimeout);
_this.setState({ isScrolling: false, showSpotlight: true });
_this.scrollParent.removeEventListener('scroll', _this.handleScroll);
}, 50);
};
_this.handleResize = function () {
clearTimeout(_this.resizeTimeout);
_this.resizeTimeout = setTimeout(function () {
clearTimeout(_this.resizeTimeout);
_this.forceUpdate();
}, 100);
};
_this.state = {
mouseOverSpotlight: false,
isScrolling: false,
showSpotlight: props.disableScrolling
};
return _this;
}
createClass(Overlay, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props,
disableScrolling = _props.disableScrolling,
target = _props.target;
if (!disableScrolling) {
var element = getElement(target);
this.scrollParent = hasCustomScrollParent(element) ? getScrollParent(element) : document;
}
window.addEventListener('resize', this.handleResize);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this2 = this;
var disableScrolling = nextProps.disableScrolling,
lifecycle = nextProps.lifecycle,
spotlightClicks = nextProps.spotlightClicks;
var _treeChanges = treeChanges(this.props, nextProps),
changed = _treeChanges.changed,
changedTo = _treeChanges.changedTo;
if (!disableScrolling) {
if (changedTo('lifecycle', LIFECYCLE.TOOLTIP)) {
this.scrollParent.addEventListener('scroll', this.handleScroll, { passive: true });
setTimeout(function () {
var isScrolling = _this2.state.isScrolling;
if (!isScrolling) {
_this2.setState({ showSpotlight: true });
_this2.scrollParent.removeEventListener('scroll', _this2.handleScroll);
}
}, 100);
}
}
if (changed('spotlightClicks') || changed('disableOverlay') || changed('lifecycle')) {
if (spotlightClicks && lifecycle === LIFECYCLE.TOOLTIP) {
window.addEventListener('mousemove', this.handleMouseMove, false);
} else if (lifecycle !== LIFECYCLE.TOOLTIP) {
window.removeEventListener('mousemove', this.handleMouseMove);
}
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var disableScrolling = this.props.disableScrolling;
window.removeEventListener('mousemove', this.handleMouseMove);
window.removeEventListener('resize', this.handleResize);
if (!disableScrolling) {
clearTimeout(this.scrollTimeout);
this.scrollParent.removeEventListener('scroll', this.handleScroll);
}
}
}, {
key: 'render',
value: function render() {
var _state = this.state,
mouseOverSpotlight = _state.mouseOverSpotlight,
showSpotlight = _state.showSpotlight;
var _props2 = this.props,
disableOverlay = _props2.disableOverlay,
lifecycle = _props2.lifecycle,
onClickOverlay = _props2.onClickOverlay,
placement = _props2.placement,
styles = _props2.styles;
if (disableOverlay || lifecycle !== LIFECYCLE.TOOLTIP) {
return null;
}
var stylesOverlay = _extends({
cursor: disableOverlay ? 'default' : 'pointer',
height: getDocumentHeight(),
pointerEvents: mouseOverSpotlight ? 'none' : 'auto'
}, isLegacy() ? styles.overlayLegacy : styles.overlay);
var spotlight = placement !== 'center' && showSpotlight && React.createElement(JoyrideSpotlight, { styles: this.stylesSpotlight });
// Hack for Safari bug with mix-blend-mode with z-index
if (getBrowser() === 'safari') {
var mixBlendMode = stylesOverlay.mixBlendMode,
zIndex = stylesOverlay.zIndex,
safarOverlay = objectWithoutProperties(stylesOverlay, ['mixBlendMode', 'zIndex']);
spotlight = React.createElement(
'div',
{ style: _extends({}, safarOverlay) },
spotlight
);
delete stylesOverlay.backgroundColor;
}
return React.createElement(
'div',
{
className: 'joyride-overlay',
style: stylesOverlay,
onClick: onClickOverlay
},
spotlight
);
}
}, {
key: 'stylesSpotlight',
get: function get$$1() {
var showSpotlight = this.state.showSpotlight;
var _props3 = this.props,
spotlightClicks = _props3.spotlightClicks,
spotlightPadding = _props3.spotlightPadding,
styles = _props3.styles,
target = _props3.target;
var element = getElement(target);
var elementRect = getClientRect(element);
var isFixedTarget = isFixed(element);
var top = getElementPosition(element, spotlightPadding);
return _extends({}, isLegacy() ? styles.spotlightLegacy : styles.spotlight, {
height: Math.round(elementRect.height + spotlightPadding * 2),
left: Math.round(elementRect.left - spotlightPadding),
opacity: showSpotlight ? 1 : 0,
pointerEvents: spotlightClicks ? 'none' : 'auto',
position: isFixedTarget ? 'fixed' : 'absolute',
top: top,
transition: 'opacity 0.2s',
width: Math.round(elementRect.width + spotlightPadding * 2)
});
}
}]);
return Overlay;
}(React.Component);
Overlay.propTypes = {
disableOverlay: PropTypes.bool.isRequired,
disableScrolling: PropTypes.bool.isRequired,
lifecycle: PropTypes.string.isRequired,
onClickOverlay: PropTypes.func.isRequired,
placement: PropTypes.string.isRequired,
spotlightClicks: PropTypes.bool.isRequired,
spotlightPadding: PropTypes.number,
styles: PropTypes.object.isRequired,
target: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired
};
var CloseBtn = function CloseBtn(_ref) {
var styles = _ref.styles,
props = objectWithoutProperties(_ref, ['styles']);
var color = styles.color,
height = styles.height,
width = styles.width,
style = objectWithoutProperties(styles, ['color', 'height', 'width']);
return React.createElement(
'button',
_extends({
style: style,
type: 'button'
}, props),
React.createElement(
'svg',
{
width: typeof width === 'number' ? width + 'px' : width,
height: typeof height === 'number' ? height + 'px' : height,
viewBox: '0 0 18 18',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
preserveAspectRatio: 'xMidYMid'
},
React.createElement(
'g',
null,
React.createElement('path', {
d: 'M8.13911129,9.00268191 L0.171521827,17.0258467 C-0.0498027049,17.248715 -0.0498027049,17.6098394 0.171521827,17.8327545 C0.28204354,17.9443526 0.427188206,17.9998706 0.572051765,17.9998706 C0.71714958,17.9998706 0.862013139,17.9443526 0.972581703,17.8327545 L9.0000937,9.74924618 L17.0276057,17.8327545 C17.1384085,17.9443526 17.2832721,17.9998706 17.4281356,17.9998706 C17.5729992,17.9998706 17.718097,17.9443526 17.8286656,17.8327545 C18.0499901,17.6098862 18.0499901,17.2487618 17.8286656,17.0258467 L9.86135722,9.00268191 L17.8340066,0.973848225 C18.0553311,0.750979934 18.0553311,0.389855532 17.8340066,0.16694039 C17.6126821,-0.0556467968 17.254037,-0.0556467968 17.0329467,0.16694039 L9.00042166,8.25611765 L0.967006424,0.167268345 C0.745681892,-0.0553188426 0.387317931,-0.0553188426 0.165993399,0.167268345 C-0.0553311331,0.390136635 -0.0553311331,0.751261038 0.165993399,0.974176179 L8.13920499,9.00268191 L8.13911129,9.00268191 Z',
fill: color
})
)
)
);
};
CloseBtn.propTypes = {
styles: PropTypes.object.isRequired
};
var JoyrideTooltipContainer = function JoyrideTooltipContainer(_ref) {
var continuous = _ref.continuous,
backProps = _ref.backProps,
closeProps = _ref.closeProps,
primaryProps = _ref.primaryProps,
skipProps = _ref.skipProps,
index = _ref.index,
isLastStep = _ref.isLastStep,
setTooltipRef = _ref.setTooltipRef,
size = _ref.size,
step = _ref.step;
var content = step.content,
hideBackButton = step.hideBackButton,
locale = step.locale,
showProgress = step.showProgress,
showSkipButton = step.showSkipButton,
title = step.title,
styles = step.styles;
var back = locale.back,
close = locale.close,
last = locale.last,
next = locale.next,
skip = locale.skip;
var output = {
primary: close
};
if (continuous) {
if (isLastStep) {
output.primary = last;
} else {
output.primary = next;
}
if (showProgress) {
output.primary += ' (' + (index + 1) + '/' + size + ')';
}
}
if (showSkipButton && !isLastStep) {
output.skip = React.createElement(
'button',
_extends({
style: styles.buttonSkip,
type: 'button'
}, skipProps),
skip
);
}
if (!hideBackButton && index > 0) {
output.back = React.createElement(
'button',
_extends({
style: styles.buttonBack,
type: 'button'
}, backProps),
back
);
}
output.close = React.createElement(CloseBtn, _extends({}, closeProps, { styles: styles.buttonClose }));
return React.createElement(
'div',
{
key: 'JoyrideTooltip',
ref: setTooltipRef,
style: styles.tooltip
},
React.createElement(
'div',
{ style: styles.tooltipContainer },
output.close,
title && React.createElement(
'h4',
{ style: styles.tooltipTitle },
title
),
!!content && React.createElement(
'div',
{ style: styles.tooltipContent },
content
)
),
React.createElement(
'div',
{ style: styles.tooltipFooter },
output.skip,
output.back,
React.createElement(
'button',
_extends({
style: styles.buttonNext,
type: 'button'
}, primaryProps),
output.primary
)
)
);
};
JoyrideTooltipContainer.propTypes = {
backProps: PropTypes.object.isRequired,
closeProps: PropTypes.object.isRequired,
continuous: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,
isLastStep: PropTypes.bool.isRequired,
primaryProps: PropTypes.object.isRequired,
setTooltipRef: PropTypes.func.isRequired,
size: PropTypes.number.isRequired,
skipProps: PropTypes.object.isRequired,
step: PropTypes.object.isRequired
};
var JoyrideTooltip = function (_React$Component) {
inherits(JoyrideTooltip, _React$Component);
function JoyrideTooltip() {
var _ref;
var _temp, _this, _ret;
classCallCheck(this, JoyrideTooltip);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = JoyrideTooltip.__proto__ || Object.getPrototypeOf(JoyrideTooltip)).call.apply(_ref, [this].concat(args))), _this), _this.handleClickBack = function (e) {
e.preventDefault();
var helpers = _this.props.helpers;
helpers.prev();
}, _this.handleClickClose = function (e) {
e.preventDefault();
var helpers = _this.props.helpers;
helpers.close();
}, _this.handleClickPrimary = function (e) {
e.preventDefault();
var _this$props = _this.props,
continuous = _this$props.continuous,
helpers = _this$props.helpers;
if (!continuous) {
helpers.close();
return;
}
helpers.next();
}, _this.handleClickSkip = function (e) {
e.preventDefault();
var helpers = _this.props.helpers;
helpers.skip();
}, _temp), possibleConstructorReturn(_this, _ret);
}
createClass(JoyrideTooltip, [{
key: 'render',
value: function render() {
var _props = this.props,
continuous = _props.continuous,
index = _props.index,
isLastStep = _props.isLastStep,
setTooltipRef = _props.setTooltipRef,
size = _props.size,
step = _props.step;
var content = step.content,
locale = step.locale,
title = step.title,
tooltipComponent = step.tooltipComponent;
var back = locale.back,
close = locale.close,
last = locale.last,
next = locale.next,
skip = locale.skip;
var primaryText = continuous ? next : close;
if (isLastStep) {
primaryText = last;
}
var component = void 0;
var buttonProps = {
backProps: { 'aria-label': back, onClick: this.handleClickBack, role: 'button', title: back },
closeProps: { 'aria-label': close, onClick: this.handleClickClose, role: 'button', title: close },
primaryProps: { 'aria-label': primaryText, onClick: this.handleClickPrimary, role: 'button', title: primaryText },
skipProps: { 'aria-label': skip, onClick: this.handleClickSkip, role: 'button', title: skip }
};
if (tooltipComponent) {
var renderProps = _extends({}, buttonProps, {
content: content,
continuous: continuous,
index: index,
isLastStep: isLastStep,
locale: locale,
setTooltipRef: setTooltipRef,
size: size,
title: title
});
if (React.isValidElement(tooltipComponent)) {
component = React.cloneElement(tooltipComponent, renderProps);
} else {
component = tooltipComponent(renderProps);
}
} else {
component = React.createElement(JoyrideTooltipContainer, _extends({
continuous: continuous,
index: index,
isLastStep: isLastStep,
setTooltipRef: setTooltipRef,
size: size,
step: step
}, buttonProps));
}
return component;
}
}]);
return JoyrideTooltip;
}(React.Component);
JoyrideTooltip.propTypes = {
continuous: PropTypes.bool.isRequired,
helpers: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
isLastStep: PropTypes.bool.isRequired,
setTooltipRef: PropTypes.func.isRequired,
size: PropTypes.number.isRequired,
step: PropTypes.object.isRequired
};
var JoyridePortal = function (_React$Component) {
inherits(JoyridePortal, _React$Component);
function JoyridePortal(props) {
classCallCheck(this, JoyridePortal);
var _this = possibleConstructorReturn(this, (JoyridePortal.__proto__ || Object.getPrototypeOf(JoyridePortal)).call(this, props));
if (!canUseDOM) return possibleConstructorReturn(_this);
_this.node = document.createElement('div');
if (props.id) {
_this.node.id = props.id;
}
document.body.appendChild(_this.node);
return _this;
}
createClass(JoyridePortal, [{
key: 'componentDidMount',
value: function componentDidMount() {
if (!canUseDOM) return;
if (!isReact16) {
this.renderReact15();
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
if (!canUseDOM) return;
if (!isReact16) {
this.renderReact15();
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
if (!canUseDOM || !this.node) return;
if (!isReact16) {
ReactDOM.unmountComponentAtNode(this.node);
}
document.body.removeChild(this.node);
}
}, {
key: 'renderReact15',
value: function renderReact15() {
if (!canUseDOM) return null;
var children = this.props.children;
ReactDOM.unstable_renderSubtreeIntoContainer(this, children, this.node);
return null;
}
}, {
key: 'renderReact16',
value: function renderReact16() {
if (!canUseDOM || !isReact16) return null;
var children = this.props.children;
return ReactDOM.createPortal(children, this.node);
}
}, {
key: 'render',
value: function render() {
if (!isReact16) {
return null;
}
return this.renderReact16();
}
}]);
return JoyridePortal;
}(React.Component);
JoyridePortal.propTypes = {
children: PropTypes.element,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
};
var JoyrideStep = function (_React$Component) {
inherits(JoyrideStep, _React$Component);
function JoyrideStep() {
var _ref;
var _temp, _this, _ret;
classCallCheck(this, JoyrideStep);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = JoyrideStep.__proto__ || Object.getPrototypeOf(JoyrideStep)).call.apply(_ref, [this].concat(args))), _this), _this.handleClickHoverBeacon = function (e) {
var _this$props = _this.props,
step = _this$props.step,
update = _this$props.update;
if (e.type === 'mouseenter' && step.event !== 'hover') {
return;
}
update({ lifecycle: LIFECYCLE.TOOLTIP });
}, _this.handleClickOverlay = function () {
var _this$props2 = _this.props,
helpers = _this$props2.helpers,
step = _this$props2.step;
if (!step.disableOverlayClose) {
helpers.close();
}
}, _this.setTooltipRef = function (c) {
_this.tooltip = c;
}, _this.setPopper = function (popper, type) {
var _this$props3 = _this.props,
action = _this$props3.action,
getPopper = _this$props3.getPopper,
update = _this$props3.update;
if (type === 'wrapper') {
_this.beaconPopper = popper;
} else {
_this.tooltipPopper = popper;
}
getPopper(popper, type);
if (_this.beaconPopper && _this.tooltipPopper) {
update({
action: action === ACTIONS.CLOSE ? ACTIONS.CLOSE : action,
lifecycle: LIFECYCLE.READY
});
}
}, _temp), possibleConstructorReturn(_this, _ret);
}
createClass(JoyrideStep, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props,
debug = _props.debug,
lifecycle = _props.lifecycle;
log({
title: 'step:' + lifecycle,
data: [{ key: 'props', value: this.props }],
debug: debug
});
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _props2 = this.props,
action = _props2.action,
continuous = _props2.continuous,
debug = _props2.debug,
index = _props2.index,
lifecycle = _props2.lifecycle,
step = _props2.step,
update = _props2.update;
var _treeChanges = treeChanges(this.props, nextProps),
changed = _treeChanges.changed,
changedFrom = _treeChanges.changedFrom;
var skipBeacon = continuous && action !== ACTIONS.CLOSE && (index > 0 || action === ACTIONS.PREV);
if (changedFrom('lifecycle', LIFECYCLE.INIT, LIFECYCLE.READY)) {
update({ lifecycle: step.disableBeacon || skipBeacon ? LIFECYCLE.TOOLTIP : LIFECYCLE.BEACON });
}
if (changed('index')) {
log({
title: 'step:' + lifecycle,
data: [{ key: 'props', value: this.props }],
debug: debug
});
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
var _props3 = this.props,
action = _props3.action,
callback = _props3.callback,
controlled = _props3.controlled,
index = _props3.index,
lifecycle = _props3.lifecycle,
size = _props3.size,
status = _props3.status,
step = _props3.step,
update = _props3.update;
var _treeChanges2 = treeChanges(prevProps, this.props),
changed = _treeChanges2.changed,
changedTo = _treeChanges2.changedTo,
changedFrom = _treeChanges2.changedFrom;
var state = { action: action, controlled: controlled, index: index, lifecycle: lifecycle, size: size, status: status };
var isAfterAction = [ACTIONS.NEXT, ACTIONS.PREV, ACTIONS.SKIP, ACTIONS.CLOSE].indexOf(action) !== -1 && changed('action');
var hasChangedIndex = changed('index') && changedFrom('lifecycle', LIFECYCLE.TOOLTIP, LIFECYCLE.INIT);
if (!changed('status') && (hasChangedIndex || controlled && isAfterAction)) {
callback(_extends({}, state, {
index: prevProps.index,
lifecycle: LIFECYCLE.COMPLETE,
step: prevProps.step,
type: EVENTS.STEP_AFTER
}));
}
// There's a step to use, but there's no target in the DOM
if (step) {
var hasRenderedTarget = !!getElement(step.target);
if (hasRenderedTarget) {
if (changedFrom('status', STATUS.READY, STATUS.RUNNING) || changed('index')) {
callback(_extends({}, state, {
step: step,
type: EVENTS.STEP_BEFORE
}));
}
}
if (!hasRenderedTarget) {
console.warn('Target not mounted', step); //eslint-disable-line no-console
callback(_extends({}, state, {
type: EVENTS.TARGET_NOT_FOUND,
step: step
}));
if (!controlled) {
update({ index: index + ([ACTIONS.PREV].indexOf(action) !== -1 ? -1 : 1) });
}
}
}
/* istanbul ignore else */
if (changedTo('lifecycle', LIFECYCLE.BEACON)) {
callback(_extends({}, state, {
step: step,
type: EVENTS.BEACON
}));
}
if (changedTo('lifecycle', LIFECYCLE.TOOLTIP)) {
callback(_extends({}, state, {
step: step,
type: EVENTS.TOOLTIP
}));
setScope(this.tooltip);
}
if (changedFrom('lifecycle', LIFECYCLE.TOOLTIP, LIFECYCLE.INIT)) {
removeScope();
}
if (changedTo('lifecycle', LIFECYCLE.INIT)) {
delete this.beaconPopper;
delete this.tooltipPopper;
}
}
/**
* Beacon click/hover event listener
*
* @param {Event} e
*/
}, {
key: 'render',
value: function render() {
var _props4 = this.props,
continuous = _props4.continuous,
controlled = _props4.controlled,
debug = _props4.debug,
helpers = _props4.helpers,
index = _props4.index,
lifecycle = _props4.lifecycle,
size = _props4.size,
step = _props4.step;
var target = getElement(step.target);
if (!validateStep(step) || !is.domElement(target)) {
return null;
}
return React.createElement(
'div',
{ key: 'JoyrideStep-' + index, className: 'joyride-step' },
React.createElement(
JoyridePortal,
null,
React.createElement(Overlay, _extends({}, step, {
lifecycle: lifecycle,
onClickOverlay: this.handleClickOverlay
}))
),
React.createElement(
Floater,
_extends({
component: React.createElement(JoyrideTooltip, {
continuous: continuous,
controlled: controlled,
helpers: helpers,
index: index,
setTooltipRef: this.setTooltipRef,
size: size,
isLastStep: index + 1 === size,
step: step
}),
debug: debug,
getPopper: this.setPopper,
id: 'react-joyride:' + index,
isPositioned: step.isFixed || isFixed(target),
open: this.open,
placement: step.placement,
target: step.target
}, step.floaterProps),
React.createElement(JoyrideBeacon, {
beaconComponent: step.beaconComponent,
locale: step.locale,
onClickOrHover: this.handleClickHoverBeacon,
styles: step.styles
})
)
);
}
}, {
key: 'open',
get: function get$$1() {
var _props5 = this.props,
step = _props5.step,
lifecycle = _props5.lifecycle;
return !!(step.disableBeacon || lifecycle === LIFECYCLE.TOOLTIP);
}
}]);
return JoyrideStep;
}(React.Component);
JoyrideStep.propTypes = {
action: PropTypes.string.isRequired,
callback: PropTypes.func.isRequired,
continuous: PropTypes.bool.isRequired,
controlled: PropTypes.bool.isRequired,
debug: PropTypes.bool.isRequired,
getPopper: PropTypes.func.isRequired,
helpers: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
lifecycle: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
status: PropTypes.string.isRequired,
step: PropTypes.shape({
beaconComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
content: isRequiredIf(PropTypes.node, function (props) {
return !props.tooltipComponent && !props.title;
}),
disableBeacon: PropTypes.bool,
disableOverlay: PropTypes.bool,
disableOverlayClose: PropTypes.bool,
event: PropTypes.string,
floaterProps: PropTypes.shape({
offset: PropTypes.number
}),
hideBackButton: PropTypes.bool,
isFixed: PropTypes.bool,
locale: PropTypes.object,
offset: PropTypes.number.isRequired,
placement: PropTypes.oneOf(['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end', 'auto', 'center']),
spotlightClicks: PropTypes.bool,
spotlightPadding: PropTypes.number,
styles: PropTypes.object,
target: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
title: PropTypes.node,
tooltipComponent: isRequiredIf(PropTypes.oneOfType([PropTypes.func, PropTypes.element]), function (props) {
return !props.content && !props.title;
})
}).isRequired,
update: PropTypes.func.isRequired
};
var Joyride = function (_React$Component) {
inherits(Joyride, _React$Component);
function Joyride(props) {
classCallCheck(this, Joyride);
var _this = possibleConstructorReturn(this, (Joyride.__proto__ || Object.getPrototypeOf(Joyride)).call(this, props));
_this.callback = function (data) {
var callback = _this.props.callback;
/* istanbul ignore else */
if (is.function(callback)) {
callback(data);
}
};
_this.handleKeyboard = function (e) {
var _this$state = _this.state,
index = _this$state.index,
lifecycle = _this$state.lifecycle;
var steps = _this.props.steps;
var step = steps[index];
var intKey = window.Event ? e.which : e.keyCode;
if (lifecycle === LIFECYCLE.TOOLTIP) {
if (intKey === 27 && step && !step.disableCloseOnEsc) {
_this.store.close();
}
}
};
_this.syncState = function (state) {
_this.setState(state);
};
_this.getPopper = function (popper, type) {
if (type === 'wrapper') {
_this.beaconPopper = popper;
} else {
_this.tooltipPopper = popper;
}
};
_this.store = new createStore(_extends({}, props, {
controlled: props.run && is.number(props.stepIndex)
}));
_this.state = _this.store.getState();
_this.helpers = _this.store.getHelpers();
return _this;
}
createClass(Joyride, [{
key: 'componentDidMount',
value: function componentDidMount() {
if (!canUseDOM) return;
var _props = this.props,
debug = _props.debug,
disableCloseOnEsc = _props.disableCloseOnEsc,
run = _props.run,
steps = _props.steps;
var start = this.store.start;
log({
title: 'init',
data: [{ key: 'props', value: this.props }, { key: 'state', value: this.state }],
debug: debug
});
// Sync the store to this component state.
this.store.addListener(this.syncState);
if (validateSteps(steps, debug) && run) {
start();
}
/* istanbul ignore else */
if (!disableCloseOnEsc) {
document.body.addEventListener('keydown', this.handleKeyboard, { passive: true });
}
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
if (!canUseDOM) return;
var _state = this.state,
action = _state.action,
status = _state.status;
var _props2 = this.props,
steps = _props2.steps,
stepIndex = _props2.stepIndex;
var debug = nextProps.debug,
run = nextProps.run,
nextSteps = nextProps.steps,
nextStepIndex = nextProps.stepIndex;
var _store = this.store,
setSteps = _store.setSteps,
start = _store.start,
stop = _store.stop,
update = _store.update;
var diffProps = !isEqual(this.props, nextProps);
var _treeChanges = treeChanges(this.props, nextProps),
changed = _treeChanges.changed;
if (diffProps) {
log({
title: 'props',
data: [{ key: 'nextProps', value: nextProps }, { key: 'props', value: this.props }],
debug: debug
});
var stepsChanged = !isEqual(nextSteps, steps);
var stepIndexChanged = is.number(nextStepIndex) && changed('stepIndex');
/* istanbul ignore else */
if (changed('run')) {
if (run) {
start(nextStepIndex);
} else {
stop();
}
}
if (stepsChanged) {
if (validateSteps(nextSteps, debug)) {
setSteps(nextSteps);
} else {
console.warn('Steps are not valid', nextSteps); //eslint-disable-line no-console
}
}
/* istanbul ignore else */
if (stepIndexChanged) {
var nextAction = stepIndex < nextStepIndex ? ACTIONS.NEXT : ACTIONS.PREV;
if (action === ACTIONS.STOP) {
nextAction = ACTIONS.START;
}
if (!([STATUS.FINISHED, STATUS.SKIPPED].indexOf(status) !== -1)) {
update({
action: action === ACTIONS.CLOSE ? ACTIONS.CLOSE : nextAction,
index: nextStepIndex,
lifecycle: LIFECYCLE.INIT
});
}
}
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps, prevState) {
if (!canUseDOM) return;
var _state2 = this.state,
index = _state2.index,
lifecycle = _state2.lifecycle,
status = _state2.status;
var _props3 = this.props,
debug = _props3.debug,
steps = _props3.steps;
var _treeChanges2 = treeChanges(prevState, this.state),
changed = _treeChanges2.changed,
changedFrom = _treeChanges2.changedFrom,
changedTo = _treeChanges2.changedTo;
var diffState = !isEqual(prevState, this.state);
var step = getMergedStep(steps[index], this.props);
if (diffState) {
log({
title: 'state',
data: [{ key: 'state', value: this.state }, { key: 'changed', value: diffState }, { key: 'step', value: step }],
debug: debug
});
var currentIndex = index;
if (changed('status')) {
var type = EVENTS.TOUR_STATUS;
if (changedTo('status', STATUS.FINISHED) || changedTo('status', STATUS.SKIPPED)) {
type = EVENTS.TOUR_END;
// Return the last step when the tour is finished
step = getMergedStep(steps[prevState.index], this.props);
currentIndex = prevState.index;
} else if (changedFrom('status', STATUS.READY, STATUS.RUNNING)) {
type = EVENTS.TOUR_START;
}
this.callback(_extends({}, this.state, {
index: currentIndex,
step: step,
type: type
}));
}
if (step) {
this.scrollToStep(prevState);
if (step.placement === 'center' && status === STATUS.RUNNING && lifecycle === LIFECYCLE.INIT) {
this.store.update({ lifecycle: LIFECYCLE.READY });
}
}
if (changedTo('lifecycle', LIFECYCLE.INIT)) {
delete this.beaconPopper;
delete this.tooltipPopper;
}
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var disableCloseOnEsc = this.props.disableCloseOnEsc;
/* istanbul ignore else */
if (!disableCloseOnEsc) {
document.body.removeEventListener('keydown', this.handleKeyboard);
}
}
}, {
key: 'scrollToStep',
value: function scrollToStep(prevState) {
var _state3 = this.state,
index = _state3.index,
lifecycle = _state3.lifecycle,
status = _state3.status;
var _props4 = this.props,
debug = _props4.debug,
disableScrolling = _props4.disableScrolling,
scrollToFirstStep = _props4.scrollToFirstStep,
scrollOffset = _props4.scrollOffset,
steps = _props4.steps;
var step = getMergedStep(steps[index], this.props);
if (step) {
var target = getElement(step.target);
var shouldScroll = step && !disableScrolling && (!step.isFixed || !isFixed(target)) // fixed steps don't need to scroll
&& prevState.lifecycle !== lifecycle && [LIFECYCLE.BEACON, LIFECYCLE.TOOLTIP].indexOf(lifecycle) !== -1 && (scrollToFirstStep || prevState.index !== index);
if (status === STATUS.RUNNING && shouldScroll) {
var hasCustomScroll = hasCustomScrollParent(target);
var scrollParent = getScrollParent(target);
var scrollY = Math.floor(getScrollTo(target, scrollOffset));
log({
title: 'scrollToStep',
data: [{ key: 'index', value: index }, { key: 'lifecycle', value: lifecycle }, { key: 'status', value: status }],
debug: debug
});
if (lifecycle === LIFECYCLE.BEACON && this.beaconPopper) {
var _beaconPopper = this.beaconPopper,
placement = _beaconPopper.placement,
popper = _beaconPopper.popper;
if (!(['bottom'].indexOf(placement) !== -1) && !hasCustomScroll) {
scrollY = Math.floor(popper.top - scrollOffset);
}
} else if (lifecycle === LIFECYCLE.TOOLTIP && this.tooltipPopper) {
var _tooltipPopper = this.tooltipPopper,
flipped = _tooltipPopper.flipped,
_placement = _tooltipPopper.placement,
_popper = _tooltipPopper.popper;
if (['top', 'right'].indexOf(_placement) !== -1 && !flipped && !hasCustomScroll) {
scrollY = Math.floor(_popper.top - scrollOffset);
} else {
scrollY -= step.spotlightPadding;
}
}
if (status === STATUS.RUNNING && shouldScroll && scrollY >= 0) {
scrollTo(scrollY, scrollParent);
}
}
}
}
/**
* Trigger the callback.
*
* @private
* @param {Object} data
*/
/**
* Keydown event listener
*
* @private
* @param {Event} e - Keyboard event
*/
/**
* Sync the store with the component's state
*
* @param {Object} state
*/
}, {
key: 'render',
value: function render() {
if (!canUseDOM) return null;
var _state4 = this.state,
index = _state4.index,
status = _state4.status;
var _props5 = this.props,
continuous = _props5.continuous,
debug = _props5.debug,
disableScrolling = _props5.disableScrolling,
steps = _props5.steps;
var step = getMergedStep(steps[index], this.props);
var output = void 0;
if (status === STATUS.RUNNING && step) {
output = React.createElement(JoyrideStep, _extends({}, this.state, {
callback: this.callback,
continuous: continuous,
debug: debug,
disableScrolling: disableScrolling,
getPopper: this.getPopper,
helpers: this.helpers,
step: step,
update: this.store.update
}));
}
return React.createElement(
'div',
{ className: 'joyride' },
output
);
}
}]);
return Joyride;
}(React.Component);
Joyride.propTypes = {
beaconComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
callback: PropTypes.func,
continuous: PropTypes.bool,
debug: PropTypes.bool,
disableCloseOnEsc: PropTypes.bool,
disableOverlay: PropTypes.bool,
disableOverlayClose: PropTypes.bool,
disableScrolling: PropTypes.bool,
floaterProps: PropTypes.shape({
offset: PropTypes.number
}),
hideBackButton: PropTypes.bool,
locale: PropTypes.object,
run: PropTypes.bool,
scrollOffset: PropTypes.number,
scrollToFirstStep: PropTypes.bool,
showProgress: PropTypes.bool,
showSkipButton: PropTypes.bool,
spotlightClicks: PropTypes.bool,
spotlightPadding: PropTypes.number,
stepIndex: PropTypes.number,
steps: PropTypes.array,
styles: PropTypes.object,
tooltipComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element])
};
Joyride.defaultProps = {
continuous: false,
debug: false,
disableCloseOnEsc: false,
disableOverlay: false,
disableOverlayClose: false,
disableScrolling: false,
hideBackButton: false,
run: true,
scrollOffset: 20,
scrollToFirstStep: false,
showSkipButton: false,
showProgress: false,
spotlightClicks: false,
spotlightPadding: 10,
steps: []
};
export default Joyride;
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var ReactDOM = _interopDefault(require('react-dom'));
var ExecutionEnvironment = _interopDefault(require('exenv'));
var is = _interopDefault(require('is-lite'));
var scroll = _interopDefault(require('scroll'));
var scrollDoc = _interopDefault(require('scroll-doc'));
var getScrollParent = _interopDefault(require('scrollparent'));
var deepmerge = _interopDefault(require('deepmerge'));
var React = _interopDefault(require('react'));
var PropTypes = _interopDefault(require('prop-types'));
var treeChanges = _interopDefault(require('tree-changes'));
var isRequiredIf = _interopDefault(require('react-proptype-conditional-require'));
var Floater = _interopDefault(require('react-floater'));
var STATUS = {
IDLE: 'idle',
READY: 'ready',
WAITING: 'waiting',
RUNNING: 'running',
PAUSED: 'paused',
SKIPPED: 'skipped',
FINISHED: 'finished',
ERROR: 'error'
};
var ACTIONS = {
INIT: 'init',
START: 'start',
STOP: 'stop',
RESET: 'reset',
RESTART: 'restart',
PREV: 'prev',
NEXT: 'next',
GO: 'go',
INDEX: 'index',
CLOSE: 'close',
SKIP: 'skip',
UPDATE: 'update'
};
var LIFECYCLE = {
INIT: 'init',
READY: 'ready',
BEACON: 'beacon',
TOOLTIP: 'tooltip',
COMPLETE: 'complete',
ERROR: 'error'
};
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var canUseDOM = ExecutionEnvironment.canUseDOM;
var isReact16 = ReactDOM.createPortal !== undefined;
/**
* Convert hex to RGB
*
* @param {string} hex
* @returns {Array}
*/
function hexToRGB(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
var properHex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(properHex);
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null;
}
/**
* Get the current browser
*
* @returns {String}
*/
function getBrowser() {
/* istanbul ignore if */
if (typeof window === 'undefined') {
return 'node';
}
if (document.documentMode) {
return 'ie';
}
if (/Edge/.test(navigator.userAgent)) {
return 'edge';
}
// Opera 8.0+
if (Boolean(window.opera) || navigator.userAgent.indexOf(' OPR/') >= 0) {
return 'opera';
}
// Firefox 1.0+
if (typeof window.InstallTrigger !== 'undefined') {
return 'firefox';
}
// Chrome 1+
if (window.chrome) {
return 'chrome';
}
// Safari (and Chrome iOS, Firefox iOS)
if (/(Version\/([0-9._]+).*Safari|CriOS|FxiOS| Mobile\/)/.test(navigator.userAgent)) {
return 'safari';
}
return navigator.userAgent;
}
/**
* Detect legacy browsers
*
* @returns {boolean}
*/
function isLegacy() {
return !(['chrome', 'safari', 'firefox', 'opera'].indexOf(getBrowser()) !== -1);
}
/**
* Log method calls if debug is enabled
*
* @private
* @param {Object} arg
* @param {string} arg.title - The title the logger was called from
* @param {Object|Array} [arg.data] - The data to be logged
* @param {boolean} [arg.warn] - If true, the message will be a warning
* @param {boolean} [arg.debug] - Nothing will be logged unless debug is true
*/
function log(_ref) {
var title = _ref.title,
data = _ref.data,
_ref$warn = _ref.warn,
warn = _ref$warn === undefined ? false : _ref$warn,
_ref$debug = _ref.debug,
debug = _ref$debug === undefined ? false : _ref$debug;
/* eslint-disable no-console */
var logFn = warn ? console.warn || console.error : console.log;
if (debug && title && data) {
console.groupCollapsed('%creact-joyride: ' + title, 'color: #ff0044; font-weight: bold; font-size: 12px;');
if (Array.isArray(data)) {
data.forEach(function (d) {
if (is.plainObject(d) && d.key) {
logFn.apply(console, [d.key, d.value]);
} else {
logFn.apply(console, [d]);
}
});
} else {
logFn.apply(console, [data]);
}
console.groupEnd();
}
/* eslint-enable */
}
function hasValidKeys(value, keys) {
if (!is.plainObject(value) || !is.array(keys)) {
return false;
}
var validKeys = keys;
if (is.string(keys)) {
validKeys = [keys];
}
return Object.keys(value).every(function (d) {
return validKeys.indexOf(d) !== -1;
});
}
function isEqual(a, b) {
var p = void 0;
var t = void 0;
for (p in a) {
if (Object.prototype.hasOwnProperty.call(a, p)) {
if (typeof b[p] === 'undefined') {
return false;
}
if (b[p] && !a[p]) {
return false;
}
t = _typeof(a[p]);
if (t === 'object' && !isEqual(a[p], b[p])) {
return false;
}
if (t === 'function' && (typeof b[p] === 'undefined' || a[p].toString() !== b[p].toString())) {
return false;
}
if (a[p] !== b[p]) {
return false;
}
}
}
for (p in b) {
if (typeof a[p] === 'undefined') {
return false;
}
}
return true;
}
var defaultState = {
action: '',
controlled: false,
index: 0,
lifecycle: LIFECYCLE.INIT,
size: 0,
status: STATUS.IDLE
};
var validKeys = ['action', 'index', 'lifecycle', 'status'];
function createStore(props) {
var store = new Map();
var data = new Map();
var Store = function () {
function Store() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$continuous = _ref.continuous,
continuous = _ref$continuous === undefined ? false : _ref$continuous,
stepIndex = _ref.stepIndex,
_ref$steps = _ref.steps,
steps = _ref$steps === undefined ? [] : _ref$steps;
classCallCheck(this, Store);
_initialiseProps.call(this);
this.setState({
action: ACTIONS.INIT,
controlled: is.number(stepIndex),
continuous: continuous,
index: is.number(stepIndex) ? stepIndex : 0,
lifecycle: LIFECYCLE.INIT,
status: steps.length ? STATUS.READY : STATUS.IDLE
}, true);
this.setSteps(steps);
}
createClass(Store, [{
key: 'addListener',
value: function addListener(listener) {
this.listener = listener;
}
}, {
key: 'setState',
value: function setState(nextState) {
var initial = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var state = this.getState();
var _state$nextState = _extends({}, state, nextState),
action = _state$nextState.action,
index = _state$nextState.index,
lifecycle = _state$nextState.lifecycle,
status = _state$nextState.status;
store.set('action', action);
store.set('index', index);
store.set('lifecycle', lifecycle);
store.set('status', status);
if (initial) {
store.set('controlled', nextState.controlled);
store.set('continuous', nextState.continuous);
}
/* istanbul ignore else */
if (this.listener && this.hasUpdatedState(state)) {
// console.log('▶ ▶ ▶ NEW STATE', this.getState());
this.listener(this.getState());
}
}
}, {
key: 'getState',
value: function getState() {
if (!store.size) {
return _extends({}, defaultState);
}
var index = parseInt(store.get('index'), 10);
var steps = this.getSteps();
var size = steps.length;
return {
action: store.get('action'),
controlled: store.get('controlled'),
index: index,
lifecycle: store.get('lifecycle'),
size: size,
status: store.get('status')
};
}
}, {
key: 'getNextState',
value: function getNextState(state) {
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var _getState = this.getState(),
action = _getState.action,
controlled = _getState.controlled,
index = _getState.index,
size = _getState.size,
status = _getState.status;
var newIndex = is.number(state.index) ? state.index : index;
var nextIndex = controlled && !force ? index : Math.min(Math.max(newIndex, 0), size);
return {
action: state.action || action,
index: nextIndex,
lifecycle: state.lifecycle || LIFECYCLE.INIT,
status: nextIndex === size ? STATUS.FINISHED : state.status || status
};
}
}, {
key: 'hasUpdatedState',
value: function hasUpdatedState(oldState) {
var before = JSON.stringify(oldState);
var after = JSON.stringify(this.getState());
return before !== after;
}
}, {
key: 'getSteps',
value: function getSteps() {
var steps = data.get('steps');
return Array.isArray(steps) ? steps : [];
}
}, {
key: 'getHelpers',
value: function getHelpers() {
return {
start: this.start,
stop: this.stop,
restart: this.restart,
reset: this.reset,
prev: this.prev,
next: this.next,
go: this.go,
index: this.index,
close: this.close,
skip: this.skip,
info: this.info
};
}
}]);
return Store;
}();
var _initialiseProps = function _initialiseProps() {
var _this = this;
this.setSteps = function (steps) {
var _getState2 = _this.getState(),
size = _getState2.size,
status = _getState2.status;
data.set('steps', steps);
if (status === STATUS.WAITING && !size && steps.length) {
_this.setState({ status: STATUS.RUNNING });
}
};
this.update = function (state) {
if (!hasValidKeys(state, validKeys)) {
throw new Error('state is not valid');
}
_this.setState(_extends({}, _this.getNextState(_extends({}, _this.getState(), state, {
action: state.action || ACTIONS.UPDATE
}), true)));
};
this.steps = function (nextSteps) {
if (!is.array(nextSteps)) return;
_this.setSteps(nextSteps);
};
this.start = function (nextIndex) {
var _getState3 = _this.getState(),
index = _getState3.index,
size = _getState3.size;
_this.setState(_extends({}, _this.getNextState({
action: ACTIONS.START,
index: is.number(nextIndex) ? nextIndex : index
}, true), {
status: size ? STATUS.RUNNING : STATUS.WAITING
}));
};
this.stop = function () {
var advance = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var _getState4 = _this.getState(),
index = _getState4.index,
status = _getState4.status;
if ([STATUS.FINISHED, STATUS.SKIPPED].indexOf(status) !== -1) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }), {
status: STATUS.PAUSED
}));
};
this.restart = function () {
var _getState5 = _this.getState(),
controlled = _getState5.controlled;
if (controlled) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.RESTART, index: 0 }), {
status: STATUS.RUNNING
}));
};
this.reset = function () {
var _getState6 = _this.getState(),
controlled = _getState6.controlled;
if (controlled) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.RESET, index: 0 }), {
status: STATUS.READY
}));
};
this.prev = function () {
var _getState7 = _this.getState(),
index = _getState7.index,
status = _getState7.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.PREV, index: index - 1 })));
};
this.next = function () {
var _getState8 = _this.getState(),
index = _getState8.index,
status = _getState8.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_this.getNextState({ action: ACTIONS.NEXT, index: index + 1 }));
};
this.go = function (number) {
var _getState9 = _this.getState(),
index = _getState9.index,
status = _getState9.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.GO, index: index + number })));
};
this.index = function (nextIndex) {
var _getState10 = _this.getState(),
status = _getState10.status;
if (status !== STATUS.RUNNING) return;
var step = _this.getSteps()[nextIndex];
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.INDEX, index: nextIndex }), {
status: step ? status : STATUS.FINISHED
}));
};
this.close = function () {
var _getState11 = _this.getState(),
index = _getState11.index,
status = _getState11.status;
if (status !== STATUS.RUNNING) return;
_this.setState(_extends({}, _this.getNextState({ action: ACTIONS.CLOSE, index: index + 1 })));
};
this.skip = function () {
var _getState12 = _this.getState(),
status = _getState12.status;
if (status !== STATUS.RUNNING) return;
_this.setState({
action: ACTIONS.SKIP,
lifecycle: LIFECYCLE.INIT,
status: STATUS.SKIPPED
});
};
this.info = function () {
return _this.getState();
};
};
return new Store(props);
}
/**
* Find the bounding client rect
*
* @private
* @param {HTMLElement} element - The target element
* @returns {Object}
*/
function getClientRect(element) {
if (!element) {
return {};
}
return element.getBoundingClientRect();
}
/**
* Helper function to get the browser-normalized "document height"
* @returns {Number}
*/
function getDocumentHeight() {
var _document = document,
body = _document.body,
html = _document.documentElement;
if (!body || !html) {
return 0;
}
return Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
}
function getStyleComputedProperty(el) {
if (!el || el.nodeType !== 1) {
return {};
}
return getComputedStyle(el);
}
function hasCustomScrollParent(element) {
if (!element) {
return false;
}
return getScrollParent(element) !== scrollDoc();
}
function hasCustomOffsetParent(element) {
return element.offsetParent !== document.body;
}
function isFixed(el) {
if (!el || !(el instanceof HTMLElement)) {
return false;
}
var nodeName = el.nodeName;
if (nodeName === 'BODY' || nodeName === 'HTML') {
return false;
}
if (getStyleComputedProperty(el).position === 'fixed') {
return true;
}
return isFixed(el.parentNode);
}
/**
* Get the scrollTop position
*
* @param {HTMLElement} element
* @param {number} offset
*
* @returns {number}
*/
function getScrollTo(element, offset) {
if (!element) {
return 0;
}
var parent = getScrollParent(element);
var top = element.offsetTop;
if (hasCustomScrollParent(element) && !hasCustomOffsetParent(element)) {
top -= parent.offsetTop;
}
return Math.floor(top - offset);
}
/**
* Find and return the target DOM element based on a step's 'target'.
*
* @private
* @param {string|HTMLElement} element
*
* @returns {HTMLElement|undefined}
*/
function getElement(element) {
if (typeof element !== 'string') {
return element;
}
return element ? document.querySelector(element) : null;
}
/**
* Find and return the target DOM element based on a step's 'target'.
*
* @private
* @param {string|HTMLElement} element
* @param {number} offset
*
* @returns {HTMLElement|undefined}
*/
function getElementPosition(element, offset) {
var elementRect = getClientRect(element);
var scrollParent = getScrollParent(element);
var hasScrollParent = hasCustomScrollParent(element);
var top = elementRect.top + (!hasScrollParent && !isFixed(element) ? scrollParent.scrollTop : 0);
return Math.floor(top - offset);
}
function scrollTo(value) {
var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scrollDoc();
return new Promise(function (resolve, reject) {
var scrollTop = element.scrollTop;
var limit = value > scrollTop ? value - scrollTop : scrollTop - value;
scroll.top(element, value, { duration: limit < 100 ? 50 : 300 }, function (error) {
if (error && error.message !== 'Element already at target scroll position') {
return reject(error);
}
return resolve();
});
});
}
var defaultOptions = {
arrowColor: '#fff',
backgroundColor: '#fff',
beaconSize: 36,
overlayColor: 'rgba(0, 0, 0, 0.5)',
primaryColor: '#f04',
spotlightShadow: '0 0 15px rgba(0, 0, 0, 0.5)',
textColor: '#333',
zIndex: 100
};
var buttonReset = {
backgroundColor: 'transparent',
border: 0,
borderRadius: 0,
color: '#555',
cursor: 'pointer',
lineHeight: 1,
padding: 8,
WebkitAppearance: 'none'
};
var spotlight = {
borderRadius: 4,
position: 'absolute'
};
function getStyles(stepStyles) {
var options = deepmerge(defaultOptions, stepStyles.options || {});
var width = 290;
if (window.innerWidth > 480) {
width = 380;
} else if (window.innerWidth > 768) {
width = 490;
}
if (options.width) {
if (window.innerWidth < options.width) {
width = window.innerWidth - 30;
} else {
width = options.width; //eslint-disable-line prefer-destructuring
}
}
var overlay = {
bottom: 0,
left: 0,
overflow: 'hidden',
position: 'absolute',
right: 0,
top: 0,
zIndex: options.zIndex
};
var defaultStyles = {
beacon: _extends({}, buttonReset, {
display: 'inline-block',
height: options.beaconSize,
position: 'relative',
width: options.beaconSize,
zIndex: options.zIndex
}),
beaconInner: {
animation: 'joyride-beacon-inner 1.2s infinite ease-in-out',
backgroundColor: options.primaryColor,
borderRadius: '50%',
display: 'block',
height: '50%',
left: '50%',
opacity: 0.7,
position: 'absolute',
top: '50%',
transform: 'translate(-50%, -50%)',
width: '50%'
},
beaconOuter: {
animation: 'joyride-beacon-outer 1.2s infinite ease-in-out',
backgroundColor: 'rgba(' + hexToRGB(options.primaryColor).join(',') + ', 0.2)',
border: '2px solid ' + options.primaryColor,
borderRadius: '50%',
boxSizing: 'border-box',
display: 'block',
height: '100%',
left: 0,
opacity: 0.9,
position: 'absolute',
top: 0,
transformOrigin: 'center',
width: '100%'
},
tooltip: {
backgroundColor: options.backgroundColor,
borderRadius: 5,
boxSizing: 'border-box',
color: options.textColor,
fontSize: 16,
maxWidth: '100%',
padding: 15,
position: 'relative',
width: width
},
tooltipContainer: {
lineHeight: 1.4,
textAlign: 'center'
},
tooltipTitle: {
fontSize: 18,
margin: '0 0 10px 0'
},
tooltipContent: {
padding: '20px 10px'
},
tooltipFooter: {
alignItems: 'center',
display: 'flex',
justifyContent: 'space-between',
marginTop: 15
},
buttonNext: _extends({}, buttonReset, {
backgroundColor: options.primaryColor,
borderRadius: 4,
color: '#fff'
}),
buttonBack: _extends({}, buttonReset, {
color: options.primaryColor,
marginLeft: 'auto',
marginRight: 5
}),
buttonClose: _extends({}, buttonReset, {
color: options.textColor,
height: 14,
padding: 15,
position: 'absolute',
right: 0,
top: 0,
width: 14
}),
buttonSkip: _extends({}, buttonReset, {
color: options.textColor,
fontSize: 14
}),
overlay: _extends({}, overlay, {
backgroundColor: options.overlayColor,
mixBlendMode: 'hard-light'
}),
overlayLegacy: _extends({}, overlay),
spotlight: _extends({}, spotlight, {
backgroundColor: 'gray'
}),
spotlightLegacy: _extends({}, spotlight, {
boxShadow: '0 0 0 9999px ' + options.overlayColor + ', ' + options.spotlightShadow
}),
floaterStyles: {
arrow: {
color: options.arrowColor
},
floater: {
zIndex: options.zIndex
}
},
options: options
};
return deepmerge(defaultStyles, stepStyles || {});
}
var DEFAULTS = {
floaterProps: {
options: {
preventOverflow: {
boundariesElement: 'scrollParent'
}
},
wrapperOptions: {
offset: -18,
position: true
}
},
locale: {
back: 'Back',
close: 'Close',
last: 'Last',
next: 'Next',
open: 'Open',
skip: 'Skip'
},
step: {
event: 'click',
placement: 'bottom',
offset: 10
}
};
/**
* Validate if a step is valid
*
* @param {Object} step - A step object
* @param {boolean} debug
*
* @returns {boolean} - True if the step is valid, false otherwise
*/
function validateStep(step) {
var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (!is.plainObject(step)) {
log({
title: 'validateStep',
data: 'step must be an object',
warn: true,
debug: debug
});
return false;
}
if (!step.target) {
log({
title: 'validateStep',
data: 'target is missing from the step',
warn: true,
debug: debug
});
return false;
}
return true;
}
/**
* Validate if steps is valid
*
* @param {Array} steps - A steps array
* @param {boolean} debug
*
* @returns {boolean} - True if the steps are valid, false otherwise
*/
function validateSteps(steps) {
var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (!is.array(steps)) {
log({
title: 'validateSteps',
data: 'steps must be an array',
warn: true,
debug: debug
});
return false;
}
return steps.every(function (d) {
return validateStep(d, debug);
});
}
function getTourProps(props) {
var sharedTourProps = ['beaconComponent', 'disableCloseOnEsc', 'disableOverlay', 'disableOverlayClose', 'disableScrolling', 'floaterProps', 'hideBackButton', 'locale', 'showProgress', 'showSkipButton', 'spotlightClicks', 'spotlightPadding', 'styles', 'tooltipComponent'];
return Object.keys(props).filter(function (d) {
return sharedTourProps.indexOf(d) !== -1;
}).reduce(function (acc, i) {
acc[i] = props[i]; //eslint-disable-line react/destructuring-assignment
return acc;
}, {});
}
function getMergedStep(step, props) {
if (!step) return undefined;
var mergedStep = deepmerge.all([getTourProps(props), DEFAULTS.step, step]);
var mergedStyles = getStyles(deepmerge(props.styles || {}, step.styles || {}));
var scrollParent = hasCustomScrollParent(getElement(step.target));
var floaterProps = deepmerge.all([props.floaterProps || {}, DEFAULTS.floaterProps, mergedStep.floaterProps || {}]);
// Set react-floater props
floaterProps.offset = mergedStep.offset;
floaterProps.styles = deepmerge(floaterProps.styles || {}, mergedStyles.floaterStyles || {});
delete mergedStyles.floaterStyles;
if (mergedStep.floaterProps && mergedStep.floaterProps.offset) {
floaterProps.offset = mergedStep.floaterProps.offset;
}
if (!mergedStep.disableScrolling) {
floaterProps.offset += props.spotlightPadding || step.spotlightPadding || 0;
}
if (step.placementBeacon) {
floaterProps.wrapperOptions.placement = step.placementBeacon;
}
if (scrollParent) {
floaterProps.options.preventOverflow.boundariesElement = 'window';
}
return _extends({}, mergedStep, {
locale: deepmerge.all([DEFAULTS.locale, props.locale || {}, mergedStep.locale || {}]),
floaterProps: floaterProps,
styles: mergedStyles
});
}
var EVENTS = {
TOUR_START: 'tour:start',
STEP_BEFORE: 'step:before',
BEACON: 'beacon',
TOOLTIP: 'tooltip',
TOOLTIP_CLOSE: 'close',
STEP_AFTER: 'step:after',
TOUR_END: 'tour:end',
TOUR_STATUS: 'tour:status',
TARGET_NOT_FOUND: 'error:target_not_found',
ERROR: 'error'
};
var validTabNodes = /input|select|textarea|button|object/;
var TAB_KEY = 9;
var modalElement = null;
function isHidden(element) {
var noSize = element.offsetWidth <= 0 && element.offsetHeight <= 0;
if (noSize && !element.innerHTML) return true;
var style = window.getComputedStyle(element);
return noSize ? style.getPropertyValue('overflow') !== 'visible' : style.getPropertyValue('display') === 'none';
}
function isVisible(element) {
var parentElement = element;
while (parentElement) {
if (parentElement === document.body) break;
if (isHidden(parentElement)) return false;
parentElement = parentElement.parentNode;
}
return true;
}
function canHaveFocus(element, isTabIndexNotNaN) {
var nodeName = element.nodeName.toLowerCase();
var res = validTabNodes.test(nodeName) && !element.disabled || (nodeName === 'a' ? element.href || isTabIndexNotNaN : isTabIndexNotNaN);
return res && isVisible(element);
}
function canBeTabbed(element) {
var tabIndex = element.getAttribute('tabindex');
if (tabIndex === null) tabIndex = undefined;
var isTabIndexNaN = isNaN(tabIndex);
return (isTabIndexNaN || tabIndex >= 0) && canHaveFocus(element, !isTabIndexNaN);
}
function findValidTabElements(element) {
return [].slice.call(element.querySelectorAll('*'), 0).filter(canBeTabbed);
}
function interceptTab(node, event) {
var elements = findValidTabElements(node);
var shiftKey = event.shiftKey;
if (!elements.length) {
event.preventDefault();
return;
}
var x = elements.indexOf(document.activeElement);
if (x === -1 || !shiftKey && x + 1 === elements.length) {
x = 0;
} else {
x += shiftKey ? -1 : 1;
}
event.preventDefault();
elements[x].focus();
}
function handleKeyDown(e) {
if (!modalElement) {
return;
}
if (e.keyCode === TAB_KEY) {
interceptTab(modalElement, e);
}
}
function setScope(element) {
modalElement = element;
window.addEventListener('keydown', handleKeyDown, false);
}
function removeScope() {
modalElement = null;
window.removeEventListener('keydown', handleKeyDown);
}
var JoyrideBeacon = function (_React$Component) {
inherits(JoyrideBeacon, _React$Component);
function JoyrideBeacon(props) {
classCallCheck(this, JoyrideBeacon);
var _this = possibleConstructorReturn(this, (JoyrideBeacon.__proto__ || Object.getPrototypeOf(JoyrideBeacon)).call(this, props));
if (!props.beaconComponent) {
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
var css = '\n@keyframes joyride-beacon-inner {\n 20% {\n opacity: 0.9;\n }\n\n 90% {\n opacity: 0.7;\n }\n}\n\n@keyframes joyride-beacon-outer {\n 0% {\n transform: scale(1);\n }\n\n 45% {\n opacity: 0.7;\n transform: scale(0.75);\n }\n\n 100% {\n opacity: 0.9;\n transform: scale(1);\n }\n}\n ';
style.type = 'text/css';
style.id = 'joyride-beacon-animation';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
}
return _this;
}
createClass(JoyrideBeacon, [{
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var style = document.getElementById('joyride-beacon-animation');
if (style) {
style.parentNode.removeChild(style);
}
}
}, {
key: 'render',
value: function render() {
var _props = this.props,
beaconComponent = _props.beaconComponent,
locale = _props.locale,
onClickOrHover = _props.onClickOrHover,
styles = _props.styles;
var props = {
'aria-label': locale.open,
onClick: onClickOrHover,
onMouseEnter: onClickOrHover,
title: locale.open
};
var component = void 0;
if (beaconComponent) {
if (React.isValidElement(beaconComponent)) {
component = React.cloneElement(beaconComponent, props);
} else {
component = beaconComponent(props);
}
} else {
component = React.createElement(
'button',
_extends({
key: 'JoyrideBeacon',
className: 'joyride-beacon',
style: styles.beacon,
type: 'button'
}, props),
React.createElement('span', { style: styles.beaconInner }),
React.createElement('span', { style: styles.beaconOuter })
);
}
return component;
}
}]);
return JoyrideBeacon;
}(React.Component);
JoyrideBeacon.propTypes = {
beaconComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
locale: PropTypes.object.isRequired,
onClickOrHover: PropTypes.func.isRequired,
styles: PropTypes.object.isRequired
};
var JoyrideSpotlight = function JoyrideSpotlight(_ref) {
var styles = _ref.styles;
return React.createElement('div', {
key: 'JoyrideSpotlight',
className: 'joyride-spotlight',
style: styles
});
};
JoyrideSpotlight.propTypes = {
styles: PropTypes.object.isRequired
};
var Overlay = function (_React$Component) {
inherits(Overlay, _React$Component);
function Overlay(props) {
classCallCheck(this, Overlay);
var _this = possibleConstructorReturn(this, (Overlay.__proto__ || Object.getPrototypeOf(Overlay)).call(this, props));
_this.handleMouseMove = function (e) {
var mouseOverSpotlight = _this.state.mouseOverSpotlight;
var _this$stylesSpotlight = _this.stylesSpotlight,
height = _this$stylesSpotlight.height,
left = _this$stylesSpotlight.left,
position = _this$stylesSpotlight.position,
top = _this$stylesSpotlight.top,
width = _this$stylesSpotlight.width;
var offsetY = position === 'fixed' ? e.clientY : e.pageY;
var offsetX = position === 'fixed' ? e.clientX : e.pageX;
var inSpotlightHeight = offsetY >= top && offsetY <= top + height;
var inSpotlightWidth = offsetX >= left && offsetX <= left + width;
var inSpotlight = inSpotlightWidth && inSpotlightHeight;
if (inSpotlight !== mouseOverSpotlight) {
_this.setState({ mouseOverSpotlight: inSpotlight });
}
};
_this.handleScroll = function () {
var isScrolling = _this.state.isScrolling;
if (!isScrolling) {
_this.setState({ isScrolling: true, showSpotlight: false });
}
clearTimeout(_this.scrollTimeout);
_this.scrollTimeout = setTimeout(function () {
clearTimeout(_this.scrollTimeout);
_this.setState({ isScrolling: false, showSpotlight: true });
_this.scrollParent.removeEventListener('scroll', _this.handleScroll);
}, 50);
};
_this.handleResize = function () {
clearTimeout(_this.resizeTimeout);
_this.resizeTimeout = setTimeout(function () {
clearTimeout(_this.resizeTimeout);
_this.forceUpdate();
}, 100);
};
_this.state = {
mouseOverSpotlight: false,
isScrolling: false,
showSpotlight: props.disableScrolling
};
return _this;
}
createClass(Overlay, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props,
disableScrolling = _props.disableScrolling,
target = _props.target;
if (!disableScrolling) {
var element = getElement(target);
this.scrollParent = hasCustomScrollParent(element) ? getScrollParent(element) : document;
}
window.addEventListener('resize', this.handleResize);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this2 = this;
var disableScrolling = nextProps.disableScrolling,
lifecycle = nextProps.lifecycle,
spotlightClicks = nextProps.spotlightClicks;
var _treeChanges = treeChanges(this.props, nextProps),
changed = _treeChanges.changed,
changedTo = _treeChanges.changedTo;
if (!disableScrolling) {
if (changedTo('lifecycle', LIFECYCLE.TOOLTIP)) {
this.scrollParent.addEventListener('scroll', this.handleScroll, { passive: true });
setTimeout(function () {
var isScrolling = _this2.state.isScrolling;
if (!isScrolling) {
_this2.setState({ showSpotlight: true });
_this2.scrollParent.removeEventListener('scroll', _this2.handleScroll);
}
}, 100);
}
}
if (changed('spotlightClicks') || changed('disableOverlay') || changed('lifecycle')) {
if (spotlightClicks && lifecycle === LIFECYCLE.TOOLTIP) {
window.addEventListener('mousemove', this.handleMouseMove, false);
} else if (lifecycle !== LIFECYCLE.TOOLTIP) {
window.removeEventListener('mousemove', this.handleMouseMove);
}
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var disableScrolling = this.props.disableScrolling;
window.removeEventListener('mousemove', this.handleMouseMove);
window.removeEventListener('resize', this.handleResize);
if (!disableScrolling) {
clearTimeout(this.scrollTimeout);
this.scrollParent.removeEventListener('scroll', this.handleScroll);
}
}
}, {
key: 'render',
value: function render() {
var _state = this.state,
mouseOverSpotlight = _state.mouseOverSpotlight,
showSpotlight = _state.showSpotlight;
var _props2 = this.props,
disableOverlay = _props2.disableOverlay,
lifecycle = _props2.lifecycle,
onClickOverlay = _props2.onClickOverlay,
placement = _props2.placement,
styles = _props2.styles;
if (disableOverlay || lifecycle !== LIFECYCLE.TOOLTIP) {
return null;
}
var stylesOverlay = _extends({
cursor: disableOverlay ? 'default' : 'pointer',
height: getDocumentHeight(),
pointerEvents: mouseOverSpotlight ? 'none' : 'auto'
}, isLegacy() ? styles.overlayLegacy : styles.overlay);
var spotlight = placement !== 'center' && showSpotlight && React.createElement(JoyrideSpotlight, { styles: this.stylesSpotlight });
// Hack for Safari bug with mix-blend-mode with z-index
if (getBrowser() === 'safari') {
var mixBlendMode = stylesOverlay.mixBlendMode,
zIndex = stylesOverlay.zIndex,
safarOverlay = objectWithoutProperties(stylesOverlay, ['mixBlendMode', 'zIndex']);
spotlight = React.createElement(
'div',
{ style: _extends({}, safarOverlay) },
spotlight
);
delete stylesOverlay.backgroundColor;
}
return React.createElement(
'div',
{
className: 'joyride-overlay',
style: stylesOverlay,
onClick: onClickOverlay
},
spotlight
);
}
}, {
key: 'stylesSpotlight',
get: function get$$1() {
var showSpotlight = this.state.showSpotlight;
var _props3 = this.props,
spotlightClicks = _props3.spotlightClicks,
spotlightPadding = _props3.spotlightPadding,
styles = _props3.styles,
target = _props3.target;
var element = getElement(target);
var elementRect = getClientRect(element);
var isFixedTarget = isFixed(element);
var top = getElementPosition(element, spotlightPadding);
return _extends({}, isLegacy() ? styles.spotlightLegacy : styles.spotlight, {
height: Math.round(elementRect.height + spotlightPadding * 2),
left: Math.round(elementRect.left - spotlightPadding),
opacity: showSpotlight ? 1 : 0,
pointerEvents: spotlightClicks ? 'none' : 'auto',
position: isFixedTarget ? 'fixed' : 'absolute',
top: top,
transition: 'opacity 0.2s',
width: Math.round(elementRect.width + spotlightPadding * 2)
});
}
}]);
return Overlay;
}(React.Component);
Overlay.propTypes = {
disableOverlay: PropTypes.bool.isRequired,
disableScrolling: PropTypes.bool.isRequired,
lifecycle: PropTypes.string.isRequired,
onClickOverlay: PropTypes.func.isRequired,
placement: PropTypes.string.isRequired,
spotlightClicks: PropTypes.bool.isRequired,
spotlightPadding: PropTypes.number,
styles: PropTypes.object.isRequired,
target: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired
};
var CloseBtn = function CloseBtn(_ref) {
var styles = _ref.styles,
props = objectWithoutProperties(_ref, ['styles']);
var color = styles.color,
height = styles.height,
width = styles.width,
style = objectWithoutProperties(styles, ['color', 'height', 'width']);
return React.createElement(
'button',
_extends({
style: style,
type: 'button'
}, props),
React.createElement(
'svg',
{
width: typeof width === 'number' ? width + 'px' : width,
height: typeof height === 'number' ? height + 'px' : height,
viewBox: '0 0 18 18',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
preserveAspectRatio: 'xMidYMid'
},
React.createElement(
'g',
null,
React.createElement('path', {
d: 'M8.13911129,9.00268191 L0.171521827,17.0258467 C-0.0498027049,17.248715 -0.0498027049,17.6098394 0.171521827,17.8327545 C0.28204354,17.9443526 0.427188206,17.9998706 0.572051765,17.9998706 C0.71714958,17.9998706 0.862013139,17.9443526 0.972581703,17.8327545 L9.0000937,9.74924618 L17.0276057,17.8327545 C17.1384085,17.9443526 17.2832721,17.9998706 17.4281356,17.9998706 C17.5729992,17.9998706 17.718097,17.9443526 17.8286656,17.8327545 C18.0499901,17.6098862 18.0499901,17.2487618 17.8286656,17.0258467 L9.86135722,9.00268191 L17.8340066,0.973848225 C18.0553311,0.750979934 18.0553311,0.389855532 17.8340066,0.16694039 C17.6126821,-0.0556467968 17.254037,-0.0556467968 17.0329467,0.16694039 L9.00042166,8.25611765 L0.967006424,0.167268345 C0.745681892,-0.0553188426 0.387317931,-0.0553188426 0.165993399,0.167268345 C-0.0553311331,0.390136635 -0.0553311331,0.751261038 0.165993399,0.974176179 L8.13920499,9.00268191 L8.13911129,9.00268191 Z',
fill: color
})
)
)
);
};
CloseBtn.propTypes = {
styles: PropTypes.object.isRequired
};
var JoyrideTooltipContainer = function JoyrideTooltipContainer(_ref) {
var continuous = _ref.continuous,
backProps = _ref.backProps,
closeProps = _ref.closeProps,
primaryProps = _ref.primaryProps,
skipProps = _ref.skipProps,
index = _ref.index,
isLastStep = _ref.isLastStep,
setTooltipRef = _ref.setTooltipRef,
size = _ref.size,
step = _ref.step;
var content = step.content,
hideBackButton = step.hideBackButton,
locale = step.locale,
showProgress = step.showProgress,
showSkipButton = step.showSkipButton,
title = step.title,
styles = step.styles;
var back = locale.back,
close = locale.close,
last = locale.last,
next = locale.next,
skip = locale.skip;
var output = {
primary: close
};
if (continuous) {
if (isLastStep) {
output.primary = last;
} else {
output.primary = next;
}
if (showProgress) {
output.primary += ' (' + (index + 1) + '/' + size + ')';
}
}
if (showSkipButton && !isLastStep) {
output.skip = React.createElement(
'button',
_extends({
style: styles.buttonSkip,
type: 'button'
}, skipProps),
skip
);
}
if (!hideBackButton && index > 0) {
output.back = React.createElement(
'button',
_extends({
style: styles.buttonBack,
type: 'button'
}, backProps),
back
);
}
output.close = React.createElement(CloseBtn, _extends({}, closeProps, { styles: styles.buttonClose }));
return React.createElement(
'div',
{
key: 'JoyrideTooltip',
ref: setTooltipRef,
style: styles.tooltip
},
React.createElement(
'div',
{ style: styles.tooltipContainer },
output.close,
title && React.createElement(
'h4',
{ style: styles.tooltipTitle },
title
),
!!content && React.createElement(
'div',
{ style: styles.tooltipContent },
content
)
),
React.createElement(
'div',
{ style: styles.tooltipFooter },
output.skip,
output.back,
React.createElement(
'button',
_extends({
style: styles.buttonNext,
type: 'button'
}, primaryProps),
output.primary
)
)
);
};
JoyrideTooltipContainer.propTypes = {
backProps: PropTypes.object.isRequired,
closeProps: PropTypes.object.isRequired,
continuous: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,
isLastStep: PropTypes.bool.isRequired,
primaryProps: PropTypes.object.isRequired,
setTooltipRef: PropTypes.func.isRequired,
size: PropTypes.number.isRequired,
skipProps: PropTypes.object.isRequired,
step: PropTypes.object.isRequired
};
var JoyrideTooltip = function (_React$Component) {
inherits(JoyrideTooltip, _React$Component);
function JoyrideTooltip() {
var _ref;
var _temp, _this, _ret;
classCallCheck(this, JoyrideTooltip);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = JoyrideTooltip.__proto__ || Object.getPrototypeOf(JoyrideTooltip)).call.apply(_ref, [this].concat(args))), _this), _this.handleClickBack = function (e) {
e.preventDefault();
var helpers = _this.props.helpers;
helpers.prev();
}, _this.handleClickClose = function (e) {
e.preventDefault();
var helpers = _this.props.helpers;
helpers.close();
}, _this.handleClickPrimary = function (e) {
e.preventDefault();
var _this$props = _this.props,
continuous = _this$props.continuous,
helpers = _this$props.helpers;
if (!continuous) {
helpers.close();
return;
}
helpers.next();
}, _this.handleClickSkip = function (e) {
e.preventDefault();
var helpers = _this.props.helpers;
helpers.skip();
}, _temp), possibleConstructorReturn(_this, _ret);
}
createClass(JoyrideTooltip, [{
key: 'render',
value: function render() {
var _props = this.props,
continuous = _props.continuous,
index = _props.index,
isLastStep = _props.isLastStep,
setTooltipRef = _props.setTooltipRef,
size = _props.size,
step = _props.step;
var content = step.content,
locale = step.locale,
title = step.title,
tooltipComponent = step.tooltipComponent;
var back = locale.back,
close = locale.close,
last = locale.last,
next = locale.next,
skip = locale.skip;
var primaryText = continuous ? next : close;
if (isLastStep) {
primaryText = last;
}
var component = void 0;
var buttonProps = {
backProps: { 'aria-label': back, onClick: this.handleClickBack, role: 'button', title: back },
closeProps: { 'aria-label': close, onClick: this.handleClickClose, role: 'button', title: close },
primaryProps: { 'aria-label': primaryText, onClick: this.handleClickPrimary, role: 'button', title: primaryText },
skipProps: { 'aria-label': skip, onClick: this.handleClickSkip, role: 'button', title: skip }
};
if (tooltipComponent) {
var renderProps = _extends({}, buttonProps, {
content: content,
continuous: continuous,
index: index,
isLastStep: isLastStep,
locale: locale,
setTooltipRef: setTooltipRef,
size: size,
title: title
});
if (React.isValidElement(tooltipComponent)) {
component = React.cloneElement(tooltipComponent, renderProps);
} else {
component = tooltipComponent(renderProps);
}
} else {
component = React.createElement(JoyrideTooltipContainer, _extends({
continuous: continuous,
index: index,
isLastStep: isLastStep,
setTooltipRef: setTooltipRef,
size: size,
step: step
}, buttonProps));
}
return component;
}
}]);
return JoyrideTooltip;
}(React.Component);
JoyrideTooltip.propTypes = {
continuous: PropTypes.bool.isRequired,
helpers: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
isLastStep: PropTypes.bool.isRequired,
setTooltipRef: PropTypes.func.isRequired,
size: PropTypes.number.isRequired,
step: PropTypes.object.isRequired
};
var JoyridePortal = function (_React$Component) {
inherits(JoyridePortal, _React$Component);
function JoyridePortal(props) {
classCallCheck(this, JoyridePortal);
var _this = possibleConstructorReturn(this, (JoyridePortal.__proto__ || Object.getPrototypeOf(JoyridePortal)).call(this, props));
if (!canUseDOM) return possibleConstructorReturn(_this);
_this.node = document.createElement('div');
if (props.id) {
_this.node.id = props.id;
}
document.body.appendChild(_this.node);
return _this;
}
createClass(JoyridePortal, [{
key: 'componentDidMount',
value: function componentDidMount() {
if (!canUseDOM) return;
if (!isReact16) {
this.renderReact15();
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
if (!canUseDOM) return;
if (!isReact16) {
this.renderReact15();
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
if (!canUseDOM || !this.node) return;
if (!isReact16) {
ReactDOM.unmountComponentAtNode(this.node);
}
document.body.removeChild(this.node);
}
}, {
key: 'renderReact15',
value: function renderReact15() {
if (!canUseDOM) return null;
var children = this.props.children;
ReactDOM.unstable_renderSubtreeIntoContainer(this, children, this.node);
return null;
}
}, {
key: 'renderReact16',
value: function renderReact16() {
if (!canUseDOM || !isReact16) return null;
var children = this.props.children;
return ReactDOM.createPortal(children, this.node);
}
}, {
key: 'render',
value: function render() {
if (!isReact16) {
return null;
}
return this.renderReact16();
}
}]);
return JoyridePortal;
}(React.Component);
JoyridePortal.propTypes = {
children: PropTypes.element,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
};
var JoyrideStep = function (_React$Component) {
inherits(JoyrideStep, _React$Component);
function JoyrideStep() {
var _ref;
var _temp, _this, _ret;
classCallCheck(this, JoyrideStep);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = JoyrideStep.__proto__ || Object.getPrototypeOf(JoyrideStep)).call.apply(_ref, [this].concat(args))), _this), _this.handleClickHoverBeacon = function (e) {
var _this$props = _this.props,
step = _this$props.step,
update = _this$props.update;
if (e.type === 'mouseenter' && step.event !== 'hover') {
return;
}
update({ lifecycle: LIFECYCLE.TOOLTIP });
}, _this.handleClickOverlay = function () {
var _this$props2 = _this.props,
helpers = _this$props2.helpers,
step = _this$props2.step;
if (!step.disableOverlayClose) {
helpers.close();
}
}, _this.setTooltipRef = function (c) {
_this.tooltip = c;
}, _this.setPopper = function (popper, type) {
var _this$props3 = _this.props,
action = _this$props3.action,
getPopper = _this$props3.getPopper,
update = _this$props3.update;
if (type === 'wrapper') {
_this.beaconPopper = popper;
} else {
_this.tooltipPopper = popper;
}
getPopper(popper, type);
if (_this.beaconPopper && _this.tooltipPopper) {
update({
action: action === ACTIONS.CLOSE ? ACTIONS.CLOSE : action,
lifecycle: LIFECYCLE.READY
});
}
}, _temp), possibleConstructorReturn(_this, _ret);
}
createClass(JoyrideStep, [{
key: 'componentDidMount',
value: function componentDidMount() {
var _props = this.props,
debug = _props.debug,
lifecycle = _props.lifecycle;
log({
title: 'step:' + lifecycle,
data: [{ key: 'props', value: this.props }],
debug: debug
});
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _props2 = this.props,
action = _props2.action,
continuous = _props2.continuous,
debug = _props2.debug,
index = _props2.index,
lifecycle = _props2.lifecycle,
step = _props2.step,
update = _props2.update;
var _treeChanges = treeChanges(this.props, nextProps),
changed = _treeChanges.changed,
changedFrom = _treeChanges.changedFrom;
var skipBeacon = continuous && action !== ACTIONS.CLOSE && (index > 0 || action === ACTIONS.PREV);
if (changedFrom('lifecycle', LIFECYCLE.INIT, LIFECYCLE.READY)) {
update({ lifecycle: step.disableBeacon || skipBeacon ? LIFECYCLE.TOOLTIP : LIFECYCLE.BEACON });
}
if (changed('index')) {
log({
title: 'step:' + lifecycle,
data: [{ key: 'props', value: this.props }],
debug: debug
});
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
var _props3 = this.props,
action = _props3.action,
callback = _props3.callback,
controlled = _props3.controlled,
index = _props3.index,
lifecycle = _props3.lifecycle,
size = _props3.size,
status = _props3.status,
step = _props3.step,
update = _props3.update;
var _treeChanges2 = treeChanges(prevProps, this.props),
changed = _treeChanges2.changed,
changedTo = _treeChanges2.changedTo,
changedFrom = _treeChanges2.changedFrom;
var state = { action: action, controlled: controlled, index: index, lifecycle: lifecycle, size: size, status: status };
var isAfterAction = [ACTIONS.NEXT, ACTIONS.PREV, ACTIONS.SKIP, ACTIONS.CLOSE].indexOf(action) !== -1 && changed('action');
var hasChangedIndex = changed('index') && changedFrom('lifecycle', LIFECYCLE.TOOLTIP, LIFECYCLE.INIT);
if (!changed('status') && (hasChangedIndex || controlled && isAfterAction)) {
callback(_extends({}, state, {
index: prevProps.index,
lifecycle: LIFECYCLE.COMPLETE,
step: prevProps.step,
type: EVENTS.STEP_AFTER
}));
}
// There's a step to use, but there's no target in the DOM
if (step) {
var hasRenderedTarget = !!getElement(step.target);
if (hasRenderedTarget) {
if (changedFrom('status', STATUS.READY, STATUS.RUNNING) || changed('index')) {
callback(_extends({}, state, {
step: step,
type: EVENTS.STEP_BEFORE
}));
}
}
if (!hasRenderedTarget) {
console.warn('Target not mounted', step); //eslint-disable-line no-console
callback(_extends({}, state, {
type: EVENTS.TARGET_NOT_FOUND,
step: step
}));
if (!controlled) {
update({ index: index + ([ACTIONS.PREV].indexOf(action) !== -1 ? -1 : 1) });
}
}
}
/* istanbul ignore else */
if (changedTo('lifecycle', LIFECYCLE.BEACON)) {
callback(_extends({}, state, {
step: step,
type: EVENTS.BEACON
}));
}
if (changedTo('lifecycle', LIFECYCLE.TOOLTIP)) {
callback(_extends({}, state, {
step: step,
type: EVENTS.TOOLTIP
}));
setScope(this.tooltip);
}
if (changedFrom('lifecycle', LIFECYCLE.TOOLTIP, LIFECYCLE.INIT)) {
removeScope();
}
if (changedTo('lifecycle', LIFECYCLE.INIT)) {
delete this.beaconPopper;
delete this.tooltipPopper;
}
}
/**
* Beacon click/hover event listener
*
* @param {Event} e
*/
}, {
key: 'render',
value: function render() {
var _props4 = this.props,
continuous = _props4.continuous,
controlled = _props4.controlled,
debug = _props4.debug,
helpers = _props4.helpers,
index = _props4.index,
lifecycle = _props4.lifecycle,
size = _props4.size,
step = _props4.step;
var target = getElement(step.target);
if (!validateStep(step) || !is.domElement(target)) {
return null;
}
return React.createElement(
'div',
{ key: 'JoyrideStep-' + index, className: 'joyride-step' },
React.createElement(
JoyridePortal,
null,
React.createElement(Overlay, _extends({}, step, {
lifecycle: lifecycle,
onClickOverlay: this.handleClickOverlay
}))
),
React.createElement(
Floater,
_extends({
component: React.createElement(JoyrideTooltip, {
continuous: continuous,
controlled: controlled,
helpers: helpers,
index: index,
setTooltipRef: this.setTooltipRef,
size: size,
isLastStep: index + 1 === size,
step: step
}),
debug: debug,
getPopper: this.setPopper,
id: 'react-joyride:' + index,
isPositioned: step.isFixed || isFixed(target),
open: this.open,
placement: step.placement,
target: step.target
}, step.floaterProps),
React.createElement(JoyrideBeacon, {
beaconComponent: step.beaconComponent,
locale: step.locale,
onClickOrHover: this.handleClickHoverBeacon,
styles: step.styles
})
)
);
}
}, {
key: 'open',
get: function get$$1() {
var _props5 = this.props,
step = _props5.step,
lifecycle = _props5.lifecycle;
return !!(step.disableBeacon || lifecycle === LIFECYCLE.TOOLTIP);
}
}]);
return JoyrideStep;
}(React.Component);
JoyrideStep.propTypes = {
action: PropTypes.string.isRequired,
callback: PropTypes.func.isRequired,
continuous: PropTypes.bool.isRequired,
controlled: PropTypes.bool.isRequired,
debug: PropTypes.bool.isRequired,
getPopper: PropTypes.func.isRequired,
helpers: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
lifecycle: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
status: PropTypes.string.isRequired,
step: PropTypes.shape({
beaconComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
content: isRequiredIf(PropTypes.node, function (props) {
return !props.tooltipComponent && !props.title;
}),
disableBeacon: PropTypes.bool,
disableOverlay: PropTypes.bool,
disableOverlayClose: PropTypes.bool,
event: PropTypes.string,
floaterProps: PropTypes.shape({
offset: PropTypes.number
}),
hideBackButton: PropTypes.bool,
isFixed: PropTypes.bool,
locale: PropTypes.object,
offset: PropTypes.number.isRequired,
placement: PropTypes.oneOf(['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end', 'auto', 'center']),
spotlightClicks: PropTypes.bool,
spotlightPadding: PropTypes.number,
styles: PropTypes.object,
target: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
title: PropTypes.node,
tooltipComponent: isRequiredIf(PropTypes.oneOfType([PropTypes.func, PropTypes.element]), function (props) {
return !props.content && !props.title;
})
}).isRequired,
update: PropTypes.func.isRequired
};
var Joyride = function (_React$Component) {
inherits(Joyride, _React$Component);
function Joyride(props) {
classCallCheck(this, Joyride);
var _this = possibleConstructorReturn(this, (Joyride.__proto__ || Object.getPrototypeOf(Joyride)).call(this, props));
_this.callback = function (data) {
var callback = _this.props.callback;
/* istanbul ignore else */
if (is.function(callback)) {
callback(data);
}
};
_this.handleKeyboard = function (e) {
var _this$state = _this.state,
index = _this$state.index,
lifecycle = _this$state.lifecycle;
var steps = _this.props.steps;
var step = steps[index];
var intKey = window.Event ? e.which : e.keyCode;
if (lifecycle === LIFECYCLE.TOOLTIP) {
if (intKey === 27 && step && !step.disableCloseOnEsc) {
_this.store.close();
}
}
};
_this.syncState = function (state) {
_this.setState(state);
};
_this.getPopper = function (popper, type) {
if (type === 'wrapper') {
_this.beaconPopper = popper;
} else {
_this.tooltipPopper = popper;
}
};
_this.store = new createStore(_extends({}, props, {
controlled: props.run && is.number(props.stepIndex)
}));
_this.state = _this.store.getState();
_this.helpers = _this.store.getHelpers();
return _this;
}
createClass(Joyride, [{
key: 'componentDidMount',
value: function componentDidMount() {
if (!canUseDOM) return;
var _props = this.props,
debug = _props.debug,
disableCloseOnEsc = _props.disableCloseOnEsc,
run = _props.run,
steps = _props.steps;
var start = this.store.start;
log({
title: 'init',
data: [{ key: 'props', value: this.props }, { key: 'state', value: this.state }],
debug: debug
});
// Sync the store to this component state.
this.store.addListener(this.syncState);
if (validateSteps(steps, debug) && run) {
start();
}
/* istanbul ignore else */
if (!disableCloseOnEsc) {
document.body.addEventListener('keydown', this.handleKeyboard, { passive: true });
}
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
if (!canUseDOM) return;
var _state = this.state,
action = _state.action,
status = _state.status;
var _props2 = this.props,
steps = _props2.steps,
stepIndex = _props2.stepIndex;
var debug = nextProps.debug,
run = nextProps.run,
nextSteps = nextProps.steps,
nextStepIndex = nextProps.stepIndex;
var _store = this.store,
setSteps = _store.setSteps,
start = _store.start,
stop = _store.stop,
update = _store.update;
var diffProps = !isEqual(this.props, nextProps);
var _treeChanges = treeChanges(this.props, nextProps),
changed = _treeChanges.changed;
if (diffProps) {
log({
title: 'props',
data: [{ key: 'nextProps', value: nextProps }, { key: 'props', value: this.props }],
debug: debug
});
var stepsChanged = !isEqual(nextSteps, steps);
var stepIndexChanged = is.number(nextStepIndex) && changed('stepIndex');
/* istanbul ignore else */
if (changed('run')) {
if (run) {
start(nextStepIndex);
} else {
stop();
}
}
if (stepsChanged) {
if (validateSteps(nextSteps, debug)) {
setSteps(nextSteps);
} else {
console.warn('Steps are not valid', nextSteps); //eslint-disable-line no-console
}
}
/* istanbul ignore else */
if (stepIndexChanged) {
var nextAction = stepIndex < nextStepIndex ? ACTIONS.NEXT : ACTIONS.PREV;
if (action === ACTIONS.STOP) {
nextAction = ACTIONS.START;
}
if (!([STATUS.FINISHED, STATUS.SKIPPED].indexOf(status) !== -1)) {
update({
action: action === ACTIONS.CLOSE ? ACTIONS.CLOSE : nextAction,
index: nextStepIndex,
lifecycle: LIFECYCLE.INIT
});
}
}
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps, prevState) {
if (!canUseDOM) return;
var _state2 = this.state,
index = _state2.index,
lifecycle = _state2.lifecycle,
status = _state2.status;
var _props3 = this.props,
debug = _props3.debug,
steps = _props3.steps;
var _treeChanges2 = treeChanges(prevState, this.state),
changed = _treeChanges2.changed,
changedFrom = _treeChanges2.changedFrom,
changedTo = _treeChanges2.changedTo;
var diffState = !isEqual(prevState, this.state);
var step = getMergedStep(steps[index], this.props);
if (diffState) {
log({
title: 'state',
data: [{ key: 'state', value: this.state }, { key: 'changed', value: diffState }, { key: 'step', value: step }],
debug: debug
});
var currentIndex = index;
if (changed('status')) {
var type = EVENTS.TOUR_STATUS;
if (changedTo('status', STATUS.FINISHED) || changedTo('status', STATUS.SKIPPED)) {
type = EVENTS.TOUR_END;
// Return the last step when the tour is finished
step = getMergedStep(steps[prevState.index], this.props);
currentIndex = prevState.index;
} else if (changedFrom('status', STATUS.READY, STATUS.RUNNING)) {
type = EVENTS.TOUR_START;
}
this.callback(_extends({}, this.state, {
index: currentIndex,
step: step,
type: type
}));
}
if (step) {
this.scrollToStep(prevState);
if (step.placement === 'center' && status === STATUS.RUNNING && lifecycle === LIFECYCLE.INIT) {
this.store.update({ lifecycle: LIFECYCLE.READY });
}
}
if (changedTo('lifecycle', LIFECYCLE.INIT)) {
delete this.beaconPopper;
delete this.tooltipPopper;
}
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
var disableCloseOnEsc = this.props.disableCloseOnEsc;
/* istanbul ignore else */
if (!disableCloseOnEsc) {
document.body.removeEventListener('keydown', this.handleKeyboard);
}
}
}, {
key: 'scrollToStep',
value: function scrollToStep(prevState) {
var _state3 = this.state,
index = _state3.index,
lifecycle = _state3.lifecycle,
status = _state3.status;
var _props4 = this.props,
debug = _props4.debug,
disableScrolling = _props4.disableScrolling,
scrollToFirstStep = _props4.scrollToFirstStep,
scrollOffset = _props4.scrollOffset,
steps = _props4.steps;
var step = getMergedStep(steps[index], this.props);
if (step) {
var target = getElement(step.target);
var shouldScroll = step && !disableScrolling && (!step.isFixed || !isFixed(target)) // fixed steps don't need to scroll
&& prevState.lifecycle !== lifecycle && [LIFECYCLE.BEACON, LIFECYCLE.TOOLTIP].indexOf(lifecycle) !== -1 && (scrollToFirstStep || prevState.index !== index);
if (status === STATUS.RUNNING && shouldScroll) {
var hasCustomScroll = hasCustomScrollParent(target);
var scrollParent = getScrollParent(target);
var scrollY = Math.floor(getScrollTo(target, scrollOffset));
log({
title: 'scrollToStep',
data: [{ key: 'index', value: index }, { key: 'lifecycle', value: lifecycle }, { key: 'status', value: status }],
debug: debug
});
if (lifecycle === LIFECYCLE.BEACON && this.beaconPopper) {
var _beaconPopper = this.beaconPopper,
placement = _beaconPopper.placement,
popper = _beaconPopper.popper;
if (!(['bottom'].indexOf(placement) !== -1) && !hasCustomScroll) {
scrollY = Math.floor(popper.top - scrollOffset);
}
} else if (lifecycle === LIFECYCLE.TOOLTIP && this.tooltipPopper) {
var _tooltipPopper = this.tooltipPopper,
flipped = _tooltipPopper.flipped,
_placement = _tooltipPopper.placement,
_popper = _tooltipPopper.popper;
if (['top', 'right'].indexOf(_placement) !== -1 && !flipped && !hasCustomScroll) {
scrollY = Math.floor(_popper.top - scrollOffset);
} else {
scrollY -= step.spotlightPadding;
}
}
if (status === STATUS.RUNNING && shouldScroll && scrollY >= 0) {
scrollTo(scrollY, scrollParent);
}
}
}
}
/**
* Trigger the callback.
*
* @private
* @param {Object} data
*/
/**
* Keydown event listener
*
* @private
* @param {Event} e - Keyboard event
*/
/**
* Sync the store with the component's state
*
* @param {Object} state
*/
}, {
key: 'render',
value: function render() {
if (!canUseDOM) return null;
var _state4 = this.state,
index = _state4.index,
status = _state4.status;
var _props5 = this.props,
continuous = _props5.continuous,
debug = _props5.debug,
disableScrolling = _props5.disableScrolling,
steps = _props5.steps;
var step = getMergedStep(steps[index], this.props);
var output = void 0;
if (status === STATUS.RUNNING && step) {
output = React.createElement(JoyrideStep, _extends({}, this.state, {
callback: this.callback,
continuous: continuous,
debug: debug,
disableScrolling: disableScrolling,
getPopper: this.getPopper,
helpers: this.helpers,
step: step,
update: this.store.update
}));
}
return React.createElement(
'div',
{ className: 'joyride' },
output
);
}
}]);
return Joyride;
}(React.Component);
Joyride.propTypes = {
beaconComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
callback: PropTypes.func,
continuous: PropTypes.bool,
debug: PropTypes.bool,
disableCloseOnEsc: PropTypes.bool,
disableOverlay: PropTypes.bool,
disableOverlayClose: PropTypes.bool,
disableScrolling: PropTypes.bool,
floaterProps: PropTypes.shape({
offset: PropTypes.number
}),
hideBackButton: PropTypes.bool,
locale: PropTypes.object,
run: PropTypes.bool,
scrollOffset: PropTypes.number,
scrollToFirstStep: PropTypes.bool,
showProgress: PropTypes.bool,
showSkipButton: PropTypes.bool,
spotlightClicks: PropTypes.bool,
spotlightPadding: PropTypes.number,
stepIndex: PropTypes.number,
steps: PropTypes.array,
styles: PropTypes.object,
tooltipComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element])
};
Joyride.defaultProps = {
continuous: false,
debug: false,
disableCloseOnEsc: false,
disableOverlay: false,
disableOverlayClose: false,
disableScrolling: false,
hideBackButton: false,
run: true,
scrollOffset: 20,
scrollToFirstStep: false,
showSkipButton: false,
showProgress: false,
spotlightClicks: false,
spotlightPadding: 10,
steps: []
};
exports.default = Joyride;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment