🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

react-tour-guide

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-tour-guide - npm Package Compare versions

Comparing version
0.0.2
to
0.0.3
+153
dist/css/tour-guide.css
.tour-indicator {
height: 30px;
width: 30px;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
border-radius: 100%;
background-color: #3f94d0;
cursor: pointer;
/* Animate */
-webkit-animation-name: pulse;
-webkit-animation-duration: 1.5s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: ease-out;
-moz-animation-name: pulse;
-moz-animation-duration: 1.5s;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: ease-out;
-o-animation-name: pulse;
-o-animation-duration: 1.5s;
-o-animation-iteration-count: infinite;
-o-animation-timing-function: ease-out;
animation-name: pulse;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: ease-out;
}
/* WebKit/Safari and Chrome */
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
80% {
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
100% {
-webkit-transform: scale(2.5);
transform: scale(2.5);
opacity: 0;
}
}
/* Gecko/Firefox */
@-moz-keyframes pulse {
0% {
-moz-transform: scale(0.3);
transform: scale(0.3);
opacity: 0.5;
}
80% {
-moz-transform: scale(1.5);
transform: scale(1.5);
opacity: 0;
}
100% {
-moz-transform: scale(2.5);
transform: scale(2.5);
opacity: 0;
}
}
/* Presto/Opera */
@-o-keyframes pulse {
0% {
-o-transform: scale(0.3);
transform: scale(0.3);
opacity: 0.5;
}
80% {
-o-transform: scale(1.5);
transform: scale(1.5);
opacity: 0;
}
100% {
-o-transform: scale(2.5);
transform: scale(2.5);
opacity: 0;
}
}
/* Standard */
@keyframes pulse {
0% {
transform: scale(0.3);
opacity: 0.5;
}
80% {
transform: scale(1.5);
opacity: 0;
}
100% {
transform: scale(2.5);
opacity: 0;
}
}
.tour-backdrop {
z-index: 998; /* one below z-index of tour-toolip (999) */
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
text-align: center;
background: rgba(0, 0, 0, 0.45);
}
.tour-tooltip {
width: 200px;
background-color: #ffffff;
color: #545454;
border: 1px solid #dddddd;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
padding: 5px;
-webkit-box-shadow: 0 8px 6px -6px rgba(0,0,0,0.4);
-moz-box-shadow: 0 8px 6px -6px rgba(0,0,0,0.4);
box-shadow: 0 8px 6px -6px rgba(0,0,0,0.4);
}
.tour-tooltip p {
margin: 5px 3px;
}
.tour-tooltip .tour-btn.close {
cursor: pointer;
display: block;
width: auto;
margin: 0 auto;
background-color: #ffffff;
border: 1px solid #dddddd;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
padding: 3px;
text-align: center;
}
.tour-tooltip .tour-btn.close:hover {
border-color: #3f94d0;
color: #3f94d0;
}
/**
* @jsx React.DOM
*/
'use strict';
var React = require('react/addons');
var Indicator = React.createClass({displayName: "Indicator",
propTypes: {
cssPosition: React.PropTypes.string.isRequired,
size: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
xPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
yPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
handleIndicatorClick: React.PropTypes.func.isRequired
},
getDefaultProps: function() {
return {
cssPosition: 'absolute',
size: '30px',
xPos: 0,
yPos: 0
};
},
render: function() {
var styles = {
'position': this.props.cssPosition === 'fixed' ? 'fixed' : 'absolute',
'top': this.props.yPos,
'left': this.props.xPos,
'width': this.props.size,
'height': this.props.size
};
return (
React.createElement("div", {className: "tour-indicator", style: styles, onClick: this.props.handleIndicatorClick})
);
}
});
module.exports = React.createFactory(Indicator);
/**
* @jsx React.DOM
*/
'use strict';
var React = require('react/addons');
var $ = require('jquery');
var Indicator = require('./Indicator');
var Tooltip = require('./Tooltip');
module.exports = function(settings, done) {
var mixin = {
settings: $.extend({
scrollToSteps: true,
indicatorSize: 30,
tooltipWidth: 250,
steps: []
}, settings),
completionCallback: done || function() {},
getInitialState: function() {
return {
currentIndex: 0,
showTooltip: false
};
},
_renderLayer: function() {
// By calling this method in componentDidMount() and componentDidUpdate(), you're effectively
// creating a "wormhole" that funnels React's hierarchical updates through to a DOM node on an
// entirely different part of the page.
React.render(this.renderCurrentStep(), this._target);
},
_unrenderLayer: function() {
React.unmountComponentAtNode(this._target);
},
componentDidUpdate: function() {
if ( this.settings.steps[this.state.currentIndex] ) {
this._renderLayer();
} else {
this.completionCallback();
this._unrenderLayer();
}
},
componentDidMount: function() {
// Appending to the body is easier than managing the z-index of everything on the page.
// It's also better for accessibility and makes stacking a snap (since components will stack
// in mount order).
if ( this.settings.steps[this.state.currentIndex] ) {
this._target = document.createElement('div');
document.body.appendChild(this._target);
this._renderLayer();
}
},
componentWillUnmount: function() {
this._unrenderLayer();
document.body.removeChild(this._target);
},
preventWindowOverflow: function(type, value, axis) {
var winWidth = parseInt($(window).width());
var docHeight = parseInt($(document).height());
var sizeVariable = type.toLowerCase() === 'indicator' ? this.settings.indicatorSize : this.settings.tooltipWidth;
if ( axis.toLowerCase() === 'x' ) {
if ( value + sizeVariable > winWidth ) {
value = winWidth - sizeVariable;
} else if ( value - sizeVariable/2 < 0 ) {
value = 0;
}
} else if ( axis.toLowerCase() === 'y' ) {
if ( value + sizeVariable/2 > docHeight ) {
value = docHeight - sizeVariable;
} else if ( value - sizeVariable/2 < 0 ) {
value = 0;
}
}
return value;
},
calculatePlacement: function(step, $element) {
var offset = $element.offset();
var width = $element.width();
var height = $element.height();
var position = step.position.toLowerCase();
var topRegex = new RegExp('top', 'gi');
var bottomRegex = new RegExp('bottom', 'gi');
var leftRegex = new RegExp('left', 'gi');
var rightRegex = new RegExp('right', 'gi');
var placement = {
indicator: {
x: 0,
y: 0
},
tooltip: {
x: 0,
y: 0
}
};
// Calculate x positions
if ( leftRegex.test(position) ) {
placement.indicator.x = offset.left - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top - this.settings.tooltipWidth/4;
} else if ( rightRegex.test(position) ) {
placement.indicator.x = offset.left + width - this.settings.indicatorSize/2;
placement.tooltip.x = offset.left + width - this.settings.tooltipWidth/2;
} else {
placement.indicator.x = offset.left + width/2 - this.settings.indicatorSize/2;
placement.tooltip.x = offset.left + width/2 - this.settings.tooltipWidth/2;
}
// Calculate y positions
if ( topRegex.test(position) ) {
placement.indicator.y = offset.top - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top - this.settings.tooltipWidth/4;
} else if ( bottomRegex.test(position) ) {
placement.indicator.y = offset.top + height - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top + height - this.settings.tooltipWidth/4;
} else {
placement.indicator.y = offset.top + height/2 - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top + height/2 - this.settings.tooltipWidth/4;
}
return {
indicator: {
x: this.preventWindowOverflow('indicator', placement.indicator.x, 'x'),
y: this.preventWindowOverflow('indicator', placement.indicator.y, 'y')
},
tooltip: {
x: this.preventWindowOverflow('tooltip', placement.tooltip.x, 'x'),
y: this.preventWindowOverflow('tooltip', placement.tooltip.y, 'y')
}
};
},
handleIndicatorClick: function(evt) {
evt.preventDefault();
this.setState({ showTooltip: true });
},
closeTooltip: function(evt) {
evt.preventDefault();
this.setState({
showTooltip: false,
currentIndex: this.state.currentIndex + 1
}, this.scrollToNextStep);
},
scrollToNextStep: function() {
var $nextIndicator = $('.tour-indicator');
if ( $nextIndicator && $nextIndicator.length && this.settings.scrollToSteps ) {
$('html, body').animate({
'scrollTop': $nextIndicator.offset().top - $(window).height()/2
}, 500);
}
},
renderCurrentStep: function() {
var element = null;
var currentStep = this.settings.steps[this.state.currentIndex];
var $target = $(currentStep.element);
var cssPosition = $target.css('position');
var placement = this.calculatePlacement(currentStep, $target);
if ( this.state.showTooltip ) {
element = (
React.createElement(Tooltip, {cssPosition: cssPosition,
xPos: placement.tooltip.x,
yPos: placement.tooltip.y,
width: this.settings.tooltipWidth,
text: currentStep.text,
closeTooltip: this.closeTooltip})
);
} else {
element = (
React.createElement(Indicator, {cssPosition: cssPosition,
xPos: placement.indicator.x,
yPos: placement.indicator.y,
size: this.settings.indicatorSize,
handleIndicatorClick: this.handleIndicatorClick})
);
}
return element;
}
};
return mixin;
};
/**
* @jsx React.DOM
*/
'use strict';
var React = require('react/addons');
var Tooltip = React.createClass({displayName: "Tooltip",
propTypes: {
cssPosition: React.PropTypes.string.isRequired,
xPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
yPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
width: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
text: React.PropTypes.string.isRequired,
closeTooltip: React.PropTypes.func.isRequired
},
getDefaultProps: function() {
return {
cssPosition: 'absolute',
xPos: 0,
yPos: 0,
text: ''
};
},
render: function() {
var styles = {
'position': this.props.cssPosition === 'fixed' ? 'fixed' : 'absolute',
'top': this.props.yPos,
'left': this.props.xPos,
'width': this.props.width
};
return (
React.createElement("div", null,
React.createElement("div", {className: "tour-backdrop", onClick: this.props.closeTooltip}),
React.createElement("div", {className: "tour-tooltip", style: styles},
React.createElement("p", null, this.props.text),
React.createElement("div", {className: "tour-btn close", onClick: this.props.closeTooltip}, "Close")
)
)
);
}
});
module.exports = React.createFactory(Tooltip);
+3
-3

@@ -6,8 +6,8 @@

Mixin: require('./lib/js/Mixin'),
Mixin: require('./dist/js/Mixin'),
Indicator: require('./lib/js/Indicator'),
Indicator: require('./dist/js/Indicator'),
Tooltip: require('./lib/js/Tooltip')
Tooltip: require('./dist/js/Tooltip')
};
{
"name": "react-tour-guide",
"version": "0.0.2",
"version": "0.0.3",
"author": "Jake Marsh <jakemmarsh@gmail.com>",

@@ -24,3 +24,9 @@ "description": "A ReactJS mixin to give new users a popup-based tour of your application.",

"jquery": "^2.1.3"
},
"devDependencies": {
"del": "^1.1.1",
"gulp": "^3.8.11",
"gulp-react": "^3.0.0",
"run-sequence": "^1.0.2"
}
}

@@ -90,3 +90,4 @@ react-tour-guide [![npm version](https://badge.fury.io/js/react-tour-guide.svg)](http://badge.fury.io/js/react-tour-guide)

```html
<div class="tour-backdrop">
<div>
<div class="tour-backdrop"></div>
<div class="tour-tooltip">

@@ -93,0 +94,0 @@ <p>{The step's text goes here.}</p>

{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"noarg": true,
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"newcap": false
}
/**
* @jsx React.DOM
*/
'use strict';
var React = require('react/addons');
var Indicator = React.createClass({
propTypes: {
cssPosition: React.PropTypes.string.isRequired,
size: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
xPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
yPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
handleIndicatorClick: React.PropTypes.func.isRequired
},
getDefaultProps: function() {
return {
cssPosition: 'absolute',
size: '30px',
xPos: 0,
yPos: 0
};
},
render: function() {
var styles = {
'position': this.props.cssPosition === 'fixed' ? 'fixed' : 'absolute',
'top': this.props.yPos,
'left': this.props.xPos,
'width': this.props.size,
'height': this.props.size
};
return (
<div className="tour-indicator" style={styles} onClick={this.props.handleIndicatorClick} />
);
}
});
module.exports = React.createFactory(Indicator);
/**
* @jsx React.DOM
*/
'use strict';
var React = require('react/addons');
var $ = require('jquery');
var Indicator = require('./Indicator');
var Tooltip = require('./Tooltip');
window.jQuery = $;
module.exports = function(settings, done) {
var mixin = {
settings: $.extend({
scrollToSteps: true,
indicatorSize: 30,
tooltipWidth: 250,
steps: []
}, settings),
completionCallback: done || function() {},
getInitialState: function() {
return {
currentIndex: 0,
showTooltip: false
};
},
_renderLayer: function() {
// By calling this method in componentDidMount() and componentDidUpdate(), you're effectively
// creating a "wormhole" that funnels React's hierarchical updates through to a DOM node on an
// entirely different part of the page.
React.render(this.renderCurrentStep(), this._target);
},
_unrenderLayer: function() {
React.unmountComponentAtNode(this._target);
},
componentDidUpdate: function() {
if ( this.settings.steps[this.state.currentIndex] ) {
this._renderLayer();
} else {
this.completionCallback();
this._unrenderLayer();
}
},
componentDidMount: function() {
// Appending to the body is easier than managing the z-index of everything on the page.
// It's also better for accessibility and makes stacking a snap (since components will stack
// in mount order).
if ( this.settings.steps[this.state.currentIndex] ) {
this._target = document.createElement('div');
document.body.appendChild(this._target);
this._renderLayer();
}
},
componentWillUnmount: function() {
this._unrenderLayer();
document.body.removeChild(this._target);
},
preventWindowOverflow: function(type, value, axis) {
var winWidth = parseInt($(window).width());
var docHeight = parseInt($(document).height());
var sizeVariable = type.toLowerCase() === 'indicator' ? this.settings.indicatorSize : this.settings.tooltipWidth;
if ( axis.toLowerCase() === 'x' ) {
if ( value + sizeVariable > winWidth ) {
value = winWidth - sizeVariable;
} else if ( value - sizeVariable/2 < 0 ) {
value = 0;
}
} else if ( axis.toLowerCase() === 'y' ) {
if ( value + sizeVariable/2 > docHeight ) {
value = docHeight - sizeVariable;
} else if ( value - sizeVariable/2 < 0 ) {
value = 0;
}
}
return value;
},
calculatePlacement: function(step, $element) {
var offset = $element.offset();
var width = $element.width();
var height = $element.height();
var position = step.position.toLowerCase();
var topRegex = new RegExp('top', 'gi');
var bottomRegex = new RegExp('bottom', 'gi');
var leftRegex = new RegExp('left', 'gi');
var rightRegex = new RegExp('right', 'gi');
var placement = {
indicator: {
x: 0,
y: 0
},
tooltip: {
x: 0,
y: 0
}
};
// Calculate x positions
if ( leftRegex.test(position) ) {
placement.indicator.x = offset.left - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top - this.settings.tooltipWidth/4;
} else if ( rightRegex.test(position) ) {
placement.indicator.x = offset.left + width - this.settings.indicatorSize/2;
placement.tooltip.x = offset.left + width - this.settings.tooltipWidth/2;
} else {
placement.indicator.x = offset.left + width/2 - this.settings.indicatorSize/2;
placement.tooltip.x = offset.left + width/2 - this.settings.tooltipWidth/2;
}
// Calculate y positions
if ( topRegex.test(position) ) {
placement.indicator.y = offset.top - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top - this.settings.tooltipWidth/4;
} else if ( bottomRegex.test(position) ) {
placement.indicator.y = offset.top + height - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top + height - this.settings.tooltipWidth/4;
} else {
placement.indicator.y = offset.top + height/2 - this.settings.indicatorSize/2;
placement.tooltip.y = offset.top + height/2 - this.settings.tooltipWidth/4;
}
return {
indicator: {
x: this.preventWindowOverflow('indicator', placement.indicator.x, 'x'),
y: this.preventWindowOverflow('indicator', placement.indicator.y, 'y')
},
tooltip: {
x: this.preventWindowOverflow('tooltip', placement.tooltip.x, 'x'),
y: this.preventWindowOverflow('tooltip', placement.tooltip.y, 'y')
}
};
},
handleIndicatorClick: function(evt) {
evt.preventDefault();
this.setState({ showTooltip: true });
},
closeTooltip: function(evt) {
evt.preventDefault();
this.setState({
showTooltip: false,
currentIndex: this.state.currentIndex + 1
}, this.scrollToNextStep);
},
scrollToNextStep: function() {
var $nextIndicator = $('.tour-indicator');
if ( $nextIndicator && $nextIndicator.length && this.settings.scrollToSteps ) {
$('html, body').animate({
'scrollTop': $nextIndicator.offset().top - $(window).height()/2
}, 500);
}
},
renderCurrentStep: function() {
var element = null;
var currentStep = this.settings.steps[this.state.currentIndex];
var $target = $(currentStep.element);
var cssPosition = $target.css('position');
var placement = this.calculatePlacement(currentStep, $target);
if ( this.state.showTooltip ) {
element = (
<Tooltip cssPosition={cssPosition}
xPos={placement.tooltip.x}
yPos={placement.tooltip.y}
width={this.settings.tooltipWidth}
text={currentStep.text}
closeTooltip={this.closeTooltip} />
);
} else {
element = (
<Indicator cssPosition={cssPosition}
xPos={placement.indicator.x}
yPos={placement.indicator.y}
size={this.settings.indicatorSize}
handleIndicatorClick={this.handleIndicatorClick} />
);
}
return element;
}
};
return mixin;
};
/**
* @jsx React.DOM
*/
'use strict';
var React = require('react/addons');
var Tooltip = React.createClass({
propTypes: {
cssPosition: React.PropTypes.string.isRequired,
xPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
yPos: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
width: React.PropTypes.oneOfType([
React.PropTypes.number,
React.PropTypes.string
]).isRequired,
text: React.PropTypes.string.isRequired,
closeTooltip: React.PropTypes.func.isRequired
},
getDefaultProps: function() {
return {
cssPosition: 'absolute',
xPos: 0,
yPos: 0,
text: ''
};
},
render: function() {
var styles = {
'position': this.props.cssPosition === 'fixed' ? 'fixed' : 'absolute',
'top': this.props.yPos,
'left': this.props.xPos,
'width': this.props.width
};
return (
<div>
<div className="tour-backdrop" onClick={this.props.closeTooltip} />
<div className="tour-tooltip" style={styles}>
<p>{this.props.text}</p>
<div className="tour-btn close" onClick={this.props.closeTooltip}>Close</div>
</div>
</div>
);
}
});
module.exports = React.createFactory(Tooltip);
.tour-indicator {
height: 30px;
width: 30px;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
border-radius: 100%;
background-color: #3f94d0;
cursor: pointer;
/* Animate */
-webkit-animation-name: pulse;
-webkit-animation-duration: 1.5s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: ease-out;
-moz-animation-name: pulse;
-moz-animation-duration: 1.5s;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: ease-out;
-o-animation-name: pulse;
-o-animation-duration: 1.5s;
-o-animation-iteration-count: infinite;
-o-animation-timing-function: ease-out;
animation-name: pulse;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: ease-out;
}
/* WebKit/Safari and Chrome */
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
transform: scale(1);
}
80% {
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
100% {
-webkit-transform: scale(2.5);
transform: scale(2.5);
opacity: 0;
}
}
/* Gecko/Firefox */
@-moz-keyframes pulse {
0% {
-moz-transform: scale(0.3);
transform: scale(0.3);
opacity: 0.5;
}
80% {
-moz-transform: scale(1.5);
transform: scale(1.5);
opacity: 0;
}
100% {
-moz-transform: scale(2.5);
transform: scale(2.5);
opacity: 0;
}
}
/* Presto/Opera */
@-o-keyframes pulse {
0% {
-o-transform: scale(0.3);
transform: scale(0.3);
opacity: 0.5;
}
80% {
-o-transform: scale(1.5);
transform: scale(1.5);
opacity: 0;
}
100% {
-o-transform: scale(2.5);
transform: scale(2.5);
opacity: 0;
}
}
/* Standard */
@keyframes pulse {
0% {
transform: scale(0.3);
opacity: 0.5;
}
80% {
transform: scale(1.5);
opacity: 0;
}
100% {
transform: scale(2.5);
opacity: 0;
}
}
.tour-backdrop {
z-index: 998; /* one below z-index of tour-toolip (999) */
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
text-align: center;
background: rgba(0, 0, 0, 0.45);
}
.tour-tooltip {
width: 200px;
background-color: #ffffff;
color: #545454;
border: 1px solid #dddddd;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
padding: 5px;
-webkit-box-shadow: 0 8px 6px -6px rgba(0,0,0,0.4);
-moz-box-shadow: 0 8px 6px -6px rgba(0,0,0,0.4);
box-shadow: 0 8px 6px -6px rgba(0,0,0,0.4);
}
.tour-tooltip p {
margin: 5px 3px;
}
.tour-tooltip .tour-btn.close {
cursor: pointer;
display: block;
width: auto;
margin: 0 auto;
background-color: #ffffff;
border: 1px solid #dddddd;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
padding: 3px;
text-align: center;
}
.tour-tooltip .tour-btn.close:hover {
border-color: #3f94d0;
color: #3f94d0;
}

Sorry, the diff of this file is not supported yet