Repository: shipshapecode/react-shepherd
Branch: master
Commit: 518829fdcb0c
Files: 37
Total size: 49.3 KB
Directory structure:
gitextract_rt5270q3/
├── .babelrc
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── ghpages.yml
│ ├── publish.yml
│ └── test.yml
├── .gitignore
├── .nvmrc
├── CHANGELOG.md
├── README.md
├── RELEASE.md
├── netlify.toml
├── package.json
└── packages/
├── example/
│ ├── .eslintrc.json
│ ├── README.md
│ ├── astro.config.mjs
│ ├── jsconfig.json
│ ├── package.json
│ └── src/
│ ├── components/
│ │ ├── home.astro
│ │ └── tour.jsx
│ ├── css/
│ │ ├── duotone.css
│ │ ├── index.css
│ │ └── welcome.css
│ ├── env.d.ts
│ ├── pages/
│ │ └── index.astro
│ └── steps.js
└── lib/
├── .eslintrc.js
├── CHANGELOG.md
├── README.md
├── jest.config.js
├── package.json
├── rollup.config.js
├── src/
│ ├── __tests__/
│ │ └── shepherd.test.tsx
│ ├── index.tsx
│ └── styles.css
├── tsconfig-declarations.json
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [
["@babel/env", {
"modules": false
}],
"@babel/react"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-external-helpers",
"@babel/plugin-proposal-function-bind"
]
}
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: npm
directory: "/packages/lib"
schedule:
interval: weekly
time: "10:00"
open-pull-requests-limit: 10
labels:
- dependencies
================================================
FILE: .github/workflows/ghpages.yml
================================================
name: Build and GH Pages Deploy
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: 16
# Cache dependencies
- name: Cache Dependencies
uses: actions/cache@v2
id: cache
with:
path: |
**/node_modules
key: yarn-${{ hashFiles('**/package.json', 'yarn.lock') }}
# Install project dependencies
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: yarn
- name: Build Shepherd
run: yarn build
# Build the example site
- name: Build Site
run: |
yarn
yarn build
working-directory: ./packages/example
- name: GitHub Pages
if: success()
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: packages/example/out
================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish to NPM
on:
push:
tags:
- v*
jobs:
publish:
name: Build and Publissh
runs-on: ubuntu-latest
env:
NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
steps:
# Checkout the repo
- name: Checkout
uses: actions/checkout@v2
# Setup Node.js build environment
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 16
# Cache dependencies
- name: Cache Dependencies
uses: actions/cache@v2
id: cache
with:
path: |
**/node_modules
key: yarn-${{ hashFiles('**/package.json', 'yarn.lock') }}
# Install project dependencies
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: yarn
- name: Build
run: yarn build
- name: Generate .npmrc
run: echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > .npmrc
- name: Release version
run: yarn release --ci --npm.skipChecks
env:
GITHUB_AUTH: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/test.yml
================================================
name: Test
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
# Checkout the repo
- name: Checkout
uses: actions/checkout@v1
# Setup Node.js build environment
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: 16
# Cache dependencies
- name: Cache Dependencies
uses: actions/cache@v2
id: cache
with:
path: |
**/node_modules
key: yarn-${{ hashFiles('**/package.json', 'yarn.lock') }}
# Install project dependencies
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: yarn
# Run linter
- name: Lint
run: yarn lint
# Run tests
- name: Run Tests
run: yarn test
================================================
FILE: .gitignore
================================================
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
node_modules
# builds
build
dist
out
.next
.rpt2_cache
# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: .nvmrc
================================================
16.13.1
================================================
FILE: CHANGELOG.md
================================================
## v4.1.0 (2022-07-07)
## v4.0.1 (2022-07-06)
#### :bug: Bug Fix
* `lib`
* [#637](https://github.com/shipshapecode/react-shepherd/pull/637) Add children field for React 18 ([@andersaamodt](https://github.com/andersaamodt))
#### Committers: 2
- Anders ([@andersaamodt](https://github.com/andersaamodt))
- Chuck Carpenter ([@chuckcarpenter](https://github.com/chuckcarpenter))
## v4.0.0 (2022-06-24)
## v3.3.7 (2022-06-24)
## v3.3.6 (2021-11-02)
## v3.3.4 (2021-10-29)
================================================
FILE: README.md
================================================
**This repository is no longer being maintained and all further development is at the main [shepherd](https://github.com/shepherd-pro/shepherd/tree/main/packages/react) repo.**
# react-shepherd
<div>
<a href="https://shipshape.io">
<img align="left" src="http://i.imgur.com/DWHQjA5.png" alt="Ship Shape" width="50" height="50"/>
</a>
**[react-shepherd is built and maintained by Ship Shape. Contact us for web app consulting, development, and training for your project](https://shipshape.io/)**.
</div>
[](https://www.npmjs.com/package/react-shepherd)
[](https://github.com/shipshapecode/react-shepherd/actions?query=workflow%3ATest)
[](https://codeclimate.com/github/shipshapecode/react-shepherd/maintainability)
[](https://codeclimate.com/github/shipshapecode/react-shepherd/test_coverage)
[](https://standardjs.com)
This is a React wrapper for the [Shepherd](https://github.com/shipshapecode/shepherd), site tour, library.
It's mainly a wrapper around the Shepherd library that exposes the tour object and methods to the context object
that can be passed into props for dynamic interactivity.
## Install
```bash
npm install --save react-shepherd
```
## Usage
### Via Provider/Context
```jsx
import React, { Component, useContext } from "react";
import { ShepherdTour, ShepherdTourContext } from "react-shepherd";
import newSteps from "./steps";
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true,
},
},
useModalOverlay: true,
};
function Button() {
const tour = useContext(ShepherdTourContext);
return (
<button className="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
export default function App() {
return (
<div>
<ShepherdTour steps={newSteps} tourOptions={tourOptions}>
<Button />
</ShepherdTour>
</div>
);
}
```
### Via Hook
```jsx
import React, { Component } from "react";
import { useShepherdTour } from "react-shepherd";
import newSteps from "./steps";
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true,
},
},
useModalOverlay: true,
};
export default function App() {
const tour = useShepherdTour({ tourOptions, steps: newSteps });
return (
<button class="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
```
## Configuration
The following configuration options for a tour can be set on the ShepherdTour to control the way that Shepherd is used. This is simply a POJO passed to Shepherd to use the options noted in the Shepherd Tour [options](https://shepherdjs.dev/docs/Tour.html).
**The only required option is `steps`, which is an array passed to the props.**
### tourOptions
`PropTypes.object`
Used to set the options that will be applied to each step by default. You can pass in any of the options that you can with Shepherd.
### steps
`PropTypes.array`
You must pass an array of steps to `steps`, something like this:
```js
const steps = [
{
id: 'intro',
attachTo: { element: '.first-element', on: 'bottom' },
beforeShowPromise: function () {
return new Promise(function (resolve) {
setTimeout(function () {
window.scrollTo(0, 0);
resolve();
}, 500);
});
},
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Exit',
type: 'cancel'
},
{
classes: 'shepherd-button-primary',
text: 'Back',
type: 'back'
},
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
}
],
classes: 'custom-class-name-1 custom-class-name-2',
highlightClass: 'highlight',
scrollTo: false,
cancelIcon: {
enabled: true,
},
title: 'Welcome to React-Shepherd!',
text: ['React-Shepherd is a JavaScript library for guiding users through your React app.'],
when: {
show: () => {
console.log('show step');
},
hide: () => {
console.log('hide step');
}
}
},
// ...
];
```
## Steps
The options are the same as Shepherd [options](https://shepherdjs.dev/docs/Step.html).
## License
MIT
================================================
FILE: RELEASE.md
================================================
# Release
Releases are mostly automated using
[release-it](https://github.com/release-it/release-it/) and
[lerna-changelog](https://github.com/lerna/lerna-changelog/).
## Preparation
Since the majority of the actual release process is automated, the primary
remaining task prior to releasing is confirming that all pull requests that
have been merged since the last release have been labeled with the appropriate
`lerna-changelog` labels and the titles have been updated to ensure they
represent something that would make sense to our users. Some great information
on why this is important can be found at
[keepachangelog.com](https://keepachangelog.com/en/1.0.0/), but the overall
guiding principle here is that changelogs are for humans, not machines.
When reviewing merged PR's the labels to be used are:
* breaking - Used when the PR is considered a breaking change.
* enhancement - Used when the PR adds a new feature or enhancement.
* bug - Used when the PR fixes a bug included in a previous release.
* documentation - Used when the PR adds or updates documentation.
* internal - Used for internal changes that still require a mention in the
changelog/release notes.
## Release
Once the prep work is completed, the actual release is straight forward:
* First, ensure that you have installed your projects dependencies:
```
yarn install
```
* Second, ensure that you have obtained a
[GitHub personal access token][generate-token] with the `repo` scope (no
other permissions are needed). Make sure the token is available as the
`GITHUB_AUTH` environment variable.
For instance:
```bash
export GITHUB_AUTH=abc123def456
```
[generate-token]: https://github.com/settings/tokens/new?scopes=repo&description=GITHUB_AUTH+env+variable
* And last (but not least 😁) do your release.
```
npx release-it
```
[release-it](https://github.com/release-it/release-it/) manages the actual
release process. It will prompt you to to choose the version number after which
you will have the chance to hand tweak the changelog to be used (for the
`CHANGELOG.md` and GitHub release), then `release-it` continues on to tagging,
pushing the tag and commits, etc.
================================================
FILE: netlify.toml
================================================
[build]
command = "yarn build && cd packages/example && yarn build"
publish = "packages/example/dist"
================================================
FILE: package.json
================================================
{
"repository": {
"type": "git",
"url": "https://github.com/shipshapecode/react-shepherd.git"
},
"private": true,
"workspaces": [
"packages/**/*"
],
"devDependencies": {
"npm-run-all": "^4.1.5",
"release-it-yarn-workspaces": "^2.0.1"
},
"scripts": {
"build": "yarn workspace react-shepherd build",
"release": "yarn workspace react-shepherd release",
"start:lib": "yarn workspace react-shepherd start",
"start:site": "yarn workspace react-shepherd-example dev",
"start": "run-p start:*",
"lint": "yarn workspace react-shepherd lint",
"test": "yarn workspace react-shepherd test"
},
"release-it": {
"plugins": {
"release-it-yarn-workspaces": {
"workspaces": [
"packages/lib"
]
},
"release-it-lerna-changelog": {
"infile": "CHANGELOG.md",
"launchEditor": true
}
},
"git": {
"tagName": "v${version}"
},
"github": {
"release": true,
"tokenRef": "GITHUB_AUTH"
},
"npm": false
}
}
================================================
FILE: packages/example/.eslintrc.json
================================================
{
"extends": "next"
}
================================================
FILE: packages/example/README.md
================================================
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
================================================
FILE: packages/example/astro.config.mjs
================================================
import { defineConfig } from 'astro/config';
import react from "@astrojs/react";
// https://astro.build/config
export default defineConfig({
site: "https://shipshape-react-shepherd.netlify.app/",
integrations: [react()],
});
================================================
FILE: packages/example/jsconfig.json
================================================
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@components/*": ["components/*"],
"@css/*": ["css/*"]
}
}
}
================================================
FILE: packages/example/package.json
================================================
{
"name": "react-shepherd-example",
"homepage": "https://shipshapecode.github.io/react-shepherd",
"version": "0.0.0",
"license": "MIT",
"private": true,
"dependencies": {
"@astrojs/prism": "^2.1.2",
"@astrojs/react": "^2.2.1",
"astro": "^2.10.7",
"react": "latest",
"react-dom": "latest",
"react-syntax-highlighter": "^15.5.0"
},
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
}
}
================================================
FILE: packages/example/src/components/home.astro
================================================
---
import { Prism } from '@astrojs/prism';
import Tour from './tour';
const installString = 'yarn add react-shepherd';
const componentSetupString = `
import React, { Component } from 'react'
import { useShepherdTour } from 'react-shepherd'
import newSteps from './steps'
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true
}
},
useModalOverlay: true
};
`;
const usageString = `
${componentSetupString}
function Button() {
const tour = useContext(ShepherdTourContext);
return (
<button className="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
class App extends Component {
render() {
return (
<div>
<ShepherdTour steps={newSteps} tourOptions={tourOptions}>
<Button />
</ShepherdTour>
</div>
);
}
`;
const usageHoookString = `
${componentSetupString}
export default function App() {
const tour = useShepherdTour({ tourOptions, steps: newSteps });
return (
<button class="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
`;
---
<div>
<div>
<div>
<Tour client:only="react" />
<div>
<h5>Installation</h5>
<Prism lang="js" code={installString} />
</div>
<div>
<h5>Usage via Provider/Context</h5>
<Prism lang="js" code={usageString} />
</div>
<div>
<h5>Usage via Hooks</h5>
<Prism lang="js" code={usageHoookString} />
</div>
</div>
</div>
</div>
================================================
FILE: packages/example/src/components/tour.jsx
================================================
import { useShepherdTour } from '../../../lib/dist/Shepherd.es';
import newSteps from '../steps';
import 'shepherd.js/dist/css/shepherd.css';
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true
}
},
useModalOverlay: true
};
export default function Tour() {
const tour = useShepherdTour({ tourOptions, steps: newSteps });
return (
<button class="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
================================================
FILE: packages/example/src/css/duotone.css
================================================
/*
Name: Duotone Light
Author: Simurai, adapted from DuoTone themes for Atom (http://simurai.com/projects/2016/01/01/duotone-themes)
Conversion: Bram de Haan (http://atelierbram.github.io/Base2Tone-prism/output/prism/prism-base2tone-morning-light.css)
Generated with Base16 Builder (https://github.com/base16-builder/base16-builder)
*/
code[class*="language-"],
pre[class*="language-"] {
font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace;
font-size: 14px;
line-height: 1.375;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
background: #faf8f5;
color: #728fcb;
}
pre > code[class*="language-"] {
font-size: 1em;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #faf8f5;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #faf8f5;
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #b6ad9a;
}
.token.punctuation {
color: #b6ad9a;
}
.token.namespace {
opacity: .7;
}
.token.tag,
.token.operator,
.token.number {
color: #063289;
}
.token.property,
.token.function {
color: #b29762;
}
.token.tag-id,
.token.selector,
.token.atrule-id {
color: #2d2006;
}
code.language-javascript,
.token.attr-name {
color: #896724;
}
code.language-css,
code.language-scss,
.token.boolean,
.token.string,
.token.entity,
.token.url,
.language-css .token.string,
.language-scss .token.string,
.style .token.string,
.token.attr-value,
.token.keyword,
.token.control,
.token.directive,
.token.unit,
.token.statement,
.token.regex,
.token.atrule {
color: #728fcb;
}
.token.placeholder,
.token.variable {
color: #93abdc;
}
.token.deleted {
text-decoration: line-through;
}
.token.inserted {
border-bottom: 1px dotted #2d2006;
text-decoration: none;
}
.token.italic {
font-style: italic;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.important {
color: #896724;
}
.token.entity {
cursor: help;
}
pre > code.highlight {
outline: .4em solid #896724;
outline-offset: .4em;
}
/* overrides color-values for the Line Numbers plugin
* http://prismjs.com/plugins/line-numbers/
*/
.line-numbers.line-numbers .line-numbers-rows {
border-right-color: #ece8de;
}
.line-numbers .line-numbers-rows > span:before {
color: #cdc4b1;
}
/* overrides color-values for the Line Highlight plugin
* http://prismjs.com/plugins/line-highlight/
*/
.line-highlight.line-highlight {
background: rgba(45, 32, 6, 0.2);
background: -webkit-linear-gradient(left, rgba(45, 32, 6, 0.2) 70%, rgba(45, 32, 6, 0));
background: linear-gradient(to right, rgba(45, 32, 6, 0.2) 70%, rgba(45, 32, 6, 0));
}
================================================
FILE: packages/example/src/css/index.css
================================================
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
================================================
FILE: packages/example/src/css/welcome.css
================================================
html, body {
height: 100%;
}
body {
background-color: #61dbfb;
background-image: linear-gradient(-45deg, #61dbfb, #1a8598);
font-family: "proxima-nova", "Helvetica Neue", sans-serif;
margin: 0;
}
.button {
border: 2px solid #ffffff;
color: #ffffff;
cursor: pointer;
display: inline-block;
font-size: 0.8em;
font-weight: 500;
letter-spacing: 3px;
line-height: 1.3em;
padding: 1em 1.25em;
text-decoration: none;
text-transform: uppercase;
width: 140px;
}
.button.dark {
background: #ffffff;
color: #212047;
}
button.button {
background: transparent;
width: auto;
}
@media (max-width: 568px) {
.button {
display: block;
margin: 1em auto 0;
}
}
.hero-scroll {
height: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
width: 100%;
}
.hero-outer {
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: table;
height: 100%;
padding: 20px 0;
width: 100%;
}
.hero-outer .hero-inner {
margin: 0 auto 1em;
text-align: center;
width: 840px;
}
@media (max-width: 600px) {
.hero-outer .hero-inner {
width: 340px;
}
}
@media (max-width: 360px) {
.hero-outer .hero-inner {
width: 200px;
}
}
.hero-outer .hero-inner h1, .hero-outer .hero-inner h2, .hero-outer .hero-inner h3, .hero-outer .hero-inner p {
color: #ffffff;
font-weight: normal;
line-height: 1;
margin: 0 0 20px;
}
.hero-outer .hero-inner h3 {
font-size: 1.3em;
padding-top: 13px;
}
.hero-outer .hero-inner h1 {
padding-top: 10px;
}
.hero-outer .hero-followup {
padding-top: 20px;
}
pre {
border: 1px solid rgba(0, 0, 0, 0.15);
background-color: rgba(255, 255, 255, 0.15);
border-color: #d8d8d8;
line-height: 1.4em;
text-align: left;
}
/* stylelint-disable selector-max-id */
#shepherdModalOverlayContainer {
-ms-filter: "progid:dximagetransform.microsoft.gradient.alpha(Opacity=50)";
filter: alpha(opacity=50);
height: 100%;
left: 0;
opacity: 0.5;
position: fixed;
top: 0;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
width: 100%;
z-index: 9997;
}
.shepherd-modal.shepherd-enabled {
position: relative;
z-index: 9998;
}
/**
* Block clicks except for those that would occur
* on Shepherd elements or on the target element.
*/
.shepherd-active.shepherd-modal-is-visible :not(.shepherd-target) {
pointer-events: none;
}
.shepherd-active.shepherd-modal-is-visible .shepherd-target, .shepherd-active.shepherd-modal-is-visible .shepherd-cancel-link, .shepherd-active.shepherd-modal-is-visible .shepherd-button {
pointer-events: auto;
}
/* stylelint-enable */
/**
* Styles to support usage of Tippy.js tooltips (https://atomiks.github.io/tippyjs)
*/
/**
* Tippy tooltips have the following base structure:
*
* <div class="tippy-popper" x-placement="top">
* <div class="tippy-tooltip">
* <div class="tippy-content">
* [[ Content Here ]]
* </div>
* </div>
* </div>
*/
.tippy-popper {
z-index: 9999;
}
.tippy-popper .tippy-arrow {
border: 16px solid transparent;
content: '';
display: block;
height: 0;
pointer-events: none;
position: absolute;
width: 0;
}
.tippy-popper[x-placement^='top'] {
margin-bottom: 16px;
}
.tippy-popper[x-placement^='top'] .tippy-arrow {
border-bottom: 0;
border-top-color: #ffffff;
left: calc(50% - 16px);
}
.tippy-popper[x-placement^='bottom'] {
margin-top: 16px;
}
.tippy-popper[x-placement^='bottom'] .tippy-arrow {
border-bottom-color: #eeeeee;
border-top: 0;
left: calc(50% - 16px);
}
.tippy-popper[x-placement^='left'] {
margin-right: 16px;
}
.tippy-popper[x-placement^='left'] .tippy-arrow {
border-left-color: #ffffff;
border-right: 0;
margin-top: -16px;
top: calc(50% - 16px);
}
.tippy-popper[x-placement^='right'] {
margin-left: 16px;
}
.tippy-popper[x-placement^='right'] .tippy-arrow {
border-left: 0;
border-right-color: #ffffff;
top: calc(50% - 16px);
}
.tippy-popper .tippy-tooltip {
background-color: rgba(0, 0, 0, 0);
max-height: 100%;
max-width: 100%;
padding: 0;
width: 420px;
}
.shepherd-element, .shepherd-element:after, .shepherd-element:before, .shepherd-element *, .shepherd-element *:after, .shepherd-element *:before {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.shepherd-element {
-webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
}
.shepherd-element.shepherd-has-title .shepherd-content header {
background: #eeeeee;
padding: 1em;
}
.shepherd-element .shepherd-content {
background: #ffffff;
font-size: inherit;
padding: 0;
}
.shepherd-element .shepherd-content header {
*zoom: 1;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: flex-end;
line-height: 2em;
padding: 0.75em 0.75em 0;
}
.shepherd-element .shepherd-content header:after {
clear: both;
content: '';
display: table;
}
.shepherd-element .shepherd-content header .shepherd-title, .shepherd-element .shepherd-content header .shepherd-cancel-link {
font-weight: normal;
margin: 0;
padding: 0;
position: relative;
vertical-align: middle;
}
.shepherd-element .shepherd-content header .shepherd-title {
color: rgba(0, 0, 0, 0.75);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 1;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
font-size: 1.1em;
}
.shepherd-element .shepherd-content header .shepherd-cancel-link {
color: rgba(179, 179, 179, 0.75);
font-size: 2em;
margin-left: auto;
text-decoration: none;
-webkit-transition: color 0.5s ease;
transition: color 0.5s ease;
}
.shepherd-element .shepherd-content header .shepherd-cancel-link:before {
content: '\00d7';
}
.shepherd-element .shepherd-content header .shepherd-cancel-link:hover {
color: rgba(0, 0, 0, 0.75);
}
.shepherd-element .shepherd-content .shepherd-text {
color: rgba(0, 0, 0, 0.75);
line-height: 1.3em;
padding: 0.75em;
}
.shepherd-element .shepherd-content .shepherd-text a, .shepherd-element .shepherd-content .shepherd-text a:visited, .shepherd-element .shepherd-content .shepherd-text a:active {
border-bottom: 1px dotted;
border-bottom-color: rgba(0, 0, 0, 0.75);
color: rgba(0, 0, 0, 0.75);
text-decoration: none;
}
.shepherd-element .shepherd-content .shepherd-text a:hover, .shepherd-element .shepherd-content .shepherd-text a:visited:hover, .shepherd-element .shepherd-content .shepherd-text a:active:hover {
border-bottom-style: solid;
}
.shepherd-element .shepherd-content .shepherd-text p {
margin-top: 0;
}
.shepherd-element .shepherd-content .shepherd-text p:last-child {
margin-bottom: 0;
}
.shepherd-element .shepherd-content footer {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
padding: 0 0.75em 0.75em;
}
.shepherd-element .shepherd-content footer .shepherd-buttons {
list-style: none;
margin: 0;
padding: 0;
text-align: right;
}
.shepherd-element .shepherd-content footer .shepherd-buttons li {
display: inline;
margin: 0 0.5em 0 0;
}
.shepherd-element .shepherd-content footer .shepherd-buttons li:last-child {
margin-right: 0;
}
.shepherd-element .shepherd-content footer .shepherd-buttons li .shepherd-button {
display: inline-block;
*display: inline;
vertical-align: middle;
*vertical-align: auto;
*zoom: 1;
background: #557ca8;
border: 0;
border-radius: 3px;
color: rgba(255, 255, 255, 0.75);
cursor: pointer;
font-family: inherit;
font-size: 0.8em;
letter-spacing: 0.1em;
line-height: 1em;
padding: 0.75em 2em;
text-transform: uppercase;
-webkit-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.shepherd-element .shepherd-content footer .shepherd-buttons li .shepherd-button:hover {
background: #0a1632;
}
.shepherd-element .shepherd-content footer .shepherd-buttons li .shepherd-button.shepherd-button-secondary {
background: #e5e5e5;
color: rgba(0, 0, 0, 0.75);
}
.shepherd-element .shepherd-content footer .shepherd-buttons li .shepherd-button.shepherd-button-secondary:hover {
background: #cbcbcb;
color: rgba(0, 0, 0, 0.75);
}
@media only screen and (min-width: 40.0625em) {
h1, h2, h3, h4, h5, h6 {
line-height: 1.4;
}
h1 {
font-size: 2.75rem;
}
h2 {
font-size: 2.3125rem;
}
h3 {
font-size: 1.6875rem;
}
h4 {
font-size: 1.4375rem;
}
h5 {
font-size: 1.125rem;
}
h6 {
font-size: 1rem;
}
}
================================================
FILE: packages/example/src/env.d.ts
================================================
/// <reference types="astro/client" />
================================================
FILE: packages/example/src/pages/index.astro
================================================
---
import Home from '@components/home.astro';
import '@css/index.css';
import '@css/welcome.css';
import '@css/duotone.css';
---
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>React Shepherd — Guide your users through a tour of your app.</title>
<meta name="description" content="Guide your users through a tour of your app." />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="apple-touch-icon" sizes="180x180" href="/shepherd/docs/assets/favicons/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/shepherd/docs/assets/favicons/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/shepherd/docs/assets/favicons/favicon-16x16.png" />
<link rel="mask-icon" href="/shepherd/docs/assets/favicons/safari-pinned-tab.svg" color="#426170" />
<link rel="shortcut icon" href="/shepherd/docs/assets/favicons/favicon.ico" />
<meta name="msapplication-config" content="/shepherd/docs/assets/favicons/browserconfig.xml" />
<meta name="theme-color" content="#ffffff" />
</head>
</head>
<body>
<main>
<div class="hero-scroll">
<div class="hero-outer">
<div class="hero-inner">
<div class="hero-welcome">
<h1>
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K" alt="" height="40" />
React Shepherd
</h1>
<h2>Guide your users through a tour of your app.</h2>
</div>
<Home />
<div class="hero-followup">
<p>
<a class="button star" href="https://github.com/shipshapecode/react-shepherd">★ on Github</a>
<a class="button" href="https://shipshapecode.github.io/react-shepherd/">View Docs</a>
</p>
</div>
<div>
<img width="140" height="140" src="/sheep.svg" />
</div>
</div>
</div>
</div>
</main>
</body>
</html>
================================================
FILE: packages/example/src/steps.js
================================================
export default [
{
id: 'welcome',
text: [
`
<p>
Shepherd is a JavaScript library for guiding users through your app.
It uses <a href="https://popper.js.org/">Popper.js</a>,
another open source library, to render dialogs for each tour "step".
</p>
<p>
Among many things, Popper makes sure your steps never end up off screen or
cropped by an overflow. (Try resizing your browser to see what we mean.)
</p>
`
],
attachTo: { element: '.hero-welcome', on: 'bottom' },
classes: 'shepherd shepherd-welcome',
buttons: [
{
type: 'cancel',
classes: 'shepherd-button-secondary',
text: 'Exit'
},
{
type: 'next',
text: 'Next'
}
]
},
{
id: 'installation',
title: 'Installation',
text:
'Installation is simple, if you are using npm or yarn, just install like any other package.',
attachTo: { element: '.install-element', on: 'bottom' },
buttons: [
{
type: 'back',
classes: 'shepherd-button-secondary',
text: 'Back'
},
{
type: 'next',
text: 'Next'
}
]
},
{
id: 'usage',
title: 'Usage',
text: [
'To use the tour service, simply inject it into your application and use it like this example.'
],
attachTo: { element: '.usage-element', on: 'bottom' },
buttons: [
{
type: 'back',
classes: 'shepherd-button-secondary',
text: 'Back'
},
{
type: 'next',
text: 'Next'
}
]
},
{
id: 'centered-example',
title: 'Centered Shepherd Element',
text: `But attachment is totally optional!\n \
Without a target, a tour step will create an element that's centered within the view. \
Check out the <a href="https://shepherdjs.dev/docs/">documentation</a> to learn more.`,
buttons: [
{
type: 'back',
classes: 'shepherd-button-secondary',
text: 'Back'
},
{
type: 'next',
text: 'Next'
}
]
},
{
id: 'followup',
title: 'Learn more',
text: 'Star Shepherd on Github so you remember it for your next project',
attachTo: { element: '.hero-followup', on: 'top' },
scrollTo: true,
buttons: [
{
type: 'back',
classes: 'shepherd-button-secondary',
text: 'Back'
},
{
type: 'next',
text: 'Done'
}
]
}
];
================================================
FILE: packages/lib/.eslintrc.js
================================================
module.exports = {
env: {
browser: true,
es2021: true,
jest: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: [
'react',
'@typescript-eslint',
],
rules: {
'no-param-reassign': ['error', { 'props': false }],
'react/function-component-definition': [2, { 'namedComponents': 'arrow-function' }],
'react/jsx-filename-extension': [1, { 'extensions': ['.tsx', '.ts'] }],
},
settings: {
'import/resolver': {
typescript: {},
},
}
};
================================================
FILE: packages/lib/CHANGELOG.md
================================================
## v4.3.0 (2024-01-21)
## v4.0.1 (2022-07-06)
#### :bug: Bug Fix
* `lib`
* [#637](https://github.com/shipshapecode/react-shepherd/pull/637) Add children field for React 18 ([@andersaamodt](https://github.com/andersaamodt))
#### Committers: 2
- Anders ([@andersaamodt](https://github.com/andersaamodt))
- Chuck Carpenter ([@chuckcarpenter](https://github.com/chuckcarpenter))
## v3.3.1 (2020-11-13)
#### :rocket: Enhancement
* [#439](https://github.com/shipshapecode/react-shepherd/pull/439) ✨ Shepmaster expose more types ([@chuckcarpenter](https://github.com/chuckcarpenter))
* [#391](https://github.com/shipshapecode/react-shepherd/pull/391) Manage secondary property on Step button ([@linsolas](https://github.com/linsolas))
#### :bug: Bug Fix
* [#528](https://github.com/shipshapecode/react-shepherd/pull/528) 🐛 Remove check for current action assignment ([@chuckcarpenter](https://github.com/chuckcarpenter))
#### Committers: 4
- Chuck Carpenter ([@chuckcarpenter](https://github.com/chuckcarpenter))
- Hakeem Almidan ([@Hakeemmidan](https://github.com/Hakeemmidan))
- Romain Linsolas ([@linsolas](https://github.com/linsolas))
- [@cyremur](https://github.com/cyremur)
## v2.0.0 (2019-08-29)
#### :bug: Bug Fix
* [#36](https://github.com/shipshapecode/react-shepherd/pull/36) Make custom button actions work, if specified ([@jmfirth](https://github.com/jmfirth))
* [#38](https://github.com/shipshapecode/react-shepherd/pull/38) Fix adding steps ([@jmfirth](https://github.com/jmfirth))
#### Committers: 1
- Justin Firth ([@jmfirth](https://github.com/jmfirth))
================================================
FILE: packages/lib/README.md
================================================
# react-shepherd
<div>
<a href="https://shipshape.io">
<img align="left" src="http://i.imgur.com/DWHQjA5.png" alt="Ship Shape" width="50" height="50"/>
</a>
**[react-shepherd is built and maintained by Ship Shape. Contact us for web app consulting, development, and training for your project](https://shipshape.io/)**.
</div>
[](https://www.npmjs.com/package/react-shepherd)
[](https://github.com/shipshapecode/react-shepherd/actions?query=workflow%3ATest)
[](https://codeclimate.com/github/shipshapecode/react-shepherd/maintainability)
[](https://codeclimate.com/github/shipshapecode/react-shepherd/test_coverage)
[](https://standardjs.com)
This is a React wrapper for the [Shepherd](https://github.com/shipshapecode/shepherd), site tour, library.
It's mainly a wrapper around the Shepherd library that exposes the tour object and methods to the context object
that can be passed into props for dynamic interactivity.
## Install
```bash
npm install --save react-shepherd
```
## Usage
### Via Provider/Context
```jsx
import React, { Component, useContext } from "react";
import { ShepherdTour, ShepherdTourContext } from "react-shepherd";
import newSteps from "./steps";
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true,
},
},
useModalOverlay: true,
};
function Button() {
const tour = useContext(ShepherdTourContext);
return (
<button className="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
export default function App() {
return (
<div>
<ShepherdTour steps={newSteps} tourOptions={tourOptions}>
<Button />
</ShepherdTour>
</div>
);
}
```
### Via Hook
```jsx
import React, { Component } from "react";
import { useShepherdTour } from "react-shepherd";
import newSteps from "./steps";
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true,
},
},
useModalOverlay: true,
};
export default function App() {
const tour = useShepherdTour({ tourOptions, steps: newSteps });
return (
<button class="button dark" onClick={tour.start}>
Start Tour
</button>
);
}
```
## Configuration
The following configuration options for a tour can be set on the ShepherdTour to control the way that Shepherd is used. This is simply a POJO passed to Shepherd to use the options noted in the Shepherd Tour [options](https://shepherdjs.dev/docs/Tour.html).
**The only required option is `steps`, which is an array passed to the props.**
### tourOptions
`PropTypes.object`
Used to set the options that will be applied to each step by default. You can pass in any of the options that you can with Shepherd.
### steps
`PropTypes.array`
You must pass an array of steps to `steps`, something like this:
```js
const steps = [
{
id: 'intro',
attachTo: { element: '.first-element', on: 'bottom' },
beforeShowPromise: function () {
return new Promise(function (resolve) {
setTimeout(function () {
window.scrollTo(0, 0);
resolve();
}, 500);
});
},
buttons: [
{
classes: 'shepherd-button-secondary',
text: 'Exit',
type: 'cancel'
},
{
classes: 'shepherd-button-primary',
text: 'Back',
type: 'back'
},
{
classes: 'shepherd-button-primary',
text: 'Next',
type: 'next'
}
],
classes: 'custom-class-name-1 custom-class-name-2',
highlightClass: 'highlight',
scrollTo: false,
cancelIcon: {
enabled: true,
},
title: 'Welcome to React-Shepherd!',
text: ['React-Shepherd is a JavaScript library for guiding users through your React app.'],
when: {
show: () => {
console.log('show step');
},
hide: () => {
console.log('hide step');
}
}
},
// ...
];
```
## Steps
The options are the same as Shepherd [options](https://shepherdjs.dev/docs/Step.html).
## License
MIT
================================================
FILE: packages/lib/jest.config.js
================================================
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
rootDir: 'src',
testEnvironment: 'jsdom',
};
================================================
FILE: packages/lib/package.json
================================================
{
"name": "react-shepherd",
"version": "4.3.0",
"description": "A React wrapper for the site tour library Shepherd",
"homepage": "https://react-shepherd.vercel.app/",
"repository": {
"type": "git",
"url": "https://github.com/shipshapecode/react-shepherd.git"
},
"license": "MIT",
"main": "dist/Shepherd.js",
"module": "dist/Shepherd.es.js",
"jsnext:main": "dist/Shepherd.es.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"prebuild": "tsc --project ./tsconfig-declarations.json",
"build": "rollup -c",
"predeploy": "cd example && yarn && yarn build",
"prepare": "install-peers",
"problems": "tsc --noEmit",
"release": "release-it",
"start": "rollup -c -w",
"test": "cross-env CI=1 jest",
"test:watch": "jest --watch",
"lint": "eslint src --ext js,jsx,ts,tsx --max-warnings 0",
"lint:ci": "TIMING=all yarn lint --format junit --output-file reports/junit/junit.xml",
"lint:fix": "yarn lint --fix"
},
"dependencies": {
"resize-observer-polyfill": "^1.5.1",
"shepherd.js": "^11.0.1"
},
"devDependencies": {
"@babel/core": "^7.5.4",
"@babel/plugin-external-helpers": "^7.2.0",
"@babel/plugin-proposal-class-properties": "^7.5.0",
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-proposal-do-expressions": "^7.5.0",
"@babel/plugin-proposal-export-default-from": "^7.5.2",
"@babel/plugin-proposal-export-namespace-from": "^7.5.2",
"@babel/plugin-proposal-function-bind": "^7.2.0",
"@babel/plugin-proposal-function-sent": "^7.5.0",
"@babel/plugin-proposal-json-strings": "^7.2.0",
"@babel/plugin-proposal-logical-assignment-operators": "^7.2.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
"@babel/plugin-proposal-optional-chaining": "^7.2.0",
"@babel/plugin-proposal-pipeline-operator": "^7.5.0",
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.5.4",
"@babel/preset-react": "^7.0.0",
"@svgr/rollup": "^8.1.0",
"@testing-library/react": "^14.0.0",
"@types/jest": "^29.0.0",
"@types/node": "^18.0.3",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^5.30.5",
"cross-env": "^7.0.0",
"eslint": "^7.32.0 || ^8.2.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-import-resolver-typescript": "^3.2.5",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"install-peers-cli": "^2.2.0",
"jest": "^28.1.2",
"jest-environment-jsdom": "^29.0.1",
"release-it": "^14.0.2",
"release-it-lerna-changelog": "^5.0.0",
"rollup": "^2.6.1",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.0.1",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-peer-deps-external": "^2.2.0",
"rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-typescript": "^1.0.1",
"rollup-plugin-url": "^3.0.0",
"ts-jest": "^28.0.5",
"tslib": "^2.0.1",
"typescript": "^4.7.4"
},
"peerDependencies": {
"react": "^17.0.2 || 18.x",
"react-dom": "^17.0.2 || 18.x"
},
"engines": {
"node": ">=16",
"npm": ">=7"
},
"publishConfig": {
"registry": "https://registry.npmjs.org"
}
}
================================================
FILE: packages/lib/rollup.config.js
================================================
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import resolve from 'rollup-plugin-node-resolve';
import typescript from 'rollup-plugin-typescript';
import url from 'rollup-plugin-url';
import svgr from '@svgr/rollup';
import pkg from './package.json';
export default {
input: 'src/index.tsx',
output: [
{
file: pkg.main,
format: 'cjs',
sourcemap: true
},
{
file: pkg.module,
format: 'es',
sourcemap: true
}
],
plugins: [
typescript(),
external(),
postcss({
modules: true
}),
url(),
svgr(),
babel({
exclude: 'node_modules/**'
}),
resolve(),
commonjs()
]
};
================================================
FILE: packages/lib/src/__tests__/shepherd.test.tsx
================================================
import React, { useContext } from 'react';
import ResizeObserver from 'resize-observer-polyfill';
import { render, fireEvent } from '@testing-library/react';
import { ShepherdTour, ShepherdTourContext } from '..';
window.ResizeObserver = ResizeObserver;
const steps = [
{
id: 'welcome',
text: [
`
Shepherd is a JavaScript library for guiding users through your app.
It uses <a href="https://atomiks.github.io/tippyjs//">Tippy.js</a>,
another open source library, to render dialogs for each tour "step".
`,
`
Among many things, Tippy makes sure your steps never end up off screen or cropped by an overflow.
Try resizing your browser to see what we mean.
`,
],
classes: 'shepherd shepherd-welcome',
buttons: [
{
type: 'cancel',
classes: 'shepherd-button-secondary',
text: 'Exit',
},
{
type: 'next',
text: 'Next',
},
],
},
];
const tourOptions = {
defaultStepOptions: {
cancelIcon: {
enabled: true,
},
},
useModalOverlay: true,
};
describe('<ShepherdTour />', () => {
it('exists', () => {
expect(ShepherdTour).toBeTruthy();
});
it('renders the component and starts tour', async () => {
const Button = () => {
const tour = useContext(ShepherdTourContext);
return (
<button className="button dark" type="button" onClick={tour?.start}>
Start Tour
</button>
);
};
const TestApp = () => (
<ShepherdTour steps={steps} tourOptions={tourOptions}>
<Button />
</ShepherdTour>
);
const container = render(<TestApp />);
await fireEvent.click(container.getByText(/Start Tour/));
const cancelBtn = await container.findByText('Exit');
const nextBtn = await container.findByText('Next');
expect(cancelBtn).toBeTruthy();
expect(nextBtn).toBeTruthy();
});
});
================================================
FILE: packages/lib/src/index.tsx
================================================
import React, { FC, useMemo } from 'react';
import Shepherd from 'shepherd.js';
import Step from 'shepherd.js/src/types/step';
import Tour from 'shepherd.js/src/types/tour';
type StepType = 'back' | 'cancel' | 'next';
export interface ShepherdButtonWithType extends Step.StepOptionsButton {
type?: StepType;
}
export interface ShepherdOptionsWithType extends Step.StepOptions {
buttons?: ReadonlyArray<Step.StepOptionsButton | ShepherdButtonWithType>;
}
interface ShepherdProps {
steps: Array<ShepherdOptionsWithType>;
tourOptions: Tour.TourOptions;
children: React.ReactNode;
}
const ShepherdTourContext = React.createContext<Tour | null>(null);
const ShepherdTourContextConsumer = ShepherdTourContext.Consumer;
/**
* Take a set of steps and formats to use actions on the buttons in the current context
* @param {Array} steps
* @param {Array} tour
* @private
*/
const addSteps = (steps: Array<Step.StepOptions>, tour: Tour) => {
// Return nothing if there are no steps
if (!steps.length) {
return [];
}
const parsedStepsforAction = steps.map((step: Step.StepOptions): Step.StepOptions => {
const { buttons } = step;
if (buttons) {
step.buttons = buttons.map((button: ShepherdButtonWithType) => {
const {
action, classes, disabled, label, secondary, text, type,
} = button;
return {
action: type ? tour[type] : action,
classes,
disabled,
label,
secondary,
text,
type,
};
});
}
return step;
});
return parsedStepsforAction.forEach((step: any) => tour.addStep(step));
};
// for instances where Context can't be used or doesn't make sense
export const useShepherdTour = ({ tourOptions, steps }: Pick<ShepherdProps, 'steps' | 'tourOptions'>) => {
const tourObject = useMemo(() => {
const tourInstance = new Shepherd.Tour(tourOptions);
addSteps(steps, tourInstance);
return tourInstance;
}, [tourOptions, steps]);
return tourObject;
};
export const ShepherdTour: FC<ShepherdProps> = ({ children, tourOptions, steps }) => {
const tourObject = useMemo(() => {
const tourInstance = new Shepherd.Tour(tourOptions);
addSteps(steps, tourInstance);
return tourInstance;
}, [tourOptions, steps]);
return (
<ShepherdTourContext.Provider value={tourObject}>
{children}
</ShepherdTourContext.Provider>
);
};
export type { default as Step } from 'shepherd.js/src/types/step';
export type { default as Tour } from 'shepherd.js/src/types/tour';
export { ShepherdTourContextConsumer as TourMethods, ShepherdTourContext };
================================================
FILE: packages/lib/src/styles.css
================================================
/* add css styles here (optional) */
.test {
display: inline-block;
margin: 2em auto;
border: 2px solid #000;
font-size: 2em;
}
================================================
FILE: packages/lib/tsconfig-declarations.json
================================================
{
"extends": "./tsconfig.json",
"compilerOptions": {
"isolatedModules": false,
"noEmit": false,
"declaration": true,
"emitDeclarationOnly": true
}
}
================================================
FILE: packages/lib/tsconfig.json
================================================
{
"compilerOptions": {
"outDir": "./dist",
"jsx": "react",
"allowJs": true,
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"include": [
"./src/**/*"
]
}
gitextract_rt5270q3/
├── .babelrc
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── ghpages.yml
│ ├── publish.yml
│ └── test.yml
├── .gitignore
├── .nvmrc
├── CHANGELOG.md
├── README.md
├── RELEASE.md
├── netlify.toml
├── package.json
└── packages/
├── example/
│ ├── .eslintrc.json
│ ├── README.md
│ ├── astro.config.mjs
│ ├── jsconfig.json
│ ├── package.json
│ └── src/
│ ├── components/
│ │ ├── home.astro
│ │ └── tour.jsx
│ ├── css/
│ │ ├── duotone.css
│ │ ├── index.css
│ │ └── welcome.css
│ ├── env.d.ts
│ ├── pages/
│ │ └── index.astro
│ └── steps.js
└── lib/
├── .eslintrc.js
├── CHANGELOG.md
├── README.md
├── jest.config.js
├── package.json
├── rollup.config.js
├── src/
│ ├── __tests__/
│ │ └── shepherd.test.tsx
│ ├── index.tsx
│ └── styles.css
├── tsconfig-declarations.json
└── tsconfig.json
SYMBOL INDEX (5 symbols across 2 files)
FILE: packages/example/src/components/tour.jsx
function Tour (line 14) | function Tour() {
FILE: packages/lib/src/index.tsx
type StepType (line 6) | type StepType = 'back' | 'cancel' | 'next';
type ShepherdButtonWithType (line 7) | interface ShepherdButtonWithType extends Step.StepOptionsButton {
type ShepherdOptionsWithType (line 11) | interface ShepherdOptionsWithType extends Step.StepOptions {
type ShepherdProps (line 15) | interface ShepherdProps {
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (55K chars).
[
{
"path": ".babelrc",
"chars": 242,
"preview": "{\n \"presets\": [\n [\"@babel/env\", {\n \"modules\": false\n }],\n \"@babel/react\"\n ],\n \"plugins\": [\n \"@babel/"
},
{
"path": ".editorconfig",
"chars": 147,
"preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
},
{
"path": ".github/dependabot.yml",
"chars": 183,
"preview": "version: 2\nupdates:\n- package-ecosystem: npm\n directory: \"/packages/lib\"\n schedule:\n interval: weekly\n time: \"10"
},
{
"path": ".github/workflows/ghpages.yml",
"chars": 1062,
"preview": "name: Build and GH Pages Deploy\n\non:\n release:\n types: [created]\n\njobs:\n build:\n runs-on: ubuntu-latest\n\n ste"
},
{
"path": ".github/workflows/publish.yml",
"chars": 1105,
"preview": "name: Publish to NPM\n\non:\n push:\n tags:\n - v*\n\njobs:\n publish:\n name: Build and Publissh\n runs-on: ubunt"
},
{
"path": ".github/workflows/test.yml",
"chars": 903,
"preview": "name: Test\n\non:\n push:\n branches:\n - master\n pull_request:\n branches:\n - master\n\njobs:\n test:\n nam"
},
{
"path": ".gitignore",
"chars": 291,
"preview": "\n# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n\n# builds\nbuild"
},
{
"path": ".nvmrc",
"chars": 8,
"preview": "16.13.1\n"
},
{
"path": "CHANGELOG.md",
"chars": 478,
"preview": "\n## v4.1.0 (2022-07-07)\n\n## v4.0.1 (2022-07-06)\n\n#### :bug: Bug Fix\n* `lib`\n * [#637](https://github.com/shipshapecode/"
},
{
"path": "README.md",
"chars": 4589,
"preview": "**This repository is no longer being maintained and all further development is at the main [shepherd](https://github.com"
},
{
"path": "RELEASE.md",
"chars": 2177,
"preview": "# Release\n\nReleases are mostly automated using\n[release-it](https://github.com/release-it/release-it/) and\n[lerna-change"
},
{
"path": "netlify.toml",
"chars": 107,
"preview": "[build]\n command = \"yarn build && cd packages/example && yarn build\"\n publish = \"packages/example/dist\"\n\n"
},
{
"path": "package.json",
"chars": 1056,
"preview": "{\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/shipshapecode/react-shepherd.git\"\n },\n \"private\""
},
{
"path": "packages/example/.eslintrc.json",
"chars": 24,
"preview": "{\n \"extends\": \"next\"\n}\n"
},
{
"path": "packages/example/README.md",
"chars": 1325,
"preview": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js"
},
{
"path": "packages/example/astro.config.mjs",
"chars": 230,
"preview": "import { defineConfig } from 'astro/config';\nimport react from \"@astrojs/react\";\n\n// https://astro.build/config\nexport d"
},
{
"path": "packages/example/jsconfig.json",
"chars": 143,
"preview": "{\n \"compilerOptions\": {\n \"baseUrl\": \"./src\",\n \"paths\": {\n \"@components/*\": [\"components/*\"],\n \"@css/*\":"
},
{
"path": "packages/example/package.json",
"chars": 520,
"preview": "{\n \"name\": \"react-shepherd-example\",\n \"homepage\": \"https://shipshapecode.github.io/react-shepherd\",\n \"version\": \"0.0."
},
{
"path": "packages/example/src/components/home.astro",
"chars": 1506,
"preview": "---\nimport { Prism } from '@astrojs/prism';\nimport Tour from './tour';\n\nconst installString = 'yarn add react-shepherd';"
},
{
"path": "packages/example/src/components/tour.jsx",
"chars": 469,
"preview": "import { useShepherdTour } from '../../../lib/dist/Shepherd.es';\nimport newSteps from '../steps';\nimport 'shepherd.js/di"
},
{
"path": "packages/example/src/css/duotone.css",
"chars": 3380,
"preview": "/*\nName: Duotone Light\nAuthor: Simurai, adapted from DuoTone themes for Atom (http://simurai.com/projects/2016/01/01/d"
},
{
"path": "packages/example/src/css/index.css",
"chars": 63,
"preview": "body {\n margin: 0;\n padding: 0;\n font-family: sans-serif;\n}\n"
},
{
"path": "packages/example/src/css/welcome.css",
"chars": 8651,
"preview": "html, body {\n height: 100%;\n\n}\n\nbody {\n background-color: #61dbfb;\n background-image: linear-gradient(-45deg, #61dbfb"
},
{
"path": "packages/example/src/env.d.ts",
"chars": 38,
"preview": "/// <reference types=\"astro/client\" />"
},
{
"path": "packages/example/src/pages/index.astro",
"chars": 2609,
"preview": "---\nimport Home from '@components/home.astro';\n\nimport '@css/index.css';\nimport '@css/welcome.css';\nimport '@css/duotone"
},
{
"path": "packages/example/src/steps.js",
"chars": 2506,
"preview": "export default [\n {\n id: 'welcome',\n text: [\n `\n <p>\n Shepherd is a JavaScript library for guiding"
},
{
"path": "packages/lib/.eslintrc.js",
"chars": 679,
"preview": "module.exports = {\n env: {\n browser: true,\n es2021: true,\n jest: true,\n },\n extends: [\n 'plugin:react/rec"
},
{
"path": "packages/lib/CHANGELOG.md",
"chars": 1582,
"preview": "\n## v4.3.0 (2024-01-21)\n\n## v4.0.1 (2022-07-06)\n\n#### :bug: Bug Fix\n* `lib`\n * [#637](https://github.com/shipshapecode/"
},
{
"path": "packages/lib/README.md",
"chars": 4407,
"preview": "# react-shepherd\n\n<div>\n <a href=\"https://shipshape.io\">\n <img align=\"left\" src=\"http://i.imgur.com/DWHQjA5.png\" alt"
},
{
"path": "packages/lib/jest.config.js",
"chars": 154,
"preview": "/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */\nmodule.exports = {\n preset: 'ts-jest',\n rootDir: 'src"
},
{
"path": "packages/lib/package.json",
"chars": 3588,
"preview": "{\n \"name\": \"react-shepherd\",\n \"version\": \"4.3.0\",\n \"description\": \"A React wrapper for the site tour library Shepherd"
},
{
"path": "packages/lib/rollup.config.js",
"chars": 815,
"preview": "import babel from 'rollup-plugin-babel';\nimport commonjs from 'rollup-plugin-commonjs';\nimport external from 'rollup-plu"
},
{
"path": "packages/lib/src/__tests__/shepherd.test.tsx",
"chars": 1925,
"preview": "import React, { useContext } from 'react';\nimport ResizeObserver from 'resize-observer-polyfill';\nimport { render, fireE"
},
{
"path": "packages/lib/src/index.tsx",
"chars": 2643,
"preview": "import React, { FC, useMemo } from 'react';\nimport Shepherd from 'shepherd.js';\nimport Step from 'shepherd.js/src/types/"
},
{
"path": "packages/lib/src/styles.css",
"chars": 137,
"preview": "/* add css styles here (optional) */\n\n.test {\n display: inline-block;\n margin: 2em auto;\n border: 2px solid #000;\n f"
},
{
"path": "packages/lib/tsconfig-declarations.json",
"chars": 171,
"preview": "{\n \"extends\": \"./tsconfig.json\",\n \"compilerOptions\": {\n \"isolatedModules\": false,\n \"noEmit\": false,\n \"declara"
},
{
"path": "packages/lib/tsconfig.json",
"chars": 522,
"preview": "{\n \"compilerOptions\": {\n \"outDir\": \"./dist\",\n \"jsx\": \"react\",\n \"allowJs\": true,\n \"target\": \"es5\",\n \"lib\""
}
]
About this extraction
This page contains the full source code of the shipshapecode/react-shepherd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (49.3 KB), approximately 15.3k tokens, and a symbol index with 5 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.