react-joyride
Advanced tools
Comparing version 2.0.0-6 to 2.0.0-7
@@ -20,13 +20,9 @@ var ACTIONS = { | ||
BEACON: 'beacon', | ||
BEACON_TRIGGER: 'beacon:trigger', | ||
TOOLTIP: 'tooltip', | ||
TOOLTIP_SKIP: 'tooltip:skip', | ||
TOOLTIP_CLOSE: 'tooltip:close', | ||
OVERLAY_CLICK: 'overlay:click', | ||
HOLE_CLICK: 'hole:click', | ||
STEP_AFTER: 'step:after', | ||
TOUR_END: 'tour:end', | ||
// these usually don't happen in a normal tour | ||
TOUR_STATUS: 'tour:status', | ||
TARGET_NOT_FOUND: 'error:target_not_found', | ||
ERROR: 'error', | ||
TOUR_END: 'tour:end' | ||
ERROR: 'error' | ||
}; | ||
@@ -33,0 +29,0 @@ |
@@ -24,13 +24,9 @@ 'use strict'; | ||
BEACON: 'beacon', | ||
BEACON_TRIGGER: 'beacon:trigger', | ||
TOOLTIP: 'tooltip', | ||
TOOLTIP_SKIP: 'tooltip:skip', | ||
TOOLTIP_CLOSE: 'tooltip:close', | ||
OVERLAY_CLICK: 'overlay:click', | ||
HOLE_CLICK: 'hole:click', | ||
STEP_AFTER: 'step:after', | ||
TOUR_END: 'tour:end', | ||
// these usually don't happen in a normal tour | ||
TOUR_STATUS: 'tour:status', | ||
TARGET_NOT_FOUND: 'error:target_not_found', | ||
ERROR: 'error', | ||
TOUR_END: 'tour:end' | ||
ERROR: 'error' | ||
}; | ||
@@ -37,0 +33,0 @@ |
{ | ||
"name": "react-joyride", | ||
"version": "2.0.0-6", | ||
"version": "2.0.0-7", | ||
"description": "Create walkthroughs and guided tours for your apps", | ||
@@ -80,4 +80,4 @@ "author": "Gil Barbara <gilbarbara@gmail.com>", | ||
"prop-types": "^15.6.1", | ||
"react": "^16.2.0", | ||
"react-dom": "^16.2.0", | ||
"react": "^16.3.0", | ||
"react-dom": "^16.3.0", | ||
"rimraf": "^2.6.2", | ||
@@ -84,0 +84,0 @@ "rollup": "^0.57.1", |
@@ -1,7 +0,6 @@ | ||
React Joyride | ||
=== | ||
# React Joyride | ||
[![NPM version](https://badge.fury.io/js/react-joyride.svg)](https://www.npmjs.com/package/react-joyride) | ||
[![build status](https://travis-ci.org/gilbarbara/react-joyride.svg)](https://travis-ci.org/gilbarbara/react-joyride) | ||
[![Maintainability](https://api.codeclimate.com/v1/badges/43ecb5536910133429bd/maintainability)](https://codeclimate.com/github/gilbarbara/react-joyride/maintainability) | ||
[![NPM version](https://badge.fury.io/js/react-joyride.svg)](https://www.npmjs.com/package/react-joyride) | ||
[![build status](https://travis-ci.org/gilbarbara/react-joyride.svg)](https://travis-ci.org/gilbarbara/react-joyride) | ||
[![Maintainability](https://api.codeclimate.com/v1/badges/43ecb5536910133429bd/maintainability)](https://codeclimate.com/github/gilbarbara/react-joyride/maintainability) | ||
[![Test Coverage](https://api.codeclimate.com/v1/badges/43ecb5536910133429bd/test_coverage)](https://codeclimate.com/github/gilbarbara/react-joyride/test_coverage) | ||
@@ -11,4 +10,74 @@ | ||
View the demo [here](http://gilbarbara.github.io/react-joyride/) [[source](https://github.com/gilbarbara/react-joyride/tree/demo)] | ||
React-Joyride is React component to create a tour for your app for new users or explain functionality of new features. | ||
It uses [react-floater](https://github.com/gilbarbara/react-floater) \(with popper.js for positioning and styling\) and you can use your own components if you want. | ||
NO README YET FOR V2 | ||
#### View the demo [here](https://2zpjporp4p.codesandbox.io/) | ||
You can edit the demo [here](https://codesandbox.io/s/2zpjporp4p) | ||
## Setup | ||
```bash | ||
npm install --save react-joyride | ||
``` | ||
## Getting Started | ||
```js | ||
import Joyride from 'react-joyride'; | ||
export class App extends React.Component { | ||
state = { | ||
run: false, | ||
steps: [ | ||
{ | ||
target: '.my-first-step', | ||
content: 'This if my awesome feature!', | ||
placement: 'bottom', | ||
}, | ||
{ | ||
target: '.my-other-step', | ||
content: 'This if my awesome feature!', | ||
placement: 'bottom', | ||
}, | ||
... | ||
] | ||
}; | ||
componentDidMount() { | ||
this.setState({ run: true }); | ||
} | ||
callback = (tour) => { | ||
const { action, index, type } = data; | ||
}; | ||
render () { | ||
const { steps, run } = this.state; | ||
return ( | ||
<div className="app"> | ||
<Joyride | ||
steps={steps} | ||
run={run} | ||
debug={true} | ||
callback={this.callback} | ||
... | ||
/> | ||
... | ||
</div> | ||
); | ||
} | ||
} | ||
``` | ||
## Documentation | ||
* [Props](/docs/Props.md) | ||
* [Step](/docs/Step.md) | ||
* [Styling](/docs/Styling.md) | ||
* [Callback](/docs/Callback.md) | ||
* [Constants](/docs/Constants.md) | ||
@@ -41,3 +41,2 @@ import React from 'react'; | ||
static propTypes = { | ||
allowClicksThruHole: PropTypes.bool, | ||
beaconComponent: PropTypes.oneOfType([ | ||
@@ -50,9 +49,7 @@ PropTypes.func, | ||
debug: PropTypes.bool, | ||
disableBeacon: PropTypes.bool, | ||
disableCloseOnEsc: PropTypes.bool, | ||
disableOverlay: PropTypes.bool, | ||
disableOverlayClicks: PropTypes.bool, | ||
disableOverlayClose: PropTypes.bool, | ||
disableScrolling: PropTypes.bool, | ||
hideBackButton: PropTypes.bool, | ||
holePadding: PropTypes.number, | ||
locale: PropTypes.object, | ||
@@ -64,4 +61,7 @@ run: PropTypes.bool, | ||
showSkipButton: PropTypes.bool, | ||
spotlightClicks: PropTypes.bool, | ||
spotlightPadding: PropTypes.number, | ||
stepIndex: PropTypes.number, | ||
steps: PropTypes.array, | ||
styles: PropTypes.object, | ||
tooltipComponent: PropTypes.oneOfType([ | ||
@@ -77,12 +77,9 @@ PropTypes.func, | ||
static defaultProps = { | ||
allowClicksThruHole: false, | ||
continuous: false, | ||
debug: false, | ||
disableBeacon: false, | ||
disableCloseOnEsc: false, | ||
disableOverlay: false, | ||
disableOverlayClicks: false, | ||
disableOverlayClose: false, | ||
disableScrolling: false, | ||
hideBackButton: false, | ||
holePadding: 10, | ||
run: false, | ||
@@ -93,2 +90,4 @@ scrollOffset: 20, | ||
showProgress: false, | ||
spotlightClicks: false, | ||
spotlightPadding: 10, | ||
steps: [], | ||
@@ -181,12 +180,4 @@ }; | ||
if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) { | ||
if (![STATUS.FINISHED, STATUS.SKIPPED].includes(status)) { | ||
update({ | ||
action: ACTIONS.START, | ||
index: nextStepIndex, | ||
lifecycle: LIFECYCLE.INIT, | ||
status: run && STATUS.RUNNING, | ||
}); | ||
} | ||
else { | ||
update({ | ||
action: action === ACTIONS.CLOSE ? ACTIONS.CLOSE : nextAction, | ||
@@ -386,3 +377,3 @@ index: nextStepIndex, | ||
else { | ||
scrollY -= step.holePadding; | ||
scrollY -= step.spotlightPadding; | ||
} | ||
@@ -459,3 +450,2 @@ } | ||
helpers={this.helpers} | ||
locale={this.locale} | ||
step={step} | ||
@@ -462,0 +452,0 @@ update={this.store.update} |
@@ -18,3 +18,3 @@ import React from 'react'; | ||
import Hole from './Hole'; | ||
import Spotlight from './Spotlight'; | ||
@@ -26,5 +26,5 @@ export default class Overlay extends React.Component { | ||
this.state = { | ||
mouseOverHole: false, | ||
mouseOverSpotlight: false, | ||
isScrolling: false, | ||
showHole: false, | ||
showSpotlight: false, | ||
}; | ||
@@ -34,8 +34,8 @@ } | ||
static propTypes = { | ||
allowClicksThruHole: PropTypes.bool.isRequired, | ||
disableOverlay: PropTypes.bool.isRequired, | ||
disableScrolling: PropTypes.bool.isRequired, | ||
holePadding: PropTypes.number, | ||
lifecycle: PropTypes.string.isRequired, | ||
onClickOverlay: PropTypes.func.isRequired, | ||
spotlightClicks: PropTypes.bool.isRequired, | ||
spotlightPadding: PropTypes.number, | ||
styles: PropTypes.object.isRequired, | ||
@@ -59,3 +59,3 @@ target: PropTypes.oneOfType([ | ||
const { isScrolling } = this.state; | ||
const { allowClicksThruHole, disableScrolling, lifecycle } = nextProps; | ||
const { spotlightClicks, disableScrolling, lifecycle } = nextProps; | ||
const { changed, changedTo } = treeChanges(this.props, nextProps); | ||
@@ -69,3 +69,3 @@ | ||
if (!isScrolling) { | ||
this.setState({ showHole: true }); | ||
this.setState({ showSpotlight: true }); | ||
} | ||
@@ -76,4 +76,4 @@ }, 30); | ||
if (changed('allowClicksThruHole') || changed('disableOverlay') || changed('lifecycle')) { | ||
if (allowClicksThruHole && lifecycle === LIFECYCLE.TOOLTIP) { | ||
if (changed('spotlightClicks') || changed('disableOverlay') || changed('lifecycle')) { | ||
if (spotlightClicks && lifecycle === LIFECYCLE.TOOLTIP) { | ||
document.addEventListener('mousemove', this.handleMouseMove, false); | ||
@@ -94,13 +94,13 @@ } | ||
handleMouseMove = (e) => { | ||
const { mouseOverHole } = this.state; | ||
const { height, left, position, top, width } = this.stylesHole; | ||
const { mouseOverSpotlight } = this.state; | ||
const { height, left, position, top, width } = this.stylesSpotlight; | ||
const offsetY = position === 'fixed' ? e.clientY : e.pageY; | ||
const offsetX = position === 'fixed' ? e.clientX : e.pageX; | ||
const inHoleHeight = (offsetY >= top && offsetY <= top + height); | ||
const inHoleWidth = (offsetX >= left && offsetX <= left + width); | ||
const inHole = inHoleWidth && inHoleHeight; | ||
const inSpotlightHeight = (offsetY >= top && offsetY <= top + height); | ||
const inSpotlightWidth = (offsetX >= left && offsetX <= left + width); | ||
const inSpotlight = inSpotlightWidth && inSpotlightHeight; | ||
if (inHole !== mouseOverHole) { | ||
this.setState({ mouseOverHole: inHole }); | ||
if (inSpotlight !== mouseOverSpotlight) { | ||
this.setState({ mouseOverSpotlight: inSpotlight }); | ||
} | ||
@@ -111,3 +111,3 @@ }; | ||
if (!this.state.isScrolling) { | ||
this.setState({ isScrolling: true, showHole: false }); | ||
this.setState({ isScrolling: true, showSpotlight: false }); | ||
} | ||
@@ -119,3 +119,3 @@ | ||
clearTimeout(this.scrollTimeout); | ||
this.setState({ isScrolling: false, showHole: true }); | ||
this.setState({ isScrolling: false, showSpotlight: true }); | ||
this.scrollParent.removeEventListener('scroll', this.handleScroll); | ||
@@ -125,20 +125,20 @@ }, 50); | ||
get stylesHole() { | ||
const { showHole } = this.state; | ||
const { allowClicksThruHole, holePadding, styles, target } = this.props; | ||
get stylesSpotlight() { | ||
const { showSpotlight } = this.state; | ||
const { spotlightClicks, spotlightPadding, styles, target } = this.props; | ||
const element = getElement(target); | ||
const elementRect = getClientRect(element); | ||
const isFixedTarget = isFixed(target); | ||
const top = getElementPosition(element, holePadding); | ||
const top = getElementPosition(element, spotlightPadding); | ||
return { | ||
...(isLegacy() ? styles.holeLegacy : styles.hole), | ||
height: Math.round(elementRect.height + (holePadding * 2)), | ||
left: Math.round(elementRect.left - holePadding), | ||
opacity: showHole ? 1 : 0, | ||
pointerEvents: allowClicksThruHole ? 'none' : 'auto', | ||
...(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, | ||
transition: 'opacity 0.2s', | ||
width: Math.round(elementRect.width + (holePadding * 2)), | ||
width: Math.round(elementRect.width + (spotlightPadding * 2)), | ||
}; | ||
@@ -148,7 +148,7 @@ } | ||
render() { | ||
const { showHole } = this.state; | ||
const { showSpotlight } = this.state; | ||
const { | ||
allowClicksThruHole, | ||
spotlightClicks, | ||
disableOverlay, | ||
holePadding, | ||
spotlightPadding, | ||
lifecycle, | ||
@@ -168,3 +168,3 @@ onClickOverlay, | ||
height: getDocumentHeight(), | ||
pointerEvents: this.state.mouseOverHole ? 'none' : 'auto', | ||
pointerEvents: this.state.mouseOverSpotlight ? 'none' : 'auto', | ||
...(isLegacy() ? styles.overlayLegacy : styles.overlay), | ||
@@ -179,11 +179,11 @@ }; | ||
> | ||
{showHole && ( | ||
<Hole | ||
allowClicksThruHole={allowClicksThruHole} | ||
holePadding={holePadding} | ||
{showSpotlight && ( | ||
<Spotlight | ||
spotlightClicks={spotlightClicks} | ||
spotlightPadding={spotlightPadding} | ||
target={target} | ||
styles={this.stylesHole} | ||
styles={this.stylesSpotlight} | ||
/> | ||
)} | ||
{output.hole} | ||
{output.spotlight} | ||
</div> | ||
@@ -190,0 +190,0 @@ ); |
@@ -33,3 +33,2 @@ import React from 'react'; | ||
step: PropTypes.shape({ | ||
allowClicksThruHole: PropTypes.bool, | ||
beaconComponent: PropTypes.oneOfType([ | ||
@@ -42,6 +41,5 @@ PropTypes.func, | ||
disableOverlay: PropTypes.bool, | ||
disableOverlayClicks: PropTypes.bool, | ||
disableOverlayClose: PropTypes.bool, | ||
event: PropTypes.string, | ||
hideBackButton: PropTypes.bool, | ||
holePadding: PropTypes.number, | ||
isFixed: PropTypes.bool, | ||
@@ -57,2 +55,4 @@ locale: PropTypes.object, | ||
]), | ||
spotlightClicks: PropTypes.bool, | ||
spotlightPadding: PropTypes.number, | ||
target: PropTypes.oneOfType([ | ||
@@ -130,3 +130,3 @@ PropTypes.object, | ||
if (!step.disableOverlayClicks) { | ||
if (!step.disableOverlayClose) { | ||
this.props.helpers.close(); | ||
@@ -133,0 +133,0 @@ } |
@@ -31,13 +31,11 @@ import React from 'react'; | ||
let tabIndex = 0; | ||
if (showSkipButton && !isLastStep) { | ||
output.skip = (<button style={styles.buttonSkip} {...skipProps} tabIndex={++tabIndex}>{skip}</button>); | ||
output.skip = (<button style={styles.buttonSkip} {...skipProps}>{skip}</button>); | ||
} | ||
if (!hideBackButton && index > 0) { | ||
output.back = (<button style={styles.buttonBack} {...backProps} tabIndex={++tabIndex}>{back}</button>); | ||
output.back = (<button style={styles.buttonBack} {...backProps}>{back}</button>); | ||
} | ||
output.close = (<CloseBtn {...closeProps} styles={styles.buttonClose} tabIndex={++tabIndex} />); | ||
output.close = (<CloseBtn {...closeProps} styles={styles.buttonClose} />); | ||
@@ -61,3 +59,3 @@ return ( | ||
{output.back} | ||
<button style={styles.buttonNext} {...primaryProps} tabIndex={++tabIndex}>{output.primary}</button> | ||
<button style={styles.buttonNext} {...primaryProps}>{output.primary}</button> | ||
</div> | ||
@@ -64,0 +62,0 @@ </div> |
@@ -37,4 +37,3 @@ import type { Node } from 'react'; | ||
export type StepObject = { | ||
allowClicksThruHole: boolean, | ||
export type StepProps = { | ||
beaconComponent: ?Node, | ||
@@ -45,7 +44,6 @@ content: Node | string, | ||
disableOverlay: boolean, | ||
disableOverlayClicks: boolean, | ||
disableOverlayClose: boolean, | ||
disableScrolling: boolean, | ||
event: string, | ||
hideBackButton: ?boolean, | ||
holePadding: number, | ||
isFixed: ?boolean, | ||
@@ -56,2 +54,4 @@ offset: number, | ||
showSkipButton: ?boolean, | ||
spotlightPadding: number, | ||
spotlightClicks: boolean, | ||
styles: ?Object, | ||
@@ -64,14 +64,12 @@ target: string | HTMLElement, | ||
export type TourObject = { | ||
allowClicksThruHole: boolean, | ||
export type JoyrideProps = { | ||
beaconComponent: ?Node, | ||
callback: ?Function, | ||
continuous: boolean, | ||
debug: boolean, | ||
disableBeacon: boolean, | ||
disableCloseOnEsc: boolean, | ||
disableOverlay: boolean, | ||
disableOverlayClicks: boolean, | ||
disableOverlayClose: boolean, | ||
disableScrolling: boolean, | ||
hideBackButton: boolean, | ||
holePadding: boolean, | ||
locale: ?Object, | ||
@@ -83,6 +81,20 @@ run: boolean, | ||
showSkipButton: boolean, | ||
spotlightPadding: boolean, | ||
spotlightClicks: boolean, | ||
stepIndex: ?number, | ||
steps: Array<StepObject>, | ||
steps: Array<StepProps>, | ||
styles: ?Object, | ||
tooltipComponent: ?Node, | ||
tooltipOptions: ?Object, | ||
} | ||
export type CallBackProps = { | ||
action: string, | ||
controlled: boolean, | ||
index: number, | ||
lifecycle: string, | ||
size: number, | ||
status: string, | ||
step: StepProps, | ||
type: string, | ||
} |
@@ -5,13 +5,9 @@ export default { | ||
BEACON: 'beacon', | ||
BEACON_TRIGGER: 'beacon:trigger', | ||
TOOLTIP: 'tooltip', | ||
TOOLTIP_SKIP: 'tooltip:skip', | ||
TOOLTIP_CLOSE: 'tooltip:close', | ||
OVERLAY_CLICK: 'overlay:click', | ||
HOLE_CLICK: 'hole:click', | ||
STEP_AFTER: 'step:after', | ||
TOUR_END: 'tour:end', | ||
// these usually don't happen in a normal tour | ||
TOUR_STATUS: 'tour:status', | ||
TARGET_NOT_FOUND: 'error:target_not_found', | ||
ERROR: 'error', | ||
TOUR_END: 'tour:end', | ||
}; |
@@ -173,4 +173,6 @@ // @flow | ||
stop = (advance = false) => { | ||
const { index } = this.getState(); | ||
const { index, status } = this.getState(); | ||
if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) return; | ||
this.setState({ | ||
@@ -177,0 +179,0 @@ ...this.getNextState({ action: ACTIONS.STOP, index: index + (advance ? 1 : 0) }), |
@@ -11,3 +11,3 @@ // @flow | ||
import type { StepObject, TourObject } from '../config/types'; | ||
import type { StepProps, JoyrideProps } from '../config/types'; | ||
@@ -22,3 +22,3 @@ /** | ||
*/ | ||
export function validateStep(step: StepObject, debug: boolean = false): boolean { | ||
export function validateStep(step: StepProps, debug: boolean = false): boolean { | ||
if (!is.plainObject(step)) { | ||
@@ -70,16 +70,15 @@ log({ | ||
function getTourProps(props: TourObject): TourObject { | ||
function getTourProps(props: JoyrideProps): JoyrideProps { | ||
const sharedTourProps = [ | ||
'allowClicksThruHole', | ||
'beaconComponent', | ||
'disableBeacon', | ||
'disableCloseOnEsc', | ||
'disableOverlay', | ||
'disableOverlayClicks', | ||
'disableOverlayClose', | ||
'disableScrolling', | ||
'hideBackButton', | ||
'holePadding', | ||
'locale', | ||
'showProgress', | ||
'showSkipButton', | ||
'spotlightClicks', | ||
'spotlightPadding', | ||
'styles', | ||
@@ -99,3 +98,3 @@ 'tooltipComponent', | ||
export function getMergedStep(step: StepObject, props: TourObject): StepObject { | ||
export function getMergedStep(step: StepProps, props: JoyrideProps): StepProps { | ||
if (!step) return undefined; | ||
@@ -110,3 +109,3 @@ | ||
if (!mergedStep.disableScrolling) { | ||
tooltipOptions.offset += props.holePadding || step.holePadding || 0; | ||
tooltipOptions.offset += props.spotlightPadding || step.spotlightPadding || 0; | ||
} | ||
@@ -113,0 +112,0 @@ |
@@ -7,3 +7,3 @@ import deepmerge from 'deepmerge'; | ||
overlayColor: 'rgba(0, 0, 0, 0.5)', | ||
holeShadow: '0 0 15px rgba(0, 0, 0, 0.5)', | ||
spotlightShadow: '0 0 15px rgba(0, 0, 0, 0.5)', | ||
beaconSize: 36, | ||
@@ -33,3 +33,3 @@ zIndex: 100, | ||
const hole = { | ||
const spotlight = { | ||
borderRadius: 4, | ||
@@ -148,9 +148,9 @@ position: 'absolute', | ||
}, | ||
hole: { | ||
...hole, | ||
spotlight: { | ||
...spotlight, | ||
backgroundColor: 'gray', | ||
}, | ||
holeLegacy: { | ||
...hole, | ||
boxShadow: `0 0 0 9999px ${options.overlayColor}, ${options.holeShadow}`, | ||
spotlightLegacy: { | ||
...spotlight, | ||
boxShadow: `0 0 0 9999px ${options.overlayColor}, ${options.spotlightShadow}`, | ||
}, | ||
@@ -157,0 +157,0 @@ }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
206480
83
5986