├── .browserslistrc ├── .gitignore ├── LICENSE ├── angular.json ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package.json ├── projects ├── ngx-tour-console │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── karma.conf.js │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── console.module.ts │ │ │ └── tour-anchor.directive.ts │ │ ├── public_api.ts │ │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── tslint.json ├── ngx-tour-core │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── jest.config.js │ ├── karma.conf.js │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── is-in-viewport.spec.ts │ │ │ ├── is-in-viewport.ts │ │ │ ├── tour-anchor.directive.ts │ │ │ ├── tour-hotkey-listener.component.ts │ │ │ ├── tour.module.ts │ │ │ ├── tour.service.spec.ts │ │ │ └── tour.service.ts │ │ ├── public_api.ts │ │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── tslint.json ├── ngx-tour-md-menu │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── karma.conf.js │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── md-menu.module.ts │ │ │ ├── ngx-md-menu-tour.service.ts │ │ │ ├── step-option.interface.ts │ │ │ ├── tour-anchor-opener.component.ts │ │ │ ├── tour-anchor.directive.ts │ │ │ ├── tour-backdrop.service.ts │ │ │ ├── tour-step-template.component.ts │ │ │ └── tour-step-template.service.ts │ │ ├── public_api.ts │ │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── tslint.json ├── ngx-tour-ng-bootstrap │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── karma.conf.js │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── ng-bootstrap-tour.service.ts │ │ │ ├── ng-bootstrap.module.ts │ │ │ ├── step-option.interface.ts │ │ │ ├── tour-anchor.directive.ts │ │ │ ├── tour-step-template.component.ts │ │ │ └── tour-step-template.service.ts │ │ ├── public_api.ts │ │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── tslint.json ├── ngx-tour-ngx-bootstrap │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── karma.conf.js │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ │ ├── lib │ │ │ ├── ngx-bootstrap-tour.service.ts │ │ │ ├── ngx-bootstrap.module.ts │ │ │ ├── step-option.interface.ts │ │ │ ├── tour-anchor.directive.ts │ │ │ ├── tour-step-template.component.ts │ │ │ └── tour-step-template.service.ts │ │ ├── public_api.ts │ │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── tslint.json └── ngx-tour-ngx-popper │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── karma.conf.js │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ ├── lib │ │ ├── ngx-popper-tour.service.ts │ │ ├── ngx-popper.module.ts │ │ ├── step-option.interface.ts │ │ ├── tour-anchor.directive.ts │ │ ├── tour-step-template.component.ts │ │ └── tour-step-template.service.ts │ ├── public_api.ts │ ├── styles.css │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── tslint.json ├── protractor.conf.js ├── readme.md ├── src ├── app │ ├── app.module.ts │ ├── console │ │ ├── console.component.html │ │ ├── console.component.ts │ │ ├── console.module.ts │ │ ├── docs.component.html │ │ ├── docs.component.ts │ │ └── other-route.component.ts │ ├── demo.component.html │ ├── demo.component.ts │ ├── md-menu │ │ ├── docs.component.html │ │ ├── docs.component.ts │ │ ├── mat-lazy-tour │ │ │ ├── app-routing.module.ts │ │ │ ├── app.component.css │ │ │ ├── app.component.html │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ ├── components │ │ │ │ └── home │ │ │ │ │ ├── home.component.css │ │ │ │ │ ├── home.component.html │ │ │ │ │ ├── home.component.spec.ts │ │ │ │ │ └── home.component.ts │ │ │ └── modules │ │ │ │ ├── module-a │ │ │ │ ├── module-a-routing.module.ts │ │ │ │ ├── module-a.component.css │ │ │ │ ├── module-a.component.html │ │ │ │ ├── module-a.component.spec.ts │ │ │ │ ├── module-a.component.ts │ │ │ │ └── module-a.module.ts │ │ │ │ └── module-b │ │ │ │ ├── module-b-routing.module.ts │ │ │ │ ├── module-b.component.css │ │ │ │ ├── module-b.component.html │ │ │ │ ├── module-b.component.spec.ts │ │ │ │ ├── module-b.component.ts │ │ │ │ └── module-b.module.ts │ │ ├── md-menu.component.html │ │ ├── md-menu.component.ts │ │ ├── md-menu.module.ts │ │ └── other-route.component.ts │ ├── ng-bootstrap │ │ ├── docs.component.html │ │ ├── docs.component.ts │ │ ├── ng-bootstrap.component.html │ │ ├── ng-bootstrap.component.ts │ │ ├── ng-bootstrap.module.ts │ │ └── other-route.component.ts │ └── ngx-bootstrap │ │ ├── docs.component.html │ │ ├── docs.component.ts │ │ ├── ngx-bootstrap.component.css │ │ ├── ngx-bootstrap.component.html │ │ ├── ngx-bootstrap.component.ts │ │ ├── ngx-bootstrap.module.ts │ │ └── other-route.component.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.base.json ├── tsconfig.json ├── tslint.json └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | .DS_Store 60 | 61 | dist/ 62 | .ng_build/ 63 | /.idea 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { NgPackagedPage } from './app.po'; 2 | 3 | describe('ng-packaged App', () => { 4 | let page: NgPackagedPage; 5 | 6 | beforeEach(() => { 7 | page = new NgPackagedPage(); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class NgPackagedPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | files: [ 19 | 20 | ], 21 | preprocessors: { 22 | 23 | }, 24 | mime: { 25 | 'text/x-typescript': ['ts','tsx'] 26 | }, 27 | coverageIstanbulReporter: { 28 | dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], 29 | fixWebpackSourcePaths: true 30 | }, 31 | angularCli: { 32 | environment: 'dev' 33 | }, 34 | reporters: config.angularCli && config.angularCli.codeCoverage 35 | ? ['progress', 'coverage-istanbul'] 36 | : ['progress', 'kjhtml'], 37 | port: 9876, 38 | colors: true, 39 | logLevel: config.LOG_INFO, 40 | autoWatch: true, 41 | browsers: ['Chrome'], 42 | singleRun: false 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour", 3 | "version": "0.0.1", 4 | "description": "", 5 | "keywords": [], 6 | "author": "Isaac Mann ", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/isaacplmann/ngx-tour" 10 | }, 11 | "license": "MIT", 12 | "engines": { 13 | "node": ">=12.0.0" 14 | }, 15 | "scripts": { 16 | "ng": "ng", 17 | "link:core": "cd dist/ngx-tour-core && npm link && cd ../..", 18 | "link": "cd dist/ngx-tour-console && npm link ngx-tour-core && cd ../ngx-tour-md-menu && npm link ngx-tour-core && cd ../ngx-tour-ng-bootstrap && npm link ngx-tour-core && cd ../ngx-tour-ngx-bootstrap && npm link ngx-tour-core && cd ../..", 19 | "prestart": "npm run link", 20 | "start": "ng serve", 21 | "prebuild": "npm run link", 22 | "build": "ng build --prod", 23 | "build:lib:all": "npm run build:lib:core && npm run build:lib:console:base && npm run build:lib:md-menu:base && npm run build:lib:ng-bootstrap:base && npm run build:lib:ngx-bootstrap:base", 24 | "build:lib:core": "ng build ngx-tour-core --prod && cpx projects/ngx-tour-core/CHANGELOG.md dist/ngx-tour-core/", 25 | "build:lib:console": "npm run build:lib:core && npm run link:core && cd projects/ngx-tour-console && npm link ngx-tour-core && cd ../.. && npm run build:lib:console:base", 26 | "build:lib:console:base": "ng build ngx-tour-console --prod && cpx projects/ngx-tour-console/CHANGELOG.md dist/ngx-tour-console/", 27 | "build:lib:md-menu": "npm run build:lib:core && npm run link:core && cd projects/ngx-tour-md-menu && npm link ngx-tour-core && cd ../.. && npm run build:lib:md-menu:base", 28 | "build:lib:md-menu:base": "ng build ngx-tour-md-menu --prod && cpx projects/ngx-tour-md-menu/CHANGELOG.md dist/ngx-tour-md-menu/", 29 | "build:lib:ng-bootstrap": "npm run build:lib:core && npm run link:core && cd projects/ngx-tour-ng-bootstrap && npm link ngx-tour-core && cd ../.. && npm run build:lib:ng-bootstrap:base", 30 | "build:lib:ng-bootstrap:base": "ng build ngx-tour-ng-bootstrap --prod && cpx projects/ngx-tour-ng-bootstrap/CHANGELOG.md dist/ngx-tour-ng-bootstrap/", 31 | "build:lib:ngx-bootstrap": "npm run build:lib:core && npm run link:core && cd projects/ngx-tour-ngx-bootstrap && npm link ngx-tour-core && cd ../.. && npm run build:lib:ngx-bootstrap:base", 32 | "build:lib:ngx-bootstrap:base": "ng build ngx-tour-ngx-bootstrap --prod && cpx projects/ngx-tour-ngx-bootstrap/CHANGELOG.md dist/ngx-tour-ngx-bootstrap/", 33 | "build:lib:ngx-popper": "npm run build:lib:core && npm run link:core && cd projects/ngx-tour-ngx-popper && npm link ngx-tour-core && cd ../.. && npm run build:lib:ngx-popper:base", 34 | "build:lib:ngx-popper:base": "ng build ngx-tour-ngx-popper --prod && cpx projects/ngx-tour-ngx-popper/src/styles.css dist/ngx-tour-ngx-popper/ && cpx projects/ngx-tour-ngx-popper/CHANGELOG.md dist/ngx-tour-ngx-popper/", 35 | "test": "ng test", 36 | "lint": "ng lint", 37 | "e2e": "ng e2e", 38 | "pub": "npm run pub:lib && npm run pub:demo", 39 | "pub:demo": "npm run build -- --base-href /ngx-tour/ && gh-pages -d dist/app", 40 | "pub:lib": "npm run build:lib:all && (npm run pub:lib:core & npm run pub:lib:console & npm run pub:lib:ng-bootstrap & npm run pub:lib:md-menu & npm run pub:lib:ngx-bootstrap & npm run pub:lib:ngx-popper)", 41 | "pub:lib:core": "cd dist/ngx-tour-core && npm publish", 42 | "pub:lib:console": "cd dist/ngx-tour-console && npm publish", 43 | "pub:lib:ng-bootstrap": "cd dist/ngx-tour-ng-bootstrap && npm publish", 44 | "pub:lib:ngx-bootstrap": "cd dist/ngx-tour-ngx-bootstrap && npm publish", 45 | "pub:lib:ngx-popper": "cd dist/ngx-tour-ngx-popper && npm publish", 46 | "pub:lib:md-menu": "cd dist/ngx-tour-md-menu && npm publish" 47 | }, 48 | "dependencies": { 49 | "@angular/animations": "^10.0.8", 50 | "@angular/cdk": "^10.1.2", 51 | "@angular/common": "^10.0.8", 52 | "@angular/core": "^10.0.8", 53 | "@angular/forms": "^10.0.8", 54 | "@angular/localize": "^10.0.8", 55 | "@angular/material": "^10.1.2", 56 | "@angular/platform-browser": "^10.0.8", 57 | "@angular/platform-browser-dynamic": "^10.0.8", 58 | "@angular/router": "^10.0.8", 59 | "@ng-bootstrap/ng-bootstrap": "^7.0.0", 60 | "ngx-bootstrap": "^6.0.0", 61 | "ngx-popper": "^7.0.0", 62 | "popper.js": "^1.16.1", 63 | "rxjs": "^6.6.2", 64 | "tslib": "^2.0.0", 65 | "zone.js": "~0.10.2" 66 | }, 67 | "devDependencies": { 68 | "@angular-builders/jest": "^10.0.0", 69 | "@angular-devkit/build-angular": "~0.1000.5", 70 | "@angular-devkit/build-ng-packagr": "~0.1000.5", 71 | "@angular/cli": "^10.0.5", 72 | "@angular/compiler": "^10.0.8", 73 | "@angular/compiler-cli": "^10.0.8", 74 | "@types/jasmine": "^2.8.12", 75 | "@types/jest": "^26.0.9", 76 | "@types/node": "^12.11.1", 77 | "codelyzer": "^6.0.0", 78 | "cpx": "^1.5.0", 79 | "gh-pages": "^1.1.0", 80 | "jasmine-core": "~3.5.0", 81 | "jasmine-spec-reporter": "~5.0.0", 82 | "jest": "^26.3.0", 83 | "karma": "~5.0.0", 84 | "karma-chrome-launcher": "~3.1.0", 85 | "karma-cli": "~1.0.1", 86 | "karma-coverage-istanbul-reporter": "~3.0.2", 87 | "karma-jasmine": "~3.3.0", 88 | "karma-jasmine-html-reporter": "^1.5.0", 89 | "ng-packagr": "^10.0.0", 90 | "protractor": "~7.0.0", 91 | "ts-node": "^7.0.1", 92 | "tslint": "~6.1.0", 93 | "tslint-config-standard": "^9.0.0", 94 | "typescript": "~3.9.7" 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [4.3.0](https://github.com/isaacplmann/ngx-tour) (2020-08-17) 4 | 5 | ### Features 6 | 7 | - Scroll to active html element on step change 8 | 9 | 10 | 11 | # [4.2.0](https://github.com/isaacplmann/ngx-tour) (2020-08-10) 12 | 13 | ### Features 14 | 15 | - Support Angular 10 16 | 17 | 18 | 19 | # [4.1.1](https://github.com/isaacplmann/ngx-tour) (2019-12-07) 20 | 21 | ### Fixes 22 | 23 | - Skip undefined tourAnchors 24 | 25 | 26 | 27 | # [4.1.0](https://github.com/isaacplmann/ngx-tour) (2019-10-23) 28 | 29 | ### Features 30 | 31 | - Support Angular 8 as peer dependency 32 | - Support Ivy renderer 33 | 34 | 35 | 36 | # [4.0.1](https://github.com/isaacplmann/ngx-tour) (2018-12-05) 37 | 38 | ### Fixes 39 | 40 | - NavigationStart only hide currentStep if route is specified eg. routing used 41 | 42 | 43 | 44 | # [4.0.0](https://github.com/isaacplmann/ngx-tour) (2018-11-27) 45 | 46 | ### BREAKING CHANGES 47 | 48 | - Require Angular 7 as peer dependency 49 | 50 | 51 | 52 | # [3.0.0](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 53 | 54 | ### BREAKING CHANGES 55 | 56 | - Require Angular 6 as peer dependency 57 | 58 | 59 | 60 | # [2.0.0](https://github.com/isaacplmann/ngx-tour) (2017-11-28) 61 | 62 | ### BEAKING CHANGE 63 | 64 | - Update to ngx-tour-core 2.x (Angular 5 and disabling hotkeys) 65 | 66 | 67 | 68 | # [1.0.2](https://github.com/isaacplmann/ngx-tour) (2017-07-20) 69 | 70 | ### Bug fixes 71 | 72 | - Fix AoT build 73 | 74 | 75 | 76 | # [1.0.1](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 77 | 78 | ### Bug fixes 79 | 80 | - Export all of core exports 81 | 82 | 83 | 84 | # [1.0.0](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 85 | 86 | ### BREAKING CHANGES 87 | 88 | - Split out to a separate package 89 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/README.md: -------------------------------------------------------------------------------- 1 | # Ngx-Tour Console 2 | [![Dependency Status](https://david-dm.org/isaacplmann/ngx-tour-console.svg)](https://david-dm.org/isaacplmann/ngx-tour-console) 3 | [![devDependency Status](https://david-dm.org/isaacplmann/ngx-tour-console/dev-status.svg)](https://david-dm.org/isaacplmann/ngx-tour-console?type=dev) 4 | 5 | Check out the [documentation/demo page](https://isaacplmann.github.io/ngx-tour). 6 | 7 | This is a product tour library built with Angular (2+). It's inspired by [angular-ui-tour](http://benmarch.github.io/angular-ui-tour). 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, 'coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-console", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-console", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour-console", 3 | "version": "4.3.0", 4 | "repository": "https://github.com/isaacplmann/ngx-tour.git", 5 | "author": "Isaac Mann ", 6 | "license": "MIT", 7 | "peerDependencies": { 8 | "@angular/common": ">=7.0.0 <11.0.0", 9 | "@angular/core": ">=7.0.0 <11.0.0", 10 | "ngx-tour-core": "^4.3.0" 11 | }, 12 | "dependencies": { 13 | "tslib": "^2.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/src/lib/console.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; 4 | import { TourHotkeyListenerComponent, TourModule, TourService } from 'ngx-tour-core'; 5 | 6 | import { TourAnchorConsoleDirective } from './tour-anchor.directive'; 7 | 8 | export { TourAnchorConsoleDirective, TourService }; 9 | 10 | @NgModule({ 11 | declarations: [TourAnchorConsoleDirective], 12 | exports: [TourAnchorConsoleDirective, TourHotkeyListenerComponent], 13 | imports: [TourModule, CommonModule, NgbPopoverModule], 14 | }) 15 | export class TourConsoleModule { 16 | public static forRoot(): ModuleWithProviders { 17 | return { 18 | ngModule: TourConsoleModule, 19 | providers: [ 20 | TourService 21 | ], 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/src/lib/tour-anchor.directive.ts: -------------------------------------------------------------------------------- 1 | import {TourAnchorDirective, TourService, IStepOption, isInViewport, ElementSides} from 'ngx-tour-core'; 2 | import {Directive, ElementRef, Input, OnDestroy, OnInit} from '@angular/core'; 3 | 4 | @Directive({ 5 | selector: '[tourAnchor]', 6 | }) 7 | export class TourAnchorConsoleDirective implements OnInit, OnDestroy, TourAnchorDirective { 8 | @Input() public tourAnchor: string; 9 | 10 | constructor( 11 | private tourService: TourService, 12 | private element: ElementRef 13 | ) {} 14 | 15 | public ngOnInit(): void { 16 | this.tourService.register(this.tourAnchor, this); 17 | } 18 | 19 | public ngOnDestroy(): void { 20 | this.tourService.unregister(this.tourAnchor); 21 | } 22 | 23 | public showTourStep(step: IStepOption): void { 24 | const htmlElement: HTMLElement = this.element.nativeElement; 25 | 26 | if (!step.preventScrolling) { 27 | if (!isInViewport(htmlElement, ElementSides.Bottom)) { 28 | htmlElement.scrollIntoView(false); 29 | } else if (!isInViewport(htmlElement, ElementSides.Top)) { 30 | htmlElement.scrollIntoView(true); 31 | } 32 | } 33 | 34 | console.group(step.title); 35 | console.log(step.content); 36 | console.log(`${step.placement || 'above'} ${this.tourAnchor}`); 37 | console.groupEnd(); 38 | } 39 | 40 | public hideTourStep(): void { 41 | return; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-tour-console 3 | */ 4 | 5 | export * from 'ngx-tour-core'; 6 | export { 7 | TourConsoleModule, 8 | TourAnchorConsoleDirective 9 | } from './lib/console.module'; 10 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/zone-testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { 8 | BrowserDynamicTestingModule, 9 | platformBrowserDynamicTesting 10 | } from '@angular/platform-browser-dynamic/testing'; 11 | 12 | declare const require: any; 13 | 14 | // First, initialize the Angular testing environment. 15 | getTestBed().initTestEnvironment( 16 | BrowserDynamicTestingModule, 17 | platformBrowserDynamicTesting() 18 | ); 19 | // Then we find all the tests. 20 | const context = require.context('./', true, /\.spec\.ts$/); 21 | // And load the modules. 22 | context.keys().map(context); 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2015" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true, 25 | "flatModuleId": "AUTOGENERATED", 26 | "flatModuleOutFile": "AUTOGENERATED" 27 | }, 28 | "exclude": [ 29 | "src/test.ts", 30 | "**/*.spec.ts" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "enableIvy": false 5 | } 6 | } -------------------------------------------------------------------------------- /projects/ngx-tour-console/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ], 9 | "paths": { 10 | "ngx-tour-core": [ 11 | "dist/ngx-tour-core" 12 | ] 13 | } 14 | }, 15 | "files": [ 16 | "src/test.ts" 17 | ], 18 | "include": [ 19 | "**/*.spec.ts", 20 | "**/*.d.ts" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-console/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": false, 5 | "component-selector": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [4.3.0](https://github.com/isaacplmann/ngx-tour) (2020-08-17) 4 | 5 | ### Features 6 | 7 | - Introduced `isInViewport(htmlElement)` function for detecting if the whole or part of html element is visible 8 | 9 | 10 | 11 | # [4.2.0](https://github.com/isaacplmann/ngx-tour) (2020-08-10) 12 | 13 | ### Features 14 | 15 | - Support Angular 10 16 | 17 | 18 | 19 | # [4.1.1](https://github.com/isaacplmann/ngx-tour) (2019-12-07) 20 | 21 | ### Fixes 22 | 23 | - Skip undefined tourAnchors 24 | 25 | 26 | 27 | # [4.1.0](https://github.com/isaacplmann/ngx-tour) (2019-10-23) 28 | 29 | ### Features 30 | 31 | - Support Angular 8 as peer dependency 32 | - Support Ivy renderer 33 | 34 | 35 | 36 | # [4.0.1](https://github.com/isaacplmann/ngx-tour) (2018-12-05) 37 | 38 | ### Fixes 39 | 40 | - NavigationStart only hide currentStep if route is specified eg. routing used 41 | 42 | 43 | 44 | # [4.0.0](https://github.com/isaacplmann/ngx-tour) (2018-11-27) 45 | 46 | ### BREAKING CHANGES 47 | 48 | - Require Angular 7 as peer dependency 49 | 50 | 51 | 52 | # [3.0.0](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 53 | 54 | ### BREAKING CHANGES 55 | 56 | - Require Angular 6 as peer dependency 57 | 58 | 59 | 60 | # [2.1.0](https://github.com/isaacplmann/ngx-tour) (2018-02-13) 61 | 62 | ### Features 63 | 64 | - Add options to set button text 65 | 66 | 67 | 68 | # [2.0.0](https://github.com/isaacplmann/ngx-tour) (2017-11-28) 69 | 70 | ### BREAKING CHANGES 71 | 72 | - Require Angular 5 as peer dependency 73 | 74 | ### Features 75 | 76 | - TourService allows hotkeys to be disabled/enabled 77 | 78 | 79 | 80 | # [1.1.0](https://github.com/isaacplmann/ngx-tour) (2017-10-17) 81 | 82 | ### Features 83 | 84 | - TourService made generic but defaults to IStepOoption 85 | 86 | 87 | 88 | # [1.0.3](https://github.com/isaacplmann/ngx-tour) (2017-08-09) 89 | 90 | ### Bug fixes 91 | 92 | - Update zone.js version 93 | 94 | 95 | 96 | # [1.0.2](https://github.com/isaacplmann/ngx-tour) (2017-07-20) 97 | 98 | ### Bug fixes 99 | 100 | - Fix AoT build 101 | 102 | 103 | 104 | # [1.0.1](https://github.com/isaacplmann/ngx-tour) (2017-07-19) 105 | 106 | ### Bug fixes 107 | 108 | - Steps default to an empty array instead of undefined 109 | 110 | 111 | 112 | # [1.0.0](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 113 | 114 | ### BREAKING CHANGES 115 | 116 | - Split out to a separate package 117 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/README.md: -------------------------------------------------------------------------------- 1 | # Ngx-Tour Core 2 | [![Dependency Status](https://david-dm.org/isaacplmann/ngx-tour-core.svg)](https://david-dm.org/isaacplmann/ngx-tour-core) 3 | [![devDependency Status](https://david-dm.org/isaacplmann/ngx-tour-core/dev-status.svg)](https://david-dm.org/isaacplmann/ngx-tour-core?type=dev) 4 | 5 | Check out the [documentation/demo page](https://isaacplmann.github.io/ngx-tour). 6 | 7 | This is a product tour library built with Angular (2+). It's inspired by [angular-ui-tour](http://benmarch.github.io/angular-ui-tour). 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | globals: { 3 | 'ts-jest': { 4 | diagnostics: false 5 | } 6 | }, 7 | transform: { 8 | '^.+\\.ts$': 'ts-jest' 9 | }, 10 | verbose: true 11 | }; 12 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-core", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } -------------------------------------------------------------------------------- /projects/ngx-tour-core/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-core", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/ngx-tour-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour-core", 3 | "version": "4.3.0", 4 | "repository": "https://github.com/isaacplmann/ngx-tour.git", 5 | "author": "Isaac Mann ", 6 | "license": "MIT", 7 | "peerDependencies": { 8 | "@angular/common": ">=7.0.0 <11.0.0", 9 | "@angular/core": ">=7.0.0 <11.0.0", 10 | "@angular/router": ">=7.0.0 <11.0.0", 11 | "rxjs": "^6.0.0" 12 | }, 13 | "dependencies": { 14 | "tslib": "^2.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/is-in-viewport.spec.ts: -------------------------------------------------------------------------------- 1 | import {ElementSides, isInViewport} from './is-in-viewport'; 2 | import Mock = jest.Mock; 3 | 4 | describe('IsInViewport', () => { 5 | 6 | let htmlElement: HTMLElement; 7 | let sidesToTest: ElementSides; 8 | const initialClientRect = { 9 | top: 137, 10 | bottom: 255, 11 | left: 40, 12 | right: 631 13 | }; 14 | 15 | beforeEach(() => { 16 | htmlElement = { 17 | getBoundingClientRect: jest.fn().mockReturnValue({ 18 | ...initialClientRect 19 | }) 20 | }; 21 | Object.defineProperties(window, { 22 | innerWidth: { 23 | value: 800 24 | }, 25 | innerHeight: { 26 | value: 600 27 | } 28 | }); 29 | }); 30 | 31 | const testWithRectangle = (rectangle: Partial, expectedResult: boolean) => { 32 | (htmlElement.getBoundingClientRect).mockReturnValue({ 33 | ...initialClientRect, 34 | ...rectangle 35 | }); 36 | 37 | const actualResult = isInViewport(htmlElement, sidesToTest); 38 | 39 | expect(actualResult).toBe(expectedResult); 40 | }; 41 | 42 | it('should check if top is visible', () => { 43 | sidesToTest = ElementSides.Top; 44 | 45 | testWithRectangle({}, true); 46 | testWithRectangle({top: -100}, false); 47 | testWithRectangle({bottom: 700}, true); 48 | testWithRectangle({left: -10}, false); 49 | testWithRectangle({right: 900}, false); 50 | }); 51 | 52 | it('should check if bottom is visible', () => { 53 | sidesToTest = ElementSides.Bottom; 54 | 55 | testWithRectangle({}, true); 56 | testWithRectangle({top: -100}, true); 57 | testWithRectangle({bottom: 700}, false); 58 | testWithRectangle({left: -10}, false); 59 | testWithRectangle({right: 900}, false); 60 | }); 61 | 62 | it('should check if the whole element is visible', () => { 63 | sidesToTest = ElementSides.All; 64 | 65 | testWithRectangle({}, true); 66 | testWithRectangle({top: -100}, false); 67 | testWithRectangle({bottom: 700}, false); 68 | testWithRectangle({left: -10}, false); 69 | testWithRectangle({right: 900}, false); 70 | }); 71 | 72 | it('should default to all sides when "sidesToCheck" argument is omitted', () => { 73 | sidesToTest = undefined; 74 | 75 | testWithRectangle({}, true); 76 | testWithRectangle({top: -100}, false); 77 | testWithRectangle({bottom: 700}, false); 78 | testWithRectangle({left: -10}, false); 79 | testWithRectangle({right: 900}, false); 80 | }); 81 | 82 | }); 83 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/is-in-viewport.ts: -------------------------------------------------------------------------------- 1 | export enum ElementSides { 2 | Top, 3 | Bottom, 4 | All 5 | } 6 | 7 | export function isInViewport(htlmElement: HTMLElement, sidesToCheck: ElementSides = ElementSides.All): boolean { 8 | const viewportWidth = window.innerWidth, 9 | viewportHeight = window.innerHeight, 10 | boundingRectangle = htlmElement.getBoundingClientRect(), 11 | areCornersInViewport = boundingRectangle.left >= 0 && boundingRectangle.right <= viewportWidth, 12 | isTopInViewport = boundingRectangle.top >= 0, 13 | isBottomInViewport = boundingRectangle.bottom <= viewportHeight; 14 | 15 | if (sidesToCheck === ElementSides.Top) { 16 | return isTopInViewport && areCornersInViewport; 17 | } 18 | if (sidesToCheck === ElementSides.Bottom) { 19 | return isBottomInViewport && areCornersInViewport; 20 | } 21 | 22 | return isTopInViewport && isBottomInViewport && areCornersInViewport; 23 | } 24 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/tour-anchor.directive.ts: -------------------------------------------------------------------------------- 1 | import { IStepOption } from './tour.service'; 2 | 3 | export interface TourAnchorDirective { 4 | showTourStep(step: IStepOption): void; 5 | hideTourStep(): void; 6 | } 7 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/tour-hotkey-listener.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, HostListener } from '@angular/core'; 2 | 3 | import { TourService, TourState } from './tour.service'; 4 | 5 | @Component({ 6 | selector: 'tour-hotkey-listener', 7 | template: `` 8 | }) 9 | export class TourHotkeyListenerComponent { 10 | constructor(public tourService: TourService) {} 11 | 12 | /** 13 | * Configures hot keys for controlling the tour with the keyboard 14 | */ 15 | @HostListener('window:keydown.Escape') 16 | public onEscapeKey(): void { 17 | if ( 18 | this.tourService.getStatus() === TourState.ON && 19 | this.tourService.isHotkeysEnabled() 20 | ) { 21 | this.tourService.end(); 22 | } 23 | } 24 | 25 | @HostListener('window:keydown.ArrowRight') 26 | public onArrowRightKey(): void { 27 | if ( 28 | this.tourService.getStatus() === TourState.ON && 29 | this.tourService.hasNext(this.tourService.currentStep) && 30 | this.tourService.isHotkeysEnabled() 31 | ) { 32 | this.tourService.next(); 33 | } 34 | } 35 | 36 | @HostListener('window:keydown.ArrowLeft') 37 | public onArrowLeftKey(): void { 38 | if ( 39 | this.tourService.getStatus() === TourState.ON && 40 | this.tourService.hasPrev(this.tourService.currentStep) && 41 | this.tourService.isHotkeysEnabled() 42 | ) { 43 | this.tourService.prev(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/tour.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | 5 | import { TourHotkeyListenerComponent } from './tour-hotkey-listener.component'; 6 | import { TourService } from './tour.service'; 7 | 8 | @NgModule({ 9 | declarations: [TourHotkeyListenerComponent], 10 | exports: [TourHotkeyListenerComponent], 11 | imports: [CommonModule, RouterModule], 12 | }) 13 | export class TourModule { 14 | public static forRoot(): ModuleWithProviders { 15 | return { 16 | ngModule: TourModule, 17 | providers: [ 18 | TourService, 19 | ], 20 | }; 21 | } 22 | } 23 | 24 | export { TourService }; 25 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/tour.service.spec.ts: -------------------------------------------------------------------------------- 1 | // import { TourService, IStepOption, TourState } from './tour.service'; 2 | // import { RouterModule } from '@angular/router'; 3 | // import { HotkeyModule } from 'angular2-hotkeys'; 4 | // import { CommonModule } from '@angular/common'; 5 | // import { TestBed, inject, async } from '@angular/core/testing'; 6 | 7 | // describe('TourService', () => { 8 | 9 | // beforeEach(() => { 10 | // TestBed.configureTestingModule({ 11 | // imports: [CommonModule, HotkeyModule, RouterModule], 12 | // providers: [TourService], 13 | // }); 14 | // }); 15 | 16 | // describe('initialize()', () => { 17 | // let steps: IStepOption; 18 | // beforeEach(() => { 19 | // steps = [{ 20 | // anchorId: 'start.tour', 21 | // content: 'Welcome to the Ng2-Tour tour!', 22 | // placement: 'below', 23 | // title: 'Welcome', 24 | // }, { 25 | // anchorId: 'angular-ui-tour', 26 | // content: 'Thanks to angular-ui-tour for the inspiration for the library', 27 | // route: '', 28 | // title: 'angular-ui-tour', 29 | // }, { 30 | // anchorId: 'installation', 31 | // content: 'First, install the library...', 32 | // title: 'Installation', 33 | // }]; 34 | // }); 35 | 36 | // it( 37 | // 'should do nothing if no steps passed', 38 | // inject([TourService], (tourService) => { 39 | // expect(tourService.steps).toBeUndefined(); 40 | // tourService.initialize(undefined); 41 | // expect(tourService.steps).toBeUndefined(); 42 | // tourService.initialize([]); 43 | // expect(tourService.steps).toBeUndefined(); 44 | // tourService.initialize({ objects: 'are ignored' }); 45 | // expect(tourService.steps).toBeUndefined(); 46 | // }), 47 | // ); 48 | // it( 49 | // 'should save steps to the tour', 50 | // async(inject([TourService], (tourService) => { 51 | // tourService.initialize$.first().subscribe((event) => { 52 | // expect(event).toBe(steps); 53 | // }); 54 | // tourService.initialize(steps); 55 | // expect(tourService.steps).toBe(steps); 56 | // expect(tourService.status).toBe(TourState.OFF); 57 | // })), 58 | // ); 59 | // it( 60 | // 'should use default values for steps', 61 | // inject([TourService], (tourService) => { 62 | // const stepDefaults = { 63 | // placement: 'bottom', 64 | // route: 'blue', 65 | // }; 66 | // tourService.initialize$.first().subscribe((event) => { 67 | // expect(event).toBe(steps); 68 | // }); 69 | // tourService.initialize(steps, stepDefaults); 70 | // expect(tourService.steps).toBe(steps); 71 | // expect(tourService.status).toBe(TourState.OFF); 72 | // }), 73 | // ); 74 | // }); 75 | // }); 76 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/lib/tour.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {NavigationStart, Router} from '@angular/router'; 3 | import type {UrlSegment} from '@angular/router'; 4 | 5 | import { TourAnchorDirective } from './tour-anchor.directive'; 6 | import { Subject, Observable, merge as mergeStatic } from 'rxjs'; 7 | import { first, map, filter } from 'rxjs/operators'; 8 | 9 | export interface IStepOption { 10 | stepId?: string; 11 | anchorId?: string; 12 | title?: string; 13 | content?: string; 14 | route?: string | UrlSegment[]; 15 | nextStep?: number | string; 16 | prevStep?: number | string; 17 | placement?: any; 18 | preventScrolling?: boolean; 19 | prevBtnTitle?: string; 20 | nextBtnTitle?: string; 21 | endBtnTitle?: string; 22 | } 23 | 24 | export enum TourState { 25 | OFF, 26 | ON, 27 | PAUSED 28 | } 29 | 30 | @Injectable() 31 | export class TourService { 32 | public stepShow$: Subject = new Subject(); 33 | public stepHide$: Subject = new Subject(); 34 | public initialize$: Subject = new Subject(); 35 | public start$: Subject = new Subject(); 36 | public end$: Subject = new Subject(); 37 | public pause$: Subject = new Subject(); 38 | public resume$: Subject = new Subject(); 39 | public anchorRegister$: Subject = new Subject(); 40 | public anchorUnregister$: Subject = new Subject(); 41 | public events$: Observable<{ name: string; value: any }> = mergeStatic( 42 | this.stepShow$.pipe(map(value => ({ name: 'stepShow', value }))), 43 | this.stepHide$.pipe(map(value => ({ name: 'stepHide', value }))), 44 | this.initialize$.pipe(map(value => ({ name: 'initialize', value }))), 45 | this.start$.pipe(map(value => ({ name: 'start', value }))), 46 | this.end$.pipe(map(value => ({ name: 'end', value }))), 47 | this.pause$.pipe(map(value => ({ name: 'pause', value }))), 48 | this.resume$.pipe(map(value => ({ name: 'resume', value }))), 49 | this.anchorRegister$.pipe( 50 | map(value => ({ 51 | name: 'anchorRegister', 52 | value 53 | })) 54 | ), 55 | this.anchorUnregister$.pipe( 56 | map(value => ({ 57 | name: 'anchorUnregister', 58 | value 59 | })) 60 | ) 61 | ); 62 | 63 | public steps: T[] = []; 64 | public currentStep: T; 65 | 66 | public anchors: { [anchorId: string]: TourAnchorDirective } = {}; 67 | private status: TourState = TourState.OFF; 68 | private isHotKeysEnabled = true; 69 | 70 | constructor(private router: Router) {} 71 | 72 | public initialize(steps: T[], stepDefaults?: T): void { 73 | if (steps && steps.length > 0) { 74 | this.status = TourState.OFF; 75 | this.steps = steps.map(step => Object.assign({}, stepDefaults, step)); 76 | this.initialize$.next(this.steps); 77 | } 78 | } 79 | 80 | public disableHotkeys(): void { 81 | this.isHotKeysEnabled = false; 82 | } 83 | 84 | public enableHotkeys(): void { 85 | this.isHotKeysEnabled = true; 86 | } 87 | 88 | public start(): void { 89 | this.startAt(0); 90 | } 91 | 92 | public startAt(stepId: number | string): void { 93 | this.status = TourState.ON; 94 | this.goToStep(this.loadStep(stepId)); 95 | this.start$.next(); 96 | this.router.events 97 | .pipe(filter(event => event instanceof NavigationStart), first()) 98 | .subscribe(() => { 99 | if (this.currentStep && this.currentStep.hasOwnProperty('route')) { 100 | this.hideStep(this.currentStep); 101 | } 102 | }); 103 | } 104 | 105 | public end(): void { 106 | this.status = TourState.OFF; 107 | this.hideStep(this.currentStep); 108 | this.currentStep = undefined; 109 | this.end$.next(); 110 | } 111 | 112 | public pause(): void { 113 | this.status = TourState.PAUSED; 114 | this.hideStep(this.currentStep); 115 | this.pause$.next(); 116 | } 117 | 118 | public resume(): void { 119 | this.status = TourState.ON; 120 | this.showStep(this.currentStep); 121 | this.resume$.next(); 122 | } 123 | 124 | public toggle(pause?: boolean): void { 125 | if (pause) { 126 | if (this.currentStep) { 127 | this.pause(); 128 | } else { 129 | this.resume(); 130 | } 131 | } else { 132 | if (this.currentStep) { 133 | this.end(); 134 | } else { 135 | this.start(); 136 | } 137 | } 138 | } 139 | 140 | public next(): void { 141 | if (this.hasNext(this.currentStep)) { 142 | this.goToStep( 143 | this.loadStep( 144 | this.currentStep.nextStep || this.steps.indexOf(this.currentStep) + 1 145 | ) 146 | ); 147 | } 148 | } 149 | 150 | public hasNext(step: T): boolean { 151 | if (!step) { 152 | console.warn('Can\'t get next step. No currentStep.'); 153 | return false; 154 | } 155 | return ( 156 | step.nextStep !== undefined || 157 | this.steps.indexOf(step) < this.steps.length - 1 158 | ); 159 | } 160 | 161 | public prev(): void { 162 | if (this.hasPrev(this.currentStep)) { 163 | this.goToStep( 164 | this.loadStep( 165 | this.currentStep.prevStep || this.steps.indexOf(this.currentStep) - 1 166 | ) 167 | ); 168 | } 169 | } 170 | 171 | public hasPrev(step: T): boolean { 172 | if (!step) { 173 | console.warn('Can\'t get previous step. No currentStep.'); 174 | return false; 175 | } 176 | return step.prevStep !== undefined || this.steps.indexOf(step) > 0; 177 | } 178 | 179 | public goto(stepId: number | string): void { 180 | this.goToStep(this.loadStep(stepId)); 181 | } 182 | 183 | public register(anchorId: string, anchor: TourAnchorDirective): void { 184 | if (!anchorId) { 185 | return; 186 | } 187 | if (this.anchors[anchorId]) { 188 | throw new Error('anchorId ' + anchorId + ' already registered!'); 189 | } 190 | this.anchors[anchorId] = anchor; 191 | this.anchorRegister$.next(anchorId); 192 | } 193 | 194 | public unregister(anchorId: string): void { 195 | if (!anchorId) { 196 | return; 197 | } 198 | delete this.anchors[anchorId]; 199 | this.anchorUnregister$.next(anchorId); 200 | } 201 | 202 | public getStatus(): TourState { 203 | return this.status; 204 | } 205 | 206 | public isHotkeysEnabled(): boolean { 207 | return this.isHotKeysEnabled; 208 | } 209 | 210 | private goToStep(step: T): void { 211 | if (!step) { 212 | console.warn('Can\'t go to non-existent step'); 213 | this.end(); 214 | return; 215 | } 216 | let navigatePromise: Promise = new Promise(resolve => 217 | resolve(true) 218 | ); 219 | if (step.route !== undefined && typeof step.route === 'string') { 220 | navigatePromise = this.router.navigateByUrl(step.route); 221 | } else if (step.route && Array.isArray(step.route)) { 222 | navigatePromise = this.router.navigate(step.route); 223 | } 224 | navigatePromise.then(navigated => { 225 | if (navigated !== false) { 226 | setTimeout(() => this.setCurrentStep(step)); 227 | } 228 | }); 229 | } 230 | 231 | private loadStep(stepId: number | string): T { 232 | if (typeof stepId === 'number') { 233 | return this.steps[stepId]; 234 | } else { 235 | return this.steps.find(step => step.stepId === stepId); 236 | } 237 | } 238 | 239 | private setCurrentStep(step: T): void { 240 | if (this.currentStep) { 241 | this.hideStep(this.currentStep); 242 | } 243 | this.currentStep = step; 244 | this.showStep(this.currentStep); 245 | this.router.events 246 | .pipe(filter(event => event instanceof NavigationStart), first()) 247 | .subscribe(() => { 248 | if (this.currentStep && this.currentStep.hasOwnProperty('route')) { 249 | this.hideStep(this.currentStep); 250 | } 251 | }); 252 | } 253 | 254 | private showStep(step: T): void { 255 | const anchor = this.anchors[step && step.anchorId]; 256 | if (!anchor) { 257 | console.warn( 258 | 'Can\'t attach to unregistered anchor with id ' + step.anchorId 259 | ); 260 | this.end(); 261 | return; 262 | } 263 | anchor.showTourStep(step); 264 | this.stepShow$.next(step); 265 | } 266 | 267 | private hideStep(step: T): void { 268 | const anchor = this.anchors[step && step.anchorId]; 269 | if (!anchor) { 270 | return; 271 | } 272 | anchor.hideTourStep(); 273 | this.stepHide$.next(step); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-tour-core 3 | */ 4 | 5 | export { TourModule, TourService } from './lib/tour.module'; 6 | export { IStepOption, TourState } from './lib/tour.service'; 7 | export { TourAnchorDirective } from './lib/tour-anchor.directive'; 8 | export { TourHotkeyListenerComponent } from './lib/tour-hotkey-listener.component'; 9 | export { isInViewport, ElementSides } from './lib/is-in-viewport'; 10 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/zone-testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { 8 | BrowserDynamicTestingModule, 9 | platformBrowserDynamicTesting 10 | } from '@angular/platform-browser-dynamic/testing'; 11 | 12 | declare const require: any; 13 | 14 | // First, initialize the Angular testing environment. 15 | getTestBed().initTestEnvironment( 16 | BrowserDynamicTestingModule, 17 | platformBrowserDynamicTesting() 18 | ); 19 | // Then we find all the tests. 20 | const context = require.context('./', true, /\.spec\.ts$/); 21 | // And load the modules. 22 | context.keys().map(context); 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2015" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true, 25 | "flatModuleId": "AUTOGENERATED", 26 | "flatModuleOutFile": "AUTOGENERATED" 27 | }, 28 | "exclude": [ 29 | "src/test.ts", 30 | "**/*.spec.ts" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "enableIvy": false 5 | } 6 | } -------------------------------------------------------------------------------- /projects/ngx-tour-core/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": [ 6 | "jest", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngx-tour-core/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": false, 5 | "component-selector": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [4.3.0](https://github.com/isaacplmann/ngx-tour) (2020-08-17) 4 | 5 | ### Features 6 | 7 | - Replaced `withinviewport()` function from 3rd party library with our own custom `isInViewport()` function to fix 8 | CommonJS warning in Angular 10, reduce bundle size and to remove non-peer dependency 9 | 10 | 11 | 12 | # [4.2.0](https://github.com/isaacplmann/ngx-tour) (2020-08-10) 13 | 14 | ### Features 15 | 16 | - Support Angular 10 17 | 18 | 19 | 20 | # [4.1.1](https://github.com/isaacplmann/ngx-tour) (2019-12-07) 21 | 22 | ### Fixes 23 | 24 | - Skip undefined tourAnchors 25 | 26 | 27 | 28 | # [4.1.0](https://github.com/isaacplmann/ngx-tour) (2019-10-23) 29 | 30 | ### Features 31 | 32 | - Support Angular 8 as peer dependency 33 | - Support Ivy renderer 34 | 35 | 36 | 37 | # [4.0.1](https://github.com/isaacplmann/ngx-tour) (2018-12-05) 38 | 39 | ### Fixes 40 | 41 | - NavigationStart only hide currentStep if route is specified eg. routing used 42 | 43 | 44 | 45 | # [4.0.0](https://github.com/isaacplmann/ngx-tour) (2018-11-27) 46 | 47 | ### BREAKING CHANGES 48 | 49 | - Require Angular 7 as peer dependency 50 | - Require Angular Material 7 as peer dependency 51 | 52 | 53 | 54 | # [3.1.1](https://github.com/isaacplmann/ngx-tour) (2018-08-23) 55 | 56 | ### Bug fixes 57 | 58 | - Add class to backdrop element 59 | 60 | 61 | 62 | # [3.1.0](https://github.com/isaacplmann/ngx-tour) (2018-08-16) 63 | 64 | ### Features 65 | 66 | - EnableBackdrop option 67 | 68 | 69 | 70 | # [3.0.0](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 71 | 72 | ### BREAKING CHANGES 73 | 74 | - Require Angular 6 as peer dependency 75 | - Require Angular Material 6 as peer dependency 76 | 77 | 78 | 79 | # [2.0.0](https://github.com/isaacplmann/ngx-tour) (2017-01-31) 80 | 81 | ### Features 82 | 83 | - Add touranchor-is-active class 84 | - Add options to set button text 85 | 86 | 87 | 88 | # [2.0.0-rc.2](https://github.com/isaacplmann/ngx-tour) (2017-10-20) 89 | 90 | ### BREAKING CHANGES 91 | 92 | - Update to ngx-tour-core 2.x (Angular 5 and disabling hotkeys) 93 | - Update @angular/material to 5.0.0-rc.2 94 | 95 | 96 | 97 | # [2.0.0-beta.12](https://github.com/isaacplmann/ngx-tour) (2017-10-20) 98 | 99 | ### BREAKING CHANGES 100 | 101 | - Update @angular/material to 2.0.0-beta.12 102 | - Except for the library name, all 'md-' strings have been changed to 'mat-' 103 | 104 | 105 | 106 | # [1.0.4](https://github.com/isaacplmann/ngx-tour) (2017-08-30) 107 | 108 | ### Bug fixes 109 | 110 | - Update @angular/material to 2.0.0-beta.10 111 | 112 | 113 | 114 | # [1.0.3](https://github.com/isaacplmann/ngx-tour) (2017-07-31) 115 | 116 | ### Bug fixes 117 | 118 | - Fix aot build 119 | 120 | 121 | 122 | # [1.0.2](https://github.com/isaacplmann/ngx-tour) (2017-07-19) 123 | 124 | ### Docs 125 | 126 | - Add readme 127 | 128 | 129 | 130 | # [1.0.1](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 131 | 132 | ### Bug fixes 133 | 134 | - Export all of core exports 135 | 136 | 137 | 138 | # [1.0.0](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 139 | 140 | ### BREAKING CHANGES 141 | 142 | - Split out to a separate package 143 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/README.md: -------------------------------------------------------------------------------- 1 | # Ngx-Tour Md-Menu 2 | [![Dependency Status](https://david-dm.org/isaacplmann/ngx-tour-md-menu.svg)](https://david-dm.org/isaacplmann/ngx-tour-md-menu) 3 | [![devDependency Status](https://david-dm.org/isaacplmann/ngx-tour-md-menu/dev-status.svg)](https://david-dm.org/isaacplmann/ngx-tour-md-menu?type=dev) 4 | 5 | Check out the [documentation/demo page](https://isaacplmann.github.io/ngx-tour). 6 | 7 | This is a product tour library built with Angular (2+). It's inspired by [angular-ui-tour](http://benmarch.github.io/angular-ui-tour). 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-md-menu", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-md-menu", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour-md-menu", 3 | "version": "4.3.0", 4 | "repository": "https://github.com/isaacplmann/ngx-tour.git", 5 | "author": "Isaac Mann ", 6 | "license": "MIT", 7 | "dependencies": { 8 | "tslib": "^2.0.0" 9 | }, 10 | "peerDependencies": { 11 | "@angular/common": ">=7.0.0 <11.0.0", 12 | "@angular/core": ">=7.0.0 <11.0.0", 13 | "@angular/animations": ">=7.0.0 <11.0.0", 14 | "@angular/cdk": ">=7.0.0 <11.0.0", 15 | "@angular/material": ">=7.0.0 <11.0.0", 16 | "ngx-tour-core": "^4.3.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/md-menu.module.ts: -------------------------------------------------------------------------------- 1 | import { TourAnchorOpenerComponent } from './tour-anchor-opener.component'; 2 | import { CommonModule } from '@angular/common'; 3 | import { ModuleWithProviders, NgModule } from '@angular/core'; 4 | import { MatButtonModule } from '@angular/material/button'; 5 | import { MatCardModule } from '@angular/material/card'; 6 | import { MatIconModule } from '@angular/material/icon'; 7 | import { MatMenuModule } from '@angular/material/menu'; 8 | 9 | import {TourModule, TourService} from 'ngx-tour-core'; 10 | import { TourAnchorMatMenuDirective } from './tour-anchor.directive'; 11 | import { TourStepTemplateComponent } from './tour-step-template.component'; 12 | import { TourStepTemplateService } from './tour-step-template.service'; 13 | import {TourBackdropService} from './tour-backdrop.service'; 14 | import {NgxmTourService} from './ngx-md-menu-tour.service'; 15 | 16 | export { TourAnchorMatMenuDirective, TourStepTemplateComponent, NgxmTourService }; 17 | 18 | @NgModule({ 19 | declarations: [TourAnchorMatMenuDirective, TourStepTemplateComponent, TourAnchorOpenerComponent], 20 | entryComponents: [TourAnchorOpenerComponent], 21 | exports: [TourAnchorMatMenuDirective, TourStepTemplateComponent, TourModule], 22 | imports: [CommonModule, TourModule, 23 | MatMenuModule, MatCardModule, MatButtonModule, MatIconModule, 24 | ], 25 | }) 26 | export class TourMatMenuModule { 27 | public static forRoot(): ModuleWithProviders { 28 | return { 29 | ngModule: TourMatMenuModule, 30 | providers: [ 31 | TourStepTemplateService, 32 | TourBackdropService, 33 | TourService, 34 | NgxmTourService 35 | ] 36 | }; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/ngx-md-menu-tour.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { TourService } from 'ngx-tour-core'; 3 | 4 | import { INgxmStepOption } from './step-option.interface'; 5 | 6 | @Injectable() 7 | export class NgxmTourService extends TourService {} 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/step-option.interface.ts: -------------------------------------------------------------------------------- 1 | import { IStepOption } from 'ngx-tour-core'; 2 | 3 | export interface INgxmStepOption extends IStepOption { 4 | enableBackdrop?: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/tour-anchor-opener.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ViewChild, Input } from '@angular/core'; 2 | import { MatMenuTrigger, MatMenu } from '@angular/material/menu'; 3 | 4 | @Component({ 5 | selector: 'tourAnchorOpener', 6 | styles: [ 7 | ` 8 | :host { 9 | display: none; 10 | } 11 | ` 12 | ], 13 | template: ` 14 | 15 | ` 16 | }) 17 | export class TourAnchorOpenerComponent { 18 | @Input() menu: MatMenu = new MatMenu(undefined, undefined, { 19 | xPosition: 'after', 20 | yPosition: 'below', 21 | overlapTrigger: true, 22 | backdropClass: '' 23 | }); 24 | 25 | @ViewChild(MatMenuTrigger) public trigger: MatMenuTrigger; 26 | } 27 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/tour-anchor.directive.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ComponentFactoryResolver, 3 | Directive, 4 | ElementRef, 5 | HostBinding, 6 | Injector, 7 | Input, 8 | ViewContainerRef 9 | } from '@angular/core'; 10 | import type {OnDestroy, OnInit} from '@angular/core'; 11 | import { 12 | ElementSides, 13 | isInViewport, 14 | TourAnchorDirective, 15 | TourState 16 | } from 'ngx-tour-core'; 17 | import { Subscription } from 'rxjs'; 18 | 19 | import { TourAnchorOpenerComponent } from './tour-anchor-opener.component'; 20 | import { TourStepTemplateService } from './tour-step-template.service'; 21 | import { first } from 'rxjs/operators'; 22 | import {TourBackdropService} from './tour-backdrop.service'; 23 | import { INgxmStepOption as IStepOption } from './step-option.interface'; 24 | import {NgxmTourService} from './ngx-md-menu-tour.service'; 25 | 26 | @Directive({ 27 | selector: '[tourAnchor]' 28 | }) 29 | export class TourAnchorMatMenuDirective 30 | implements OnInit, OnDestroy, TourAnchorDirective { 31 | @Input() public tourAnchor: string; 32 | public opener: TourAnchorOpenerComponent; 33 | public menuCloseSubscription: Subscription; 34 | 35 | @HostBinding('class.touranchor--is-active') public isActive: boolean; 36 | 37 | constructor( 38 | private componentFactoryResolver: ComponentFactoryResolver, 39 | private injector: Injector, 40 | private viewContainer: ViewContainerRef, 41 | private element: ElementRef, 42 | private tourService: NgxmTourService, 43 | private tourStepTemplate: TourStepTemplateService, 44 | private tourBackdrop: TourBackdropService 45 | ) { 46 | this.opener = this.viewContainer.createComponent( 47 | this.componentFactoryResolver.resolveComponentFactory( 48 | TourAnchorOpenerComponent 49 | ) 50 | ).instance; 51 | } 52 | 53 | public ngOnInit(): void { 54 | this.tourService.register(this.tourAnchor, this); 55 | } 56 | 57 | public ngOnDestroy(): void { 58 | this.tourService.unregister(this.tourAnchor); 59 | } 60 | 61 | public showTourStep(step: IStepOption): void { 62 | const htmlElement: HTMLElement = this.element.nativeElement; 63 | 64 | this.isActive = true; 65 | this.tourStepTemplate.templateComponent.step = step; 66 | // Ignore step.placement 67 | if (!step.preventScrolling) { 68 | if (!isInViewport(htmlElement, ElementSides.Bottom)) { 69 | htmlElement.scrollIntoView(false); 70 | } else if (!isInViewport(htmlElement, ElementSides.Top)) { 71 | htmlElement.scrollIntoView(true); 72 | } 73 | } 74 | (this.opener.trigger)._element = this.element; 75 | this.opener.trigger.menu = this.tourStepTemplate.templateComponent.tourStep; 76 | this.opener.trigger.ngAfterContentInit(); 77 | this.opener.trigger.openMenu(); 78 | 79 | if (step.enableBackdrop) { 80 | this.tourBackdrop.show(this.element); 81 | } else { 82 | this.tourBackdrop.close(); 83 | } 84 | 85 | step.prevBtnTitle = step.prevBtnTitle || 'Prev'; 86 | step.nextBtnTitle = step.nextBtnTitle || 'Next'; 87 | step.endBtnTitle = step.endBtnTitle || 'End'; 88 | 89 | if (this.menuCloseSubscription) { 90 | this.menuCloseSubscription.unsubscribe(); 91 | } 92 | this.menuCloseSubscription = this.opener.trigger.menuClosed 93 | .pipe(first()) 94 | .subscribe(() => { 95 | if (this.tourService.getStatus() !== TourState.OFF) { 96 | this.tourService.end(); 97 | } 98 | this.tourBackdrop.close(); 99 | }); 100 | } 101 | 102 | public hideTourStep(): void { 103 | this.isActive = false; 104 | if (this.menuCloseSubscription) { 105 | this.menuCloseSubscription.unsubscribe(); 106 | } 107 | this.opener.trigger.closeMenu(); 108 | if (this.tourService.getStatus() === TourState.OFF) { 109 | this.tourBackdrop.close(); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/tour-backdrop.service.ts: -------------------------------------------------------------------------------- 1 | import { ElementRef, Injectable, RendererFactory2 } from '@angular/core'; 2 | import type { Renderer2 } from '@angular/core'; 3 | 4 | @Injectable() 5 | export class TourBackdropService { 6 | private renderer: Renderer2; 7 | private backdropElement: HTMLElement; 8 | 9 | constructor(rendererFactory: RendererFactory2) { 10 | this.renderer = rendererFactory.createRenderer(null, null); 11 | } 12 | 13 | public show(targetElement: ElementRef) { 14 | const boundingRect = targetElement.nativeElement.getBoundingClientRect(); 15 | 16 | if (!this.backdropElement) { 17 | this.backdropElement = this.renderer.createElement('div'); 18 | this.renderer.addClass(this.backdropElement, 'ngx-tour_backdrop'); 19 | this.renderer.appendChild(document.body, this.backdropElement); 20 | } 21 | 22 | this.setStyles(boundingRect); 23 | } 24 | 25 | public close() { 26 | if (this.backdropElement) { 27 | this.renderer.removeChild(document.body, this.backdropElement); 28 | this.backdropElement = null; 29 | } 30 | } 31 | 32 | private setStyles(boundingRect: DOMRect) { 33 | const styles = { 34 | position: 'fixed', 35 | width: boundingRect.width + 'px', 36 | height: boundingRect.height + 'px', 37 | top: boundingRect.top + 'px', 38 | left: boundingRect.left + 'px', 39 | 'box-shadow': '0 0 0 9999px rgba(0, 0, 0, 0.7)', 40 | 'z-index': '100' 41 | }; 42 | 43 | for (const name of Object.keys(styles)) { 44 | this.renderer.setStyle(this.backdropElement, name, styles[name]); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/tour-step-template.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AfterViewInit, 3 | Component, 4 | ContentChild, 5 | Input, 6 | TemplateRef, 7 | ViewChild 8 | } from '@angular/core'; 9 | import { MatMenu } from '@angular/material/menu'; 10 | import { IStepOption, TourHotkeyListenerComponent } from 'ngx-tour-core'; 11 | 12 | import { TourStepTemplateService } from './tour-step-template.service'; 13 | import { NgxmTourService } from './ngx-md-menu-tour.service'; 14 | 15 | @Component({ 16 | selector: 'tour-step-template', 17 | styles: [ 18 | ` 19 | ::ng-deep .tour-step .mat-menu-content { 20 | padding: 0 !important; 21 | } 22 | ` 23 | ], 24 | template: ` 25 | 26 | 32 | 33 | 34 | 35 | 36 | {{ step?.title }} 37 | 38 | 39 | 40 | 41 | 48 | 55 | 58 | 59 | 60 | 61 | ` 62 | }) 63 | export class TourStepTemplateComponent extends TourHotkeyListenerComponent 64 | implements AfterViewInit { 65 | @ViewChild(MatMenu) public tourStep: MatMenu; 66 | 67 | @Input() 68 | public stepTemplate: TemplateRef<{ step: IStepOption }>; 69 | 70 | @ContentChild(TemplateRef) 71 | public stepTemplateContent: TemplateRef<{ step: IStepOption }>; 72 | 73 | public step: IStepOption = {}; 74 | 75 | constructor( 76 | private tourStepTemplateService: TourStepTemplateService, 77 | public tourService: NgxmTourService 78 | ) { 79 | super(tourService); 80 | } 81 | 82 | public ngAfterViewInit(): void { 83 | this.tourStepTemplateService.templateComponent = this; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/lib/tour-step-template.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | import { TourStepTemplateComponent } from './tour-step-template.component'; 4 | 5 | @Injectable() 6 | export class TourStepTemplateService { 7 | public templateComponent: TourStepTemplateComponent; 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-tour-md-menu 3 | */ 4 | 5 | export { INgxmStepOption as IStepOption } from './lib/step-option.interface'; 6 | export { NgxmTourService as TourService } from './lib/ngx-md-menu-tour.service'; 7 | export { 8 | TourMatMenuModule, 9 | TourAnchorMatMenuDirective, 10 | TourStepTemplateComponent 11 | } from './lib/md-menu.module'; 12 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/zone-testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { 8 | BrowserDynamicTestingModule, 9 | platformBrowserDynamicTesting 10 | } from '@angular/platform-browser-dynamic/testing'; 11 | 12 | declare const require: any; 13 | 14 | // First, initialize the Angular testing environment. 15 | getTestBed().initTestEnvironment( 16 | BrowserDynamicTestingModule, 17 | platformBrowserDynamicTesting() 18 | ); 19 | // Then we find all the tests. 20 | const context = require.context('./', true, /\.spec\.ts$/); 21 | // And load the modules. 22 | context.keys().map(context); 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2015" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true, 25 | "flatModuleId": "AUTOGENERATED", 26 | "flatModuleOutFile": "AUTOGENERATED" 27 | }, 28 | "exclude": [ 29 | "src/test.ts", 30 | "**/*.spec.ts" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "enableIvy": false 5 | } 6 | } -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngx-tour-md-menu/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": false, 5 | "component-selector": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [6.1.0](https://github.com/isaacplmann/ngx-tour) (2020-08-17) 4 | 5 | ### Features 6 | 7 | - Replaced `withinviewport()` function from 3rd party library with our own custom `isInViewport()` function to fix 8 | CommonJS warning in Angular 10, reduce bundle size and to remove non-peer dependency 9 | 10 | 11 | 12 | # [6.0.0](https://github.com/isaacplmann/ngx-tour) (2020-08-10) 13 | 14 | ### Features 15 | 16 | - Support Angular 10 17 | 18 | ### BREAKING CHANGES 19 | 20 | - Require ng-bootstrap ^7.0.0 21 | 22 | 23 | 24 | # [5.0.0](https://github.com/isaacplmann/ngx-tour) (2020-02-19) 25 | 26 | ### BREAKING CHANGES 27 | 28 | - Require ng-bootstrap ^5.0.0 29 | 30 | 31 | 32 | # [4.1.1](https://github.com/isaacplmann/ngx-tour) (2019-12-07) 33 | 34 | ### Fixes 35 | 36 | - Skip undefined tourAnchors 37 | 38 | 39 | 40 | # [4.1.0](https://github.com/isaacplmann/ngx-tour) (2019-10-23) 41 | 42 | ### Features 43 | 44 | - Support Angular 8 as peer dependency 45 | - Support Ivy renderer 46 | 47 | 48 | 49 | # [4.0.1](https://github.com/isaacplmann/ngx-tour) (2018-12-05) 50 | 51 | ### Fixes 52 | 53 | - NavigationStart only hide currentStep if route is specified eg. routing used 54 | 55 | 56 | 57 | # [4.0.0](https://github.com/isaacplmann/ngx-tour) (2018-11-27) 58 | 59 | ### BREAKING CHANGES 60 | 61 | - Require Angular 7 as peer dependency 62 | - Require ng-bootstrap 4 as peer dependency 63 | 64 | 65 | 66 | # [3.0.0](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 67 | 68 | ### BREAKING CHANGES 69 | 70 | - Require Angular 6 as peer dependency 71 | - Require ng-bootstrap 2 as peer dependency 72 | 73 | 74 | 75 | # [2.0.1](https://github.com/isaacplmann/ngx-tour) (2017-04-24) 76 | 77 | ### Bug Fixes 78 | 79 | - Clicking tourAnchor closed and re-opened the tour 80 | 81 | 82 | 83 | # [2.0.0](https://github.com/isaacplmann/ngx-tour) (2017-01-31) 84 | 85 | ### Features 86 | 87 | - Add touranchor-is-active class 88 | - Add options to set button text 89 | 90 | 91 | 92 | # [2.0.0-beta.5-2](https://github.com/isaacplmann/ngx-tour) (2017-11-28) 93 | 94 | ### BREAKING CHANGE 95 | 96 | - Require Angular 5 97 | 98 | ### Features 99 | 100 | - Disable/enable hotkeys 101 | 102 | 103 | 104 | # [2.0.0-beta.5-1](https://github.com/isaacplmann/ngx-tour) (2017-10-17) 105 | 106 | ### Features 107 | 108 | - Allow all placement options 109 | 110 | 111 | 112 | # [2.0.0-beta.5](https://github.com/isaacplmann/ngx-tour) (2017-09-19) 113 | 114 | ### BREAKING CHANGES 115 | 116 | - Update to ng-bootstrap@1.0.0-beta.5 and bootstrap 4 117 | 118 | 119 | 120 | # [1.0.6](https://github.com/isaacplmann/ngx-tour) (2017-08-10) 121 | 122 | ### Bug fixes 123 | 124 | - Fix bundling for real this time 125 | 126 | 127 | 128 | # [1.0.5](https://github.com/isaacplmann/ngx-tour) (2017-08-09) 129 | 130 | ### Bug fixes 131 | 132 | - Fix bundling to not include ng-bootstrap library 133 | 134 | 135 | 136 | # [1.0.4](https://github.com/isaacplmann/ngx-tour) (2017-08-01) 137 | 138 | ### Bug fixes 139 | 140 | - Export TourService 141 | 142 | 143 | 144 | # [1.0.3](https://github.com/isaacplmann/ngx-tour) (2017-07-20) 145 | 146 | ### Bug fixes 147 | 148 | - Remove max-height style 149 | 150 | 151 | 152 | # [1.0.2](https://github.com/isaacplmann/ngx-tour) (2017-07-19) 153 | 154 | ### Docs 155 | 156 | - Add readme 157 | 158 | 159 | 160 | # [1.0.1](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 161 | 162 | ### Bug fixes 163 | 164 | - Export all of core exports 165 | 166 | 167 | 168 | # [1.0.0](https://github.com/isaacplmann/ngx-tour) (2017-07-18) 169 | 170 | ### BREAKING CHANGES 171 | 172 | - Split out to a separate package 173 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/README.md: -------------------------------------------------------------------------------- 1 | # Ngx-Tour Ng-Bootstrap 2 | [![Dependency Status](https://david-dm.org/isaacplmann/ngx-tour-ng-bootstrap.svg)](https://david-dm.org/isaacplmann/ngx-tour-ng-bootstrap) 3 | [![devDependency Status](https://david-dm.org/isaacplmann/ngx-tour-ng-bootstrap/dev-status.svg)](https://david-dm.org/isaacplmann/ngx-tour-ng-bootstrap?type=dev) 4 | 5 | Check out the [documentation/demo page](https://isaacplmann.github.io/ngx-tour). 6 | 7 | This is a product tour library built with Angular (2+). It's inspired by [angular-ui-tour](http://benmarch.github.io/angular-ui-tour). 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-ng-bootstrap", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-ng-bootstrap", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour-ng-bootstrap", 3 | "version": "6.1.0", 4 | "repository": "https://github.com/isaacplmann/ngx-tour.git", 5 | "author": "Isaac Mann ", 6 | "license": "MIT", 7 | "peerDependencies": { 8 | "@angular/common": ">=7.0.0 <11.0.0", 9 | "@angular/core": ">=7.0.0 <11.0.0", 10 | "@ng-bootstrap/ng-bootstrap": ">=7.0.0", 11 | "ngx-tour-core": "^4.3.0" 12 | }, 13 | "dependencies": { 14 | "tslib": "^2.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/lib/ng-bootstrap-tour.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { TourService } from 'ngx-tour-core'; 3 | 4 | import { INgbStepOption } from './step-option.interface'; 5 | 6 | @Injectable({ 7 | providedIn: 'root', 8 | }) 9 | export class NgbTourService extends TourService {} 10 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/lib/ng-bootstrap.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; 4 | import {TourService} from 'ngx-tour-core'; 5 | 6 | import { NgbTourService } from './ng-bootstrap-tour.service'; 7 | import { TourAnchorNgBootstrapDirective, TourAnchorNgBootstrapPopoverDirective } from './tour-anchor.directive'; 8 | import { TourStepTemplateComponent } from './tour-step-template.component'; 9 | import { TourStepTemplateService } from './tour-step-template.service'; 10 | 11 | export { TourAnchorNgBootstrapDirective, TourAnchorNgBootstrapPopoverDirective, TourStepTemplateComponent, NgbTourService }; 12 | 13 | @NgModule({ 14 | declarations: [TourAnchorNgBootstrapDirective, TourAnchorNgBootstrapPopoverDirective, TourStepTemplateComponent], 15 | exports: [TourAnchorNgBootstrapDirective, TourAnchorNgBootstrapPopoverDirective, TourStepTemplateComponent], 16 | imports: [CommonModule, NgbPopoverModule], 17 | }) 18 | export class TourNgBootstrapModule { 19 | public static forRoot(): ModuleWithProviders { 20 | return { 21 | ngModule: TourNgBootstrapModule, 22 | providers: [ 23 | TourStepTemplateService, 24 | TourService, 25 | NgbTourService 26 | ], 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/lib/step-option.interface.ts: -------------------------------------------------------------------------------- 1 | import { IStepOption } from 'ngx-tour-core'; 2 | import { Placement } from '@ng-bootstrap/ng-bootstrap'; 3 | 4 | export interface INgbStepOption extends IStepOption { 5 | placement?: Placement | 'after' | 'after-top' | 'after-bottom' | 6 | 'top-after' | 'top-before' | 'bottom-after' | 'bottom-before' | 7 | 'before' | 'before-top' | 'before-bottom'| 'below' | 'above'; 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/lib/tour-anchor.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, Host, HostBinding, Input } from '@angular/core'; 2 | import type {OnDestroy, OnInit} from '@angular/core'; 3 | import { NgbPopover, Placement } from '@ng-bootstrap/ng-bootstrap'; 4 | import {ElementSides, isInViewport, TourAnchorDirective} from 'ngx-tour-core'; 5 | 6 | import { NgbTourService } from './ng-bootstrap-tour.service'; 7 | import { INgbStepOption } from './step-option.interface'; 8 | import { TourStepTemplateService } from './tour-step-template.service'; 9 | 10 | 11 | @Directive({ selector: '[tourAnchor]' }) 12 | export class TourAnchorNgBootstrapPopoverDirective extends NgbPopover { } 13 | 14 | @Directive({ 15 | selector: '[tourAnchor]', 16 | }) 17 | export class TourAnchorNgBootstrapDirective implements OnInit, OnDestroy, TourAnchorDirective { 18 | @Input() public tourAnchor: string; 19 | 20 | @HostBinding('class.touranchor--is-active') 21 | public isActive: boolean; 22 | 23 | constructor( 24 | private tourService: NgbTourService, 25 | private tourStepTemplate: TourStepTemplateService, 26 | private element: ElementRef, 27 | @Host() private popoverDirective: TourAnchorNgBootstrapPopoverDirective, 28 | ) { 29 | this.popoverDirective.autoClose = false; 30 | this.popoverDirective.triggers = ''; 31 | this.popoverDirective.toggle = () => { }; 32 | } 33 | 34 | public ngOnInit(): void { 35 | this.tourService.register(this.tourAnchor, this); 36 | } 37 | 38 | public ngOnDestroy(): void { 39 | this.tourService.unregister(this.tourAnchor); 40 | } 41 | 42 | public showTourStep(step: INgbStepOption): void { 43 | const htmlElement: HTMLElement = this.element.nativeElement; 44 | 45 | this.isActive = true; 46 | this.popoverDirective.ngbPopover = this.tourStepTemplate.template; 47 | this.popoverDirective.popoverTitle = step.title; 48 | this.popoverDirective.container = 'body'; 49 | this.popoverDirective.placement = (step.placement || 'top') 50 | .replace('before', 'left').replace('after', 'right') 51 | .replace('below', 'bottom').replace('above', 'top'); 52 | step.prevBtnTitle = step.prevBtnTitle || 'Prev'; 53 | step.nextBtnTitle = step.nextBtnTitle || 'Next'; 54 | step.endBtnTitle = step.endBtnTitle || 'End'; 55 | 56 | this.popoverDirective.open({ step }); 57 | if (!step.preventScrolling) { 58 | if (!isInViewport(htmlElement, ElementSides.Bottom)) { 59 | htmlElement.scrollIntoView(false); 60 | } else if (!isInViewport(htmlElement, ElementSides.Top)) { 61 | htmlElement.scrollIntoView(true); 62 | } 63 | } 64 | } 65 | 66 | public hideTourStep(): void { 67 | this.isActive = false; 68 | this.popoverDirective.close(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/lib/tour-step-template.component.ts: -------------------------------------------------------------------------------- 1 | import { TourHotkeyListenerComponent, IStepOption } from 'ngx-tour-core'; 2 | import { TourStepTemplateService } from './tour-step-template.service'; 3 | import { 4 | Component, 5 | TemplateRef, 6 | ViewChild, 7 | AfterContentInit, 8 | ViewEncapsulation, 9 | Input, 10 | ContentChild 11 | } from '@angular/core'; 12 | import { NgbTourService } from './ng-bootstrap-tour.service'; 13 | 14 | @Component({ 15 | encapsulation: ViewEncapsulation.None, 16 | selector: 'tour-step-template', 17 | template: ` 18 | 19 |

20 |
21 | 28 | 35 | 38 |
39 |
40 | ` 41 | }) 42 | export class TourStepTemplateComponent extends TourHotkeyListenerComponent 43 | implements AfterContentInit { 44 | @ViewChild('tourStep', { read: TemplateRef, static: true }) 45 | public defaultTourStepTemplate: TemplateRef; 46 | 47 | @Input() 48 | public stepTemplate: TemplateRef<{ step: IStepOption }>; 49 | 50 | @ContentChild(TemplateRef) 51 | public stepTemplateContent: TemplateRef<{ step: IStepOption }>; 52 | 53 | constructor( 54 | private tourStepTemplateService: TourStepTemplateService, 55 | public tourService: NgbTourService 56 | ) { 57 | super(tourService); 58 | } 59 | 60 | public ngAfterContentInit(): void { 61 | this.tourStepTemplateService.template = 62 | this.stepTemplate || 63 | this.stepTemplateContent || 64 | this.defaultTourStepTemplate; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/lib/tour-step-template.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, TemplateRef } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class TourStepTemplateService { 5 | public template: TemplateRef<{content: string}>; 6 | } 7 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-tour-ng-bootstrap 3 | */ 4 | 5 | export { INgbStepOption as IStepOption } from './lib/step-option.interface'; 6 | export { NgbTourService as TourService } from './lib/ng-bootstrap-tour.service'; 7 | export { 8 | TourNgBootstrapModule, 9 | TourAnchorNgBootstrapDirective, 10 | TourStepTemplateComponent 11 | } from './lib/ng-bootstrap.module'; 12 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/zone-testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { 8 | BrowserDynamicTestingModule, 9 | platformBrowserDynamicTesting 10 | } from '@angular/platform-browser-dynamic/testing'; 11 | 12 | declare const require: any; 13 | 14 | // First, initialize the Angular testing environment. 15 | getTestBed().initTestEnvironment( 16 | BrowserDynamicTestingModule, 17 | platformBrowserDynamicTesting() 18 | ); 19 | // Then we find all the tests. 20 | const context = require.context('./', true, /\.spec\.ts$/); 21 | // And load the modules. 22 | context.keys().map(context); 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2015" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true, 25 | "flatModuleId": "AUTOGENERATED", 26 | "flatModuleOutFile": "AUTOGENERATED" 27 | }, 28 | "exclude": [ 29 | "src/test.ts", 30 | "**/*.spec.ts" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "enableIvy": false 5 | } 6 | } -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngx-tour-ng-bootstrap/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": false, 5 | "component-selector": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [4.4.0](https://github.com/isaacplmann/ngx-tour) (2020-08-17) 4 | 5 | ### Features 6 | 7 | - Replaced `withinviewport()` function from 3rd party library with our own custom `isInViewport()` function to fix 8 | CommonJS warning in Angular 10, reduce bundle size and to remove non-peer dependency 9 | 10 | 11 | 12 | # [4.3.0](https://github.com/isaacplmann/ngx-tour) (2020-08-10) 13 | 14 | ### Features 15 | 16 | - Support Angular 10 17 | - Support ngx-bootstrap 6 18 | 19 | 20 | 21 | # [4.2.1](https://github.com/isaacplmann/ngx-tour) (2019-12-07) 22 | 23 | ### Fixes 24 | 25 | - Skip undefined tourAnchors 26 | 27 | 28 | 29 | # [4.2.0](https://github.com/isaacplmann/ngx-tour) (2019-10-23) 30 | 31 | ### Features 32 | 33 | - Support Angular 8 as peer dependency 34 | - Support Ivy renderer 35 | 36 | 37 | 38 | # [4.1.0](https://github.com/isaacplmann/ngx-tour) (2018-12-07) 39 | 40 | ### Features 41 | 42 | - Add custom containerClass for step popover (only for ngx-bootstrap version) 43 | 44 | 45 | 46 | # [4.0.1](https://github.com/isaacplmann/ngx-tour) (2018-12-05) 47 | 48 | ### Fixes 49 | 50 | - NavigationStart only hide currentStep if route is specified eg. routing used 51 | - Fix clicking on attached element issue for ngx-bootstrap 52 | 53 | 54 | 55 | # [4.0.0](https://github.com/isaacplmann/ngx-tour) (2018-11-27) 56 | 57 | ### BREAKING CHANGES 58 | 59 | - Require Angular 7 as peer dependency 60 | - Require ngx-bootstrap 3.1 as peer dependency 61 | 62 | 63 | 64 | # [3.0.0](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 65 | 66 | ### BREAKING CHANGES 67 | 68 | - Require Angular 6 as peer dependency 69 | - Require ngx-bootstrap 3 as peer dependency 70 | 71 | 72 | 73 | # [2.0.0](https://github.com/isaacplmann/ngx-tour) (2017-01-31) 74 | 75 | ### Features 76 | 77 | - Add touranchor-is-active class 78 | - Add options to set button text 79 | 80 | ### Fixes 81 | 82 | - No component factory found for PopoverContainerComponent 83 | 84 | 85 | 86 | # [2.0.0-beta.9](https://github.com/isaacplmann/ngx-tour) (2017-11-28) 87 | 88 | ### BREAKING CHANGES 89 | 90 | - Require Angular 5 91 | - Require ngx-bootstrap ^2.0.0-beta.9 92 | 93 | ### Features 94 | 95 | - Disable/enable hotkeys 96 | 97 | 98 | 99 | # [1.0.4](https://github.com/isaacplmann/ngx-tour) (2017-10-23) 100 | 101 | ### BREAKING CHANGES 102 | 103 | - Create plugin for ngx-bootstrap 104 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/README.md: -------------------------------------------------------------------------------- 1 | # Ngx-Tour Ngx-Bootstrap 2 | [![Dependency Status](https://david-dm.org/isaacplmann/ngx-tour-ngx-bootstrap.svg)](https://david-dm.org/isaacplmann/ngx-tour-ngx-bootstrap) 3 | [![devDependency Status](https://david-dm.org/isaacplmann/ngx-tour-ngx-bootstrap/dev-status.svg)](https://david-dm.org/isaacplmann/ngx-tour-ngx-bootstrap?type=dev) 4 | 5 | Check out the [documentation/demo page](https://isaacplmann.github.io/ngx-tour). 6 | 7 | This is a product tour library built with Angular (2+). It's inspired by [angular-ui-tour](http://benmarch.github.io/angular-ui-tour). 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-ngx-bootstrap", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-ngx-bootstrap", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour-ngx-bootstrap", 3 | "version": "4.4.0", 4 | "repository": "https://github.com/isaacplmann/ngx-tour.git", 5 | "author": "Isaac Mann ", 6 | "license": "MIT", 7 | "peerDependencies": { 8 | "@angular/common": ">=7.0.0 <11.0.0", 9 | "@angular/core": ">=7.0.0 <11.0.0", 10 | "ngx-bootstrap": ">=3.1.0 <7.0.0", 11 | "ngx-tour-core": "^4.3.0" 12 | }, 13 | "dependencies": { 14 | "tslib": "^2.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/lib/ngx-bootstrap-tour.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { TourService } from 'ngx-tour-core'; 3 | 4 | import { INgxbStepOption } from './step-option.interface'; 5 | 6 | @Injectable() 7 | export class NgxbTourService extends TourService {} 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/lib/ngx-bootstrap.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { PopoverModule } from 'ngx-bootstrap/popover'; 4 | import {TourService} from 'ngx-tour-core'; 5 | 6 | import { TourAnchorNgxBootstrapDirective, TourAnchorNgxBootstrapPopoverDirective } from './tour-anchor.directive'; 7 | import { TourStepTemplateComponent } from './tour-step-template.component'; 8 | import { TourStepTemplateService } from './tour-step-template.service'; 9 | import { NgxbTourService } from './ngx-bootstrap-tour.service'; 10 | 11 | export { TourAnchorNgxBootstrapDirective, TourAnchorNgxBootstrapPopoverDirective, TourStepTemplateComponent, NgxbTourService }; 12 | export const popoverForRoot: ModuleWithProviders = PopoverModule.forRoot(); 13 | 14 | @NgModule({ 15 | declarations: [TourAnchorNgxBootstrapDirective, TourAnchorNgxBootstrapPopoverDirective, TourStepTemplateComponent], 16 | exports: [TourAnchorNgxBootstrapDirective, TourAnchorNgxBootstrapPopoverDirective, TourStepTemplateComponent], 17 | imports: [CommonModule, popoverForRoot] 18 | }) 19 | export class TourNgxBootstrapModule { 20 | public static forRoot(): ModuleWithProviders { 21 | return { 22 | ngModule: TourNgxBootstrapModule, 23 | providers: [ 24 | TourStepTemplateService, 25 | TourService, 26 | NgxbTourService, 27 | ], 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/lib/step-option.interface.ts: -------------------------------------------------------------------------------- 1 | import { IStepOption } from 'ngx-tour-core'; 2 | 3 | export interface INgxbStepOption extends IStepOption { 4 | placement?: 'top' | 'bottom' | 'left' | 'right' | 'auto'; 5 | containerClass?: string; 6 | } 7 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/lib/tour-anchor.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, Host, HostBinding, Input } from '@angular/core'; 2 | import type {OnDestroy, OnInit} from '@angular/core'; 3 | import { PopoverDirective } from 'ngx-bootstrap/popover'; 4 | import {ElementSides, isInViewport, TourAnchorDirective} from 'ngx-tour-core'; 5 | import { INgxbStepOption as IStepOption } from './step-option.interface'; 6 | 7 | import { NgxbTourService } from './ngx-bootstrap-tour.service'; 8 | import { TourStepTemplateService } from './tour-step-template.service'; 9 | 10 | @Directive({ selector: '[tourAnchor]' }) 11 | export class TourAnchorNgxBootstrapPopoverDirective extends PopoverDirective { } 12 | 13 | @Directive({ 14 | selector: '[tourAnchor]' 15 | }) 16 | export class TourAnchorNgxBootstrapDirective 17 | implements OnInit, OnDestroy, TourAnchorDirective { 18 | @Input() public tourAnchor: string; 19 | 20 | @HostBinding('class.touranchor--is-active') 21 | public isActive: boolean; 22 | 23 | constructor( 24 | private tourService: NgxbTourService, 25 | private tourStepTemplate: TourStepTemplateService, 26 | private element: ElementRef, 27 | @Host() private popoverDirective: TourAnchorNgxBootstrapPopoverDirective 28 | ) { 29 | this.popoverDirective.triggers = ''; 30 | } 31 | 32 | public ngOnInit(): void { 33 | this.tourService.register(this.tourAnchor, this); 34 | } 35 | 36 | public ngOnDestroy(): void { 37 | this.tourService.unregister(this.tourAnchor); 38 | } 39 | 40 | public showTourStep(step: IStepOption): void { 41 | const htmlElement: HTMLElement = this.element.nativeElement; 42 | 43 | this.isActive = true; 44 | this.popoverDirective.popover = this.tourStepTemplate.template; 45 | this.popoverDirective.popoverContext = { step }; 46 | this.popoverDirective.popoverTitle = step.title; 47 | this.popoverDirective.container = 'body'; 48 | this.popoverDirective.containerClass = 'ngx-bootstrap'; 49 | if (step.containerClass) { 50 | this.popoverDirective.containerClass += ` ${step.containerClass}`; 51 | } 52 | this.popoverDirective.placement = step.placement || 'top'; 53 | step.prevBtnTitle = step.prevBtnTitle || 'Prev'; 54 | step.nextBtnTitle = step.nextBtnTitle || 'Next'; 55 | step.endBtnTitle = step.endBtnTitle || 'End'; 56 | this.popoverDirective.show(); 57 | if (!step.preventScrolling) { 58 | if (!isInViewport(htmlElement, ElementSides.Bottom)) { 59 | htmlElement.scrollIntoView(false); 60 | } else if (!isInViewport(htmlElement, ElementSides.Top)) { 61 | htmlElement.scrollIntoView(true); 62 | } 63 | } 64 | } 65 | 66 | public hideTourStep(): void { 67 | this.isActive = false; 68 | this.popoverDirective.hide(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/lib/tour-step-template.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AfterContentInit, 3 | Component, 4 | ContentChild, 5 | Input, 6 | TemplateRef, 7 | ViewChild, 8 | ViewEncapsulation 9 | } from '@angular/core'; 10 | import { IStepOption, TourHotkeyListenerComponent } from 'ngx-tour-core'; 11 | 12 | import { NgxbTourService } from './ngx-bootstrap-tour.service'; 13 | import { TourStepTemplateService } from './tour-step-template.service'; 14 | 15 | @Component({ 16 | encapsulation: ViewEncapsulation.None, 17 | selector: 'tour-step-template', 18 | template: ` 19 | 20 |

21 |
22 | 29 | 36 | 39 |
40 |
41 | ` 42 | }) 43 | export class TourStepTemplateComponent extends TourHotkeyListenerComponent 44 | implements AfterContentInit { 45 | @ViewChild('tourStep', { read: TemplateRef, static: true }) 46 | public defaultTourStepTemplate: TemplateRef; 47 | 48 | @Input() 49 | public stepTemplate: TemplateRef<{ step: IStepOption }>; 50 | 51 | @ContentChild(TemplateRef) 52 | public stepTemplateContent: TemplateRef<{ step: IStepOption }>; 53 | 54 | constructor( 55 | private tourStepTemplateService: TourStepTemplateService, 56 | public tourService: NgxbTourService 57 | ) { 58 | super(tourService); 59 | } 60 | 61 | public ngAfterContentInit(): void { 62 | this.tourStepTemplateService.template = 63 | this.stepTemplate || 64 | this.stepTemplateContent || 65 | this.defaultTourStepTemplate; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/lib/tour-step-template.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, TemplateRef } from '@angular/core'; 2 | 3 | @Injectable() 4 | export class TourStepTemplateService { 5 | public template: TemplateRef<{content: string}>; 6 | } 7 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-tour-ngx-bootstrap 3 | */ 4 | 5 | export { INgxbStepOption as IStepOption } from './lib/step-option.interface'; 6 | export { 7 | NgxbTourService as TourService 8 | } from './lib/ngx-bootstrap-tour.service'; 9 | export * from './lib/ngx-bootstrap.module'; 10 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/zone-testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { 8 | BrowserDynamicTestingModule, 9 | platformBrowserDynamicTesting 10 | } from '@angular/platform-browser-dynamic/testing'; 11 | 12 | declare const require: any; 13 | 14 | // First, initialize the Angular testing environment. 15 | getTestBed().initTestEnvironment( 16 | BrowserDynamicTestingModule, 17 | platformBrowserDynamicTesting() 18 | ); 19 | // Then we find all the tests. 20 | const context = require.context('./', true, /\.spec\.ts$/); 21 | // And load the modules. 22 | context.keys().map(context); 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2015" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "flatModuleId": "AUTOGENERATED", 24 | "flatModuleOutFile": "AUTOGENERATED" 25 | }, 26 | "exclude": [ 27 | "src/test.ts", 28 | "**/*.spec.ts" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "enableIvy": false 5 | } 6 | } -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-bootstrap/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": false, 5 | "component-selector": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # [4.2.0](https://github.com/isaacplmann/ngx-tour) (2020-08-17) 4 | 5 | ### Features 6 | 7 | - Replaced `withinviewport()` function from 3rd party library with our own custom `isInViewport()` function to fix 8 | CommonJS warning in Angular 10, reduce bundle size and to remove non-peer dependency 9 | 10 | 11 | 12 | # [4.1.1](https://github.com/isaacplmann/ngx-tour) (2019-12-07) 13 | 14 | ### Fixes 15 | 16 | - Skip undefined tourAnchors 17 | 18 | 19 | 20 | # [4.1.0](https://github.com/isaacplmann/ngx-tour) (2019-10-23) 21 | 22 | ### Features 23 | 24 | - Support Angular 8 as peer dependency 25 | - Support Ivy renderer 26 | 27 | 28 | 29 | # [4.0.1](https://github.com/isaacplmann/ngx-tour) (2018-12-05) 30 | 31 | ### Fixes 32 | 33 | - NavigationStart only hide currentStep if route is specified eg. routing used 34 | 35 | 36 | 37 | # [4.0.0](https://github.com/isaacplmann/ngx-tour) (2018-11-27) 38 | 39 | ### BREAKING CHANGES 40 | 41 | - Require Angular 7 as peer dependency 42 | 43 | 44 | 45 | # [3.0.2](https://github.com/isaacplmann/ngx-tour) (2018-11-09) 46 | 47 | ### Bug Fixes 48 | 49 | - Respect showDelay setting 50 | 51 | 52 | 53 | # [3.0.1](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 54 | 55 | ### Bug Fixes 56 | 57 | - Include styles.css in the npm package 58 | 59 | 60 | 61 | # [3.0.0](https://github.com/isaacplmann/ngx-tour) (2018-05-17) 62 | 63 | ### BREAKING CHANGES 64 | 65 | - Require Angular 6 as peer dependency 66 | 67 | 68 | 69 | # [2.0.0](https://github.com/isaacplmann/ngx-tour) 70 | 71 | ### BREAKING CHANGES 72 | 73 | ### Features 74 | 75 | 76 | 77 | # [1.0.4](https://github.com/isaacplmann/ngx-tour) (2017-10-23) 78 | 79 | ### BREAKING CHANGES 80 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Isaac Mann 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/README.md: -------------------------------------------------------------------------------- 1 | # Ngx-Tour Ngx-Popper 2 | [![Dependency Status](https://david-dm.org/isaacplmann/ngx-tour-ngx-popper.svg)](https://david-dm.org/isaacplmann/ngx-tour-ngx-popper) 3 | [![devDependency Status](https://david-dm.org/isaacplmann/ngx-tour-ngx-popper/dev-status.svg)](https://david-dm.org/isaacplmann/ngx-tour-ngx-popper?type=dev) 4 | 5 | Check out the [documentation/demo page](https://isaacplmann.github.io/ngx-tour). 6 | 7 | This is a product tour library built with Angular (2+). It's inspired by [angular-ui-tour](http://benmarch.github.io/angular-ui-tour). 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../coverage'), 20 | reports: ['html', 'lcovonly'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-ngx-popper", 4 | "deleteDestPath": false, 5 | "lib": { 6 | "entryFile": "src/public_api.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-tour-ngx-popper", 4 | "lib": { 5 | "entryFile": "src/public_api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-tour-ngx-popper", 3 | "version": "4.2.0", 4 | "repository": "https://github.com/isaacplmann/ngx-tour.git", 5 | "author": "Damien Murphy", 6 | "license": "MIT", 7 | "peerDependencies": { 8 | "@angular/common": ">=7.0.0 <9.0.0", 9 | "@angular/core": ">=7.0.0 <9.0.0", 10 | "ngx-popper": "^2.0.1", 11 | "ngx-tour-core": "^4.3.0" 12 | }, 13 | "dependencies": { 14 | "tslib": "^2.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/lib/ngx-popper-tour.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { TourService } from 'ngx-tour-core'; 3 | 4 | import { INgxpStepOption } from './step-option.interface'; 5 | 6 | @Injectable() 7 | export class NgxpTourService extends TourService {} 8 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/lib/ngx-popper.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { NgxPopperModule } from 'ngx-popper'; 4 | import {TourService} from 'ngx-tour-core'; 5 | 6 | import { TourAnchorNgxPopperDirective, TourAnchorNgxPopperPopoverDirective } from './tour-anchor.directive'; 7 | import { TourStepTemplateComponent } from './tour-step-template.component'; 8 | import { TourStepTemplateService } from './tour-step-template.service'; 9 | import { NgxpTourService } from './ngx-popper-tour.service'; 10 | 11 | export { TourAnchorNgxPopperDirective, TourAnchorNgxPopperPopoverDirective, TourStepTemplateComponent, NgxpTourService }; 12 | 13 | @NgModule({ 14 | declarations: [TourAnchorNgxPopperDirective, TourAnchorNgxPopperPopoverDirective, TourStepTemplateComponent], 15 | exports: [TourAnchorNgxPopperDirective, TourAnchorNgxPopperPopoverDirective, TourStepTemplateComponent], 16 | imports: [CommonModule, NgxPopperModule.forRoot()], 17 | }) 18 | export class TourNgxPopperModule { 19 | public static forRoot(): ModuleWithProviders { 20 | return { 21 | ngModule: TourNgxPopperModule, 22 | providers: [ 23 | TourStepTemplateService, 24 | TourService, 25 | NgxpTourService, 26 | ], 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/lib/step-option.interface.ts: -------------------------------------------------------------------------------- 1 | import { IStepOption } from 'ngx-tour-core'; 2 | import { Placement, Trigger } from 'ngx-popper'; 3 | 4 | export interface INgxpStepOption extends IStepOption { 5 | placement?: Placement; 6 | popperSettings?: { 7 | boundariesElement?: string; 8 | closeOnClickOutside?: boolean; 9 | disableAnimation?: boolean; 10 | disabled?: boolean; 11 | disableStyle?: boolean; 12 | forceDetection?: boolean; 13 | hideOnClickOutside?: boolean; 14 | hideOnScroll?: boolean; 15 | hideTimeout?: number; 16 | popperModifiers?: any; 17 | popperOnHidden?: any; 18 | popperOnShown?: any; 19 | positionFixed?: boolean; 20 | showDelay?: number; 21 | showOnStart?: boolean; 22 | showTrigger?: Trigger; 23 | targetElement?: HTMLElement; 24 | timeoutAfterShow?: number; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/lib/tour-anchor.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, Host, HostBinding, Input } from '@angular/core'; 2 | import type {OnDestroy, OnInit} from '@angular/core'; 3 | import { PopperController, Placements, Triggers } from 'ngx-popper'; 4 | import {ElementSides, isInViewport, TourAnchorDirective} from 'ngx-tour-core'; 5 | 6 | import { NgxpTourService } from './ngx-popper-tour.service'; 7 | import { TourStepTemplateService } from './tour-step-template.service'; 8 | import { INgxpStepOption as IStepOption } from './step-option.interface'; 9 | 10 | @Directive({ selector: '[tourAnchor]'}) 11 | export class TourAnchorNgxPopperPopoverDirective extends PopperController implements OnInit { 12 | // Overwrite parent ngOnInit to do nothing since the content property isn't set yet. 13 | ngOnInit() {} 14 | 15 | // Call this to initialize the popover once the content has been set 16 | initialize() { 17 | super.ngOnInit(); 18 | } 19 | } 20 | 21 | @Directive({ 22 | selector: '[tourAnchor]', 23 | }) 24 | export class TourAnchorNgxPopperDirective implements OnInit, OnDestroy, TourAnchorDirective { 25 | @Input() public tourAnchor: string; 26 | 27 | @HostBinding('class.touranchor--is-active') 28 | public isActive: boolean; 29 | 30 | constructor(private tourService: NgxpTourService, 31 | private tourStepTemplate: TourStepTemplateService, 32 | private element: ElementRef, 33 | @Host() private popoverDirective: TourAnchorNgxPopperPopoverDirective, 34 | ) { 35 | } 36 | 37 | public ngOnInit(): void { 38 | this.tourService.register(this.tourAnchor, this); 39 | } 40 | 41 | public ngOnDestroy(): void { 42 | this.tourService.unregister(this.tourAnchor); 43 | } 44 | 45 | public showTourStep(step: IStepOption): void { 46 | const htmlElement: HTMLElement = this.element.nativeElement; 47 | 48 | this.isActive = true; 49 | this.tourStepTemplate.templateComponent.step = step; 50 | step.prevBtnTitle = step.prevBtnTitle || 'Prev'; 51 | step.nextBtnTitle = step.nextBtnTitle || 'Next'; 52 | step.endBtnTitle = step.endBtnTitle || 'End'; 53 | 54 | this.popoverDirective.content = this.tourStepTemplate.template; 55 | this.popoverDirective.targetElement = htmlElement; 56 | this.popoverDirective.placement = step.placement || Placements.Auto; 57 | this.popoverDirective.showTrigger = Triggers.NONE; 58 | 59 | if (step.popperSettings) { 60 | this.popoverDirective.boundariesElement = step.popperSettings.boundariesElement || undefined; 61 | this.popoverDirective.closeOnClickOutside = step.popperSettings.closeOnClickOutside || false; 62 | this.popoverDirective.disableAnimation = step.popperSettings.disableAnimation || false; 63 | this.popoverDirective.disabled = step.popperSettings.disabled || false; 64 | this.popoverDirective.disableStyle = step.popperSettings.disableStyle || false; 65 | this.popoverDirective.hideOnClickOutside = step.popperSettings.hideOnClickOutside || false; 66 | this.popoverDirective.hideOnScroll = step.popperSettings.hideOnScroll || false; 67 | this.popoverDirective.hideTimeout = step.popperSettings.hideTimeout || 0; 68 | this.popoverDirective.positionFixed = step.popperSettings.positionFixed || false; 69 | this.popoverDirective.showDelay = step.popperSettings.showDelay || 0; 70 | this.popoverDirective.showOnStart = step.popperSettings.showOnStart || false; 71 | this.popoverDirective.showTrigger = step.popperSettings.showTrigger || Triggers.NONE; 72 | this.popoverDirective.timeoutAfterShow = step.popperSettings.timeoutAfterShow || 0; 73 | 74 | // TODO: Can these even get passed in via json? 75 | // this.popoverDirective.popperModifiers = step.popperSettings.popperModifiers || undefined; 76 | // this.popoverDirective.popperOnHidden = step.popperSettings.popperOnHidden || undefined; 77 | // this.popoverDirective.popperOnShown = step.popperSettings.popperOnShown || undefined; 78 | } 79 | 80 | this.popoverDirective.initialize(); 81 | if (step.hasOwnProperty('popperSettings') && step.popperSettings.hasOwnProperty('showDelay')) { 82 | this.popoverDirective.scheduledShow(); 83 | } else { 84 | this.popoverDirective.show(); 85 | } 86 | 87 | if (!step.preventScrolling) { 88 | if (!isInViewport(htmlElement, ElementSides.Bottom)) { 89 | htmlElement.scrollIntoView(false); 90 | } else if (!isInViewport(htmlElement, ElementSides.Top)) { 91 | htmlElement.scrollIntoView(true); 92 | } 93 | } 94 | } 95 | 96 | public hideTourStep(): void { 97 | this.isActive = false; 98 | this.popoverDirective.hide(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/lib/tour-step-template.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AfterViewInit, 3 | AfterContentInit, 4 | Component, 5 | ContentChild, 6 | Input, 7 | ViewChild, 8 | ViewEncapsulation, 9 | TemplateRef 10 | } from '@angular/core'; 11 | import { IStepOption, TourHotkeyListenerComponent } from 'ngx-tour-core'; 12 | import { PopperContent } from 'ngx-popper'; 13 | import { NgxpTourService } from './ngx-popper-tour.service'; 14 | import { TourStepTemplateService } from './tour-step-template.service'; 15 | 16 | @Component({ 17 | encapsulation: ViewEncapsulation.None, 18 | selector: 'tour-step-template', 19 | template: ` 20 | 21 | 27 | 28 | 29 | 30 |

{{ step?.title }}

31 |

32 |
33 | 40 | 47 | 50 |
51 |
52 | ` 53 | }) 54 | export class TourStepTemplateComponent extends TourHotkeyListenerComponent 55 | implements AfterViewInit, AfterContentInit { 56 | @ViewChild(PopperContent, { static: true }) 57 | public popperContent: PopperContent; 58 | 59 | @Input() 60 | public stepTemplate: TemplateRef<{ step: IStepOption }>; 61 | 62 | @ContentChild(TemplateRef) 63 | public stepTemplateContent: TemplateRef<{ step: IStepOption }>; 64 | 65 | public step: IStepOption = {}; 66 | 67 | constructor( 68 | private tourStepTemplateService: TourStepTemplateService, 69 | public tourService: NgxpTourService 70 | ) { 71 | super(tourService); 72 | } 73 | 74 | public ngAfterViewInit(): void { 75 | this.tourStepTemplateService.templateComponent = this; 76 | } 77 | 78 | public ngAfterContentInit(): void { 79 | this.tourStepTemplateService.template = this.popperContent; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/lib/tour-step-template.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { PopperContent } from 'ngx-popper'; 3 | import { TourStepTemplateComponent } from './tour-step-template.component'; 4 | 5 | @Injectable() 6 | export class TourStepTemplateService { 7 | public template: PopperContent; 8 | public templateComponent: TourStepTemplateComponent; 9 | } 10 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/public_api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-tour-ngx-popper 3 | */ 4 | 5 | export { INgxpStepOption as IStepOption } from './lib/step-option.interface'; 6 | export { NgxpTourService as TourService } from './lib/ngx-popper-tour.service'; 7 | export { 8 | TourNgxPopperModule, 9 | TourAnchorNgxPopperDirective, 10 | TourStepTemplateComponent 11 | } from './lib/ngx-popper.module'; 12 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/styles.css: -------------------------------------------------------------------------------- 1 | /* ngx-popper internal classes */ 2 | .ngxp__container { 3 | width: 240px; 4 | background: #FFF; 5 | color: black; 6 | text-align: center; 7 | padding: 10px !important; 8 | border: none !important; 9 | box-shadow: 0 0 2px rgba(0,0,0,0.2) !important; 10 | } 11 | 12 | .ngxp__container[x-placement^="top"] .ngxp__arrow { 13 | border-color: rgba(0,0,0,0.2) transparent transparent transparent!important; 14 | } 15 | 16 | .ngxp__container[x-placement^="bottom"] .ngxp__arrow { 17 | border-color: transparent transparent rgba(0,0,0,0.2) transparent!important; 18 | } 19 | 20 | .ngxp__container[x-placement^="right"] .ngxp__arrow { 21 | border-color: transparent rgba(0,0,0,0.2) transparent transparent!important; 22 | } 23 | 24 | .ngxp__container[x-placement^="left"] .ngxp__arrow { 25 | border-color: transparent transparent transparent rgba(0,0,0,0.2)!important; 26 | } 27 | 28 | /* ngxp-popper template classes */ 29 | .ngxp-title{ 30 | font-size: 18px; 31 | font-weight: bold; 32 | } 33 | 34 | .ngxp-content{ 35 | font-size: 14px; 36 | font-weight: normal; 37 | } 38 | 39 | .ngxp-btn{ 40 | border: none; 41 | background: none; 42 | } -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'core-js/es7/reflect'; 4 | import 'zone.js/dist/zone'; 5 | import 'zone.js/dist/zone-testing'; 6 | import { getTestBed } from '@angular/core/testing'; 7 | import { 8 | BrowserDynamicTestingModule, 9 | platformBrowserDynamicTesting 10 | } from '@angular/platform-browser-dynamic/testing'; 11 | 12 | declare const require: any; 13 | 14 | // First, initialize the Angular testing environment. 15 | getTestBed().initTestEnvironment( 16 | BrowserDynamicTestingModule, 17 | platformBrowserDynamicTesting() 18 | ); 19 | // Then we find all the tests. 20 | const context = require.context('./', true, /\.spec\.ts$/); 21 | // And load the modules. 22 | context.keys().map(context); 23 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "node", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2015" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true, 25 | "flatModuleId": "AUTOGENERATED", 26 | "flatModuleOutFile": "AUTOGENERATED" 27 | }, 28 | "exclude": [ 29 | "src/test.ts", 30 | "**/*.spec.ts" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "enableIvy": false 5 | } 6 | } -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngx-tour-ngx-popper/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": false, 5 | "component-selector": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Ngx Tour 2 | 3 | ## NOTICE: This project is no longer being maintained. :warning: 4 | 5 | Ngx Tour is no longer being maintained. [Ngx UI Tour](https://github.com/hakimio/ngx-ui-tour) is the replacement. 6 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 4 | import { RouterModule } from '@angular/router'; 5 | 6 | import { DemoComponent } from './demo.component'; 7 | import { OverlayModule } from '@angular/cdk/overlay'; 8 | 9 | @NgModule({ 10 | bootstrap: [DemoComponent], 11 | declarations: [DemoComponent], 12 | imports: [ 13 | BrowserAnimationsModule, 14 | BrowserModule, 15 | OverlayModule, 16 | RouterModule.forRoot([{ 17 | loadChildren: () => import('./md-menu/mat-lazy-tour/app.module').then(m => m.AppModule), 18 | path: 'mat-lazy-tour', 19 | }, { 20 | loadChildren: () => import('./ng-bootstrap/ng-bootstrap.module').then(m => m.NgBootstrapModule), 21 | path: 'ng-bootstrap', 22 | }, { 23 | loadChildren: () => import('./ngx-bootstrap/ngx-bootstrap.module').then(m => m.NgxBootstrapModule), 24 | path: 'ngx-bootstrap', 25 | }, { 26 | loadChildren: () => import('./console/console.module').then(m => m.ConsoleModule), 27 | path: 'console', 28 | }, { 29 | loadChildren: () => import('./md-menu/md-menu.module').then(m => m.MdMenuModule), 30 | path: '', 31 | }, { 32 | redirectTo: '', 33 | path: '**', 34 | }]), 35 | ], 36 | }) 37 | export class DemoModule { } 38 | -------------------------------------------------------------------------------- /src/app/console/console.component.html: -------------------------------------------------------------------------------- 1 | View on GitHub 2 | Start Demo Tour 3 | Prev 4 | Next 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/console/console.component.ts: -------------------------------------------------------------------------------- 1 | import { TourService } from 'ngx-tour-console'; 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | // tslint:disable-next-line:component-selector 6 | selector: 'console-route', 7 | templateUrl: './console.component.html', 8 | }) 9 | export class ConsoleComponent { 10 | constructor(public tourService: TourService) { 11 | this.tourService.initialize([{ 12 | anchorId: 'start.tour', 13 | content: 'Welcome to the Ngx-Tour tour!', 14 | placement: 'below', 15 | title: 'Welcome', 16 | }, { 17 | anchorId: 'angular-ui-tour', 18 | content: 'Thanks to angular-ui-tour for the inspiration for the library', 19 | title: 'angular-ui-tour', 20 | }, { 21 | anchorId: 'installation', 22 | content: 'First, install the library...', 23 | title: 'Installation', 24 | }, { 25 | anchorId: 'usage', 26 | content: '...then use it.', 27 | title: 'Usage', 28 | }, { 29 | anchorId: 'tourService.start', 30 | content: 'Don\'t forget to actually start the tour.', 31 | title: 'Start the tour', 32 | }, { 33 | anchorId: 'config.anchorId', 34 | content: 'Every step needs an anchor.', 35 | title: 'Anchor', 36 | }, { 37 | anchorId: 'config.route', 38 | content: 'Tours can span multiple routes.', 39 | title: 'Route', 40 | }, { 41 | anchorId: 'another.route', 42 | content: 'Like this!', 43 | route: 'console/other', 44 | title: 'Another Route', 45 | }, { 46 | anchorId: 'config.route', 47 | content: 'And then back again.', 48 | placement: 'below', 49 | title: 'Route Return', 50 | }, { 51 | anchorId: 'config.placement.default', 52 | content: 'Steps can be positioned around an anchor. You can even have multiple steps use the same anchor.', 53 | title: 'Placement', 54 | }, { 55 | anchorId: 'config.placement.default', 56 | content: 'Sliiide to the left.', 57 | placement: 'left', 58 | title: 'Placement', 59 | }, { 60 | anchorId: 'config.placement.default', 61 | content: 'Sliiide to the right.', 62 | placement: 'right', 63 | title: 'Placement', 64 | }, { 65 | anchorId: 'config.placement.default', 66 | content: 'Take it back now y\'all. One hop this time.', 67 | placement: 'below', 68 | title: 'Placement', 69 | }, { 70 | anchorId: 'hotkeys', 71 | content: 'Try using the hotkeys to navigate through the tour.', 72 | title: 'Hotkeys', 73 | }, { 74 | anchorId: 'events', 75 | content: 'You can subscribe to events', 76 | title: 'Events', 77 | }], { 78 | route: 'console', 79 | }); 80 | this.tourService.start(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/app/console/console.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | import { TourConsoleModule } from 'ngx-tour-console'; 5 | 6 | import { ConsoleComponent } from './console.component'; 7 | import { DocsComponent } from './docs.component'; 8 | import { OtherRouteComponent } from './other-route.component'; 9 | 10 | @NgModule({ 11 | declarations: [ConsoleComponent, DocsComponent, OtherRouteComponent], 12 | imports: [ 13 | CommonModule, 14 | RouterModule.forChild([{ 15 | component: ConsoleComponent, 16 | path: '', 17 | children: [{ 18 | component: DocsComponent, 19 | path: '', 20 | }, { 21 | component: OtherRouteComponent, 22 | path: 'other', 23 | }] 24 | }]), 25 | TourConsoleModule.forRoot(), 26 | ], 27 | }) 28 | export class ConsoleModule { } 29 | -------------------------------------------------------------------------------- /src/app/console/docs.component.html: -------------------------------------------------------------------------------- 1 |

About

2 |

This is a product tour library built with Angular (2+). It's inspired by 3 | angular-ui-tour.

4 |

5 | TourConsoleModule is a minimal implementation of the tour ui that uses only the browser's console to display tour steps.

6 | 7 |

Installation

8 |
    9 |
  1. 10 | npm install ngx-tour-core ngx-tour-console 11 |
  2. 12 |
  3. import 13 | TourConsoleModule.forRoot() into your app module
  4. 14 |
15 | 16 |

Usage

17 |
    18 |
  1. 19 | Define anchor points for the tour steps by adding the 20 | tourAnchor directive throughout your app. 21 |
    <div tourAnchor="some.anchor.id">...</div>
    22 |
  2. 23 |
  3. 24 | Define your tour steps using 25 | tourService.initialize(steps) 26 |
     27 | this.tourService.initialize([{{ '{' }}
     28 |   anchorId: 'some.anchor.id',
     29 |   content: 'Some content',
     30 |   title: 'First',
     31 | }, {{ '{' }}
     32 |   anchorId: 'another.anchor.id',
     33 |   content: 'Other content',
     34 |   title: 'Second',
     35 | }]);
    36 |
  4. 37 |
  5. Start the tour with 38 | tourService.start() 39 |
  6. 40 |
  7. Check out the 41 | demo source code for an example.
  8. 42 |
43 | 44 |

TourService

45 |

The 46 | TourService controls the tour. Some key functions include:

47 |
48 |
start()
49 |
Starts the tour
50 |
startAt(stepId: number | string)
51 |
Start the tour at the step with stepId or at the specified index
52 |
end()
53 |
Ends the tour
54 |
pause()
55 |
Pauses the tour
56 |
resume()
57 |
Resumes the tour
58 |
next()
59 |
Goes to the next step
60 |
prev()
61 |
Goes to the previous step
62 |
63 | 64 |

Step Configuration

65 |

Each step can have the following properties.

66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 126 | 132 | 133 | 134 | 135 | 136 | 137 | 141 | 142 | 143 |
NameTypeDefaultDescription
stepIdstring""A unique identifier for the step
anchorIdstringrequiredThe anchor to which the step will be attached
titlestring""The title of the tour step
contentstring""The content text of the tour step
routestring | UrlSegment[]undefined 105 | The route to which the tour should navigate before attempting to show this tour step. If undefined, no navigation is attempted. 106 |
nextStepnumber | stringundefinedThe step index or stepId of the next step. If undefined, the next step in the steps array is used.
prevStepnumber | stringundefinedThe step index or stepId of the previous step. If undefined, the previous step in the steps array is used.
placement'above' | 'below' | 'after' | 'before' | 'left' | 'right' 124 | 'top' 125 | 127 | (* Ignored by 128 | TourMdMenuModule) Where the tour step should placed with respect to the anchor. 'before' and 'after' are synonyms for 'left' and 129 | 'right' respectively. When RTL support is implemented, 'before' and 'after' will swap directions when RTL mode is 130 | enabled. 131 |
preventScrollingbooleanfalse 138 | Tour steps automatically scroll to the middle of the screen, if they are off the screen when shown. Setting this value to 139 | true will disable the scroll behavior. 140 |
144 | 145 |

Defaults

146 |

You can set default values in the 147 | TourService.initialize function.

148 |
149 | this.tourService.initialize(steps, {{ '{' }}
150 |   route: '',
151 |   placement: 'left',
152 |   preventScrolling: true,
153 | });
154 | 
155 |

Any value explicitly defined in a step will override the default value.

156 | 157 |

Hotkeys

158 |

159 | Hotkeys are provided using Angular's 160 | @HostListener decorator. Hotkeys are enabled when the tour starts and disabled when the tour ends. 161 |

162 |
    163 |
  • 164 | left arrow 165 | - previous step 166 |
  • 167 |
  • 168 | right arrow 169 | - next step 170 |
  • 171 |
  • 172 | esc 173 | - end tour 174 |
  • 175 |
176 |

177 | You can disable hotkeys by calling 178 | tourService.disableHotkeys() or re-enable with 179 | tourService.enableHotkeys() 180 |

181 | 182 |

Event Observables

183 |

The 184 | TourService emits events that can be subscribed to like this:

185 |
186 | this.tourService.initialize$.subscribe((steps: IStepOption[]) => {{ '{' }}
187 |   console.log('tour configured with these steps:', steps);
188 | });
189 | 
190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 |
NamePayloadEmitted When
stepShow$IStepOptionA step is shown
stepHide$IStepOptionA step is hidden
initialize$IStepOption[]The tour is configured with a set of steps
start$IStepOptionThe tour begins
end$anyThe tour ends
pause$IStepOptionThe tour is paused
resume$IStepOptionThe tour resumes
anchorRegister$stringAn anchor is registered with the tour
anchorUnregister$stringAn anchor is unregistered from the tour
-------------------------------------------------------------------------------- /src/app/console/docs.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'docs', 6 | templateUrl: './docs.component.html', 7 | }) 8 | export class DocsComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/console/other-route.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'other-route', 6 | template: `

This is the another route

`, 7 | }) 8 | export class OtherRouteComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/demo.component.html: -------------------------------------------------------------------------------- 1 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/app/demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './demo.component.html', 6 | }) 7 | export class DemoComponent { 8 | } 9 | -------------------------------------------------------------------------------- /src/app/md-menu/docs.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'docs', 6 | templateUrl: './docs.component.html', 7 | }) 8 | export class DocsComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { HomeComponent } from './components/home/home.component'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | redirectTo: 'module-app-home', 10 | pathMatch: 'full' 11 | }, 12 | { 13 | path: 'module-app-home', 14 | component: HomeComponent 15 | }, 16 | { 17 | path: 'module-a', 18 | loadChildren: () => import('./modules/module-a/module-a.module').then(m => m.ModuleAModule) 19 | }, 20 | { 21 | path: 'module-b', 22 | loadChildren: () => import('./modules/module-b/module-b.module').then(m => m.ModuleBModule) 23 | } 24 | ]; 25 | 26 | @NgModule({ 27 | imports: [RouterModule.forRoot(routes)], 28 | exports: [RouterModule] 29 | }) 30 | export class AppRoutingModule { } 31 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isaacplmann/ngx-tour/0eb37de8b0644fe15ed2b206f5c815b981bf89df/src/app/md-menu/mat-lazy-tour/app.component.css -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | HOME 3 | 4 | 5 | MODULE A 6 | 7 | 8 | MODULE B 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | describe('AppComponent', () => { 5 | beforeEach(async(() => { 6 | TestBed.configureTestingModule({ 7 | imports: [ 8 | RouterTestingModule 9 | ], 10 | declarations: [ 11 | AppComponent 12 | ], 13 | }).compileComponents(); 14 | })); 15 | it('should create the app', async(() => { 16 | const fixture = TestBed.createComponent(AppComponent); 17 | const app = fixture.debugElement.componentInstance; 18 | expect(app).toBeTruthy(); 19 | })); 20 | it(`should have as title 'app'`, async(() => { 21 | const fixture = TestBed.createComponent(AppComponent); 22 | const app = fixture.debugElement.componentInstance; 23 | expect(app.title).toEqual('app'); 24 | })); 25 | it('should render title in a h1 tag', async(() => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.debugElement.nativeElement; 29 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); 30 | })); 31 | }); 32 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 4 | 5 | import { AppRoutingModule } from './app-routing.module'; 6 | 7 | import { AppComponent } from './app.component'; 8 | import { HomeComponent } from './components/home/home.component'; 9 | 10 | import { TourMatMenuModule } from 'ngx-tour-md-menu'; 11 | 12 | 13 | @NgModule({ 14 | declarations: [ 15 | AppComponent, 16 | HomeComponent 17 | ], 18 | imports: [ 19 | BrowserModule, 20 | AppRoutingModule, 21 | BrowserAnimationsModule, 22 | TourMatMenuModule.forRoot() 23 | ], 24 | providers: [], 25 | bootstrap: [AppComponent] 26 | }) 27 | export class AppModule { } 28 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/components/home/home.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isaacplmann/ngx-tour/0eb37de8b0644fe15ed2b206f5c815b981bf89df/src/app/md-menu/mat-lazy-tour/components/home/home.component.css -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/components/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | home works! 4 |

-------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/components/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { HomeComponent } from './home.component'; 4 | 5 | describe('HomeComponent', () => { 6 | let component: HomeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ HomeComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(HomeComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/components/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { TourService } from 'ngx-tour-md-menu'; 3 | 4 | @Component({ 5 | selector: 'app-home', 6 | templateUrl: './home.component.html', 7 | styleUrls: ['./home.component.css'] 8 | }) 9 | export class HomeComponent implements OnInit { 10 | 11 | constructor(private tourService: TourService) { } 12 | 13 | ngOnInit() { 14 | this.tourService.initialize( 15 | [ 16 | { 17 | anchorId: 'app-home', 18 | content: 'This is a step from the eager loaded app module in the home component', 19 | title: 'Home Component', 20 | route: '' 21 | }, 22 | { 23 | anchorId: 'module-a', 24 | content: 'This is a step from the lazy loaded module-a module in the module-a component', 25 | title: 'Module-a Component', 26 | route: 'module-a' 27 | }, 28 | { 29 | anchorId: 'module-b', 30 | content: 'This is a step from the lazy loaded module-b module in the module-b component', 31 | title: 'Module-b Component', 32 | route: 'module-b' 33 | } 34 | ] 35 | ); 36 | 37 | this.tourService.start(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-a/module-a-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { ModuleAComponent } from './module-a.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | redirectTo: 'module-a-component', 9 | pathMatch: 'full' 10 | }, 11 | { 12 | path: 'module-a-component', 13 | component: ModuleAComponent 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule] 20 | }) 21 | export class ModuleARoutingModule { } 22 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-a/module-a.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isaacplmann/ngx-tour/0eb37de8b0644fe15ed2b206f5c815b981bf89df/src/app/md-menu/mat-lazy-tour/modules/module-a/module-a.component.css -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-a/module-a.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | module-a works! 4 |

5 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-a/module-a.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ModuleAComponent } from './module-a.component'; 4 | 5 | describe('ModuleAComponent', () => { 6 | let component: ModuleAComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ModuleAComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ModuleAComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-a/module-a.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-module-a', 5 | templateUrl: './module-a.component.html', 6 | styleUrls: ['./module-a.component.css'] 7 | }) 8 | export class ModuleAComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-a/module-a.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { ModuleARoutingModule } from './module-a-routing.module'; 5 | import { ModuleAComponent } from './module-a.component'; 6 | 7 | import { TourMatMenuModule } from 'ngx-tour-md-menu'; 8 | 9 | @NgModule({ 10 | imports: [ 11 | CommonModule, 12 | ModuleARoutingModule, 13 | TourMatMenuModule 14 | ], 15 | declarations: [ModuleAComponent] 16 | }) 17 | export class ModuleAModule { } 18 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-b/module-b-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { ModuleBComponent } from './module-b.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | redirectTo: 'module-b-component', 9 | pathMatch: 'full' 10 | }, 11 | { 12 | path: 'module-b-component', 13 | component: ModuleBComponent 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forChild(routes)], 19 | exports: [RouterModule] 20 | }) 21 | export class ModuleBRoutingModule { } 22 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-b/module-b.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isaacplmann/ngx-tour/0eb37de8b0644fe15ed2b206f5c815b981bf89df/src/app/md-menu/mat-lazy-tour/modules/module-b/module-b.component.css -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-b/module-b.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | module-b works! 4 |

5 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-b/module-b.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ModuleBComponent } from './module-b.component'; 4 | 5 | describe('ModuleBComponent', () => { 6 | let component: ModuleBComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ ModuleBComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ModuleBComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-b/module-b.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-module-b', 5 | templateUrl: './module-b.component.html', 6 | styleUrls: ['./module-b.component.css'] 7 | }) 8 | export class ModuleBComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/md-menu/mat-lazy-tour/modules/module-b/module-b.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { ModuleBRoutingModule } from './module-b-routing.module'; 5 | import { ModuleBComponent } from './module-b.component'; 6 | 7 | import { TourMatMenuModule } from 'ngx-tour-md-menu'; 8 | 9 | @NgModule({ 10 | imports: [ 11 | CommonModule, 12 | ModuleBRoutingModule, 13 | TourMatMenuModule 14 | ], 15 | declarations: [ModuleBComponent] 16 | }) 17 | export class ModuleBModule { } 18 | -------------------------------------------------------------------------------- /src/app/md-menu/md-menu.component.html: -------------------------------------------------------------------------------- 1 | View on GitHub 4 | Start Demo Tour 11 | 12 | 13 | 14 | 15 | {{ step | json }} 16 | 17 | -------------------------------------------------------------------------------- /src/app/md-menu/md-menu.component.ts: -------------------------------------------------------------------------------- 1 | import { TourService } from 'ngx-tour-md-menu'; 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | // tslint:disable-next-line:component-selector 6 | selector: 'md-menu-route', 7 | templateUrl: './md-menu.component.html', 8 | }) 9 | export class MdMenuComponent { 10 | constructor(public tourService: TourService) { 11 | this.tourService.initialize([{ 12 | anchorId: 'start.tour', 13 | content: 'Welcome to the Ngx-Tour tour!', 14 | placement: 'below', 15 | title: 'Welcome', 16 | }, { 17 | anchorId: 'angular-ui-tour', 18 | content: 'Thanks to angular-ui-tour for the inspiration for the library', 19 | route: '', 20 | title: 'angular-ui-tour', 21 | }, { 22 | anchorId: 'installation', 23 | content: 'First, install the library...', 24 | title: 'Installation', 25 | }, { 26 | anchorId: 'usage', 27 | content: '...then use it.', 28 | title: 'Usage', 29 | }, { 30 | anchorId: 'tourService.start', 31 | content: 'Don\'t forget to actually start the tour.', 32 | title: 'Start the tour', 33 | }, { 34 | anchorId: 'config.anchorId', 35 | content: 'Every step needs an anchor.', 36 | title: 'Anchor', 37 | }, { 38 | anchorId: 'config.enableBackdrop', 39 | content: 'You can enable backdrop to highlight active element.', 40 | title: 'Backdrop', 41 | enableBackdrop: true 42 | }, { 43 | anchorId: 'config.route', 44 | content: 'Tours can span multiple routes.', 45 | title: 'Route', 46 | }, { 47 | anchorId: 'another.route', 48 | content: 'Like this!', 49 | route: 'other', 50 | title: 'Another Route', 51 | }, { 52 | anchorId: 'config.route', 53 | content: 'And then back again.', 54 | placement: 'below', 55 | title: 'Route Return', 56 | }, { 57 | anchorId: 'config.buttons.custom', 58 | content: 'You can set custom step button names', 59 | title: 'Button Titles', 60 | prevBtnTitle: 'My Prev', 61 | nextBtnTitle: 'My Next', 62 | endBtnTitle: 'My End' 63 | }, { 64 | anchorId: 'hotkeys', 65 | content: 'Try using the hotkeys to navigate through the tour.', 66 | title: 'Hotkeys', 67 | }, { 68 | anchorId: 'events', 69 | content: 'You can subscribe to events', 70 | title: 'Events', 71 | }], { 72 | route: 'md-menu', 73 | }); 74 | this.tourService.start(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/app/md-menu/md-menu.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | import { TourMatMenuModule } from 'ngx-tour-md-menu'; 5 | 6 | import { DocsComponent } from './docs.component'; 7 | import { MdMenuComponent } from './md-menu.component'; 8 | import { OtherRouteComponent } from './other-route.component'; 9 | 10 | @NgModule({ 11 | declarations: [MdMenuComponent, DocsComponent, OtherRouteComponent], 12 | imports: [ 13 | CommonModule, 14 | TourMatMenuModule.forRoot(), 15 | RouterModule.forChild([{ 16 | component: MdMenuComponent, 17 | path: '', 18 | children: [{ 19 | component: DocsComponent, 20 | path: '', 21 | }, { 22 | component: OtherRouteComponent, 23 | path: 'other', 24 | }] 25 | }]), 26 | ], 27 | }) 28 | export class MdMenuModule { } 29 | -------------------------------------------------------------------------------- /src/app/md-menu/other-route.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'other-route', 6 | template: `

This is the another route

`, 7 | }) 8 | export class OtherRouteComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/ng-bootstrap/docs.component.html: -------------------------------------------------------------------------------- 1 |

About

2 |

This is a product tour library built with Angular (2+). It's inspired by 3 | angular-ui-tour.

4 |

5 | TourNgBootstrapModule is an implementation of the tour ui that uses 6 | NgBootstrap popovers to display tour steps.

7 | 8 |

Installation

9 |
    10 |
  1. 11 | npm install ngx-tour-core ngx-tour-ng-bootstrap @ng-bootstrap/ng-bootstrap 12 |
  2. 13 |
  3. Import 14 | TourNgBootstrapModule.forRoot() into your app module
  4. 15 |
  5. Make sure 16 | RouterModule is imported in your app module
  6. 17 |
  7. Include bootstrap css somehow - i.e. in your 18 | index.html add this line: 19 |
    20 | <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous"> 21 |
  8. 22 |
23 | 24 |

Usage

25 |
    26 |
  1. Add 27 | <tour-step-template></tour-step-template> to your root app component
  2. 28 |
  3. 29 | Define anchor points for the tour steps by adding the 30 | tourAnchor directive throughout your app. 31 |
    <div tourAnchor="some.anchor.id">...</div>
    32 |
  4. 33 |
  5. 34 | Define your tour steps using 35 | tourService.initialize(steps) 36 |
     37 | this.tourService.initialize([{{ '{' }}
     38 |   anchorId: 'some.anchor.id',
     39 |   content: 'Some content',
     40 |   title: 'First',
     41 | }, {{ '{' }}
     42 |   anchorId: 'another.anchor.id',
     43 |   content: 'Other content',
     44 |   title: 'Second',
     45 | }]);
    46 |
  6. 47 |
  7. Start the tour with 48 | tourService.start() 49 |
  8. 50 |
  9. Check out the 51 | demo source code for an example.
  10. 52 |
53 | 54 |

TourService

55 |

The 56 | TourService controls the tour. Some key functions include:

57 |
58 |
start()
59 |
Starts the tour
60 |
startAt(stepId: number | string)
61 |
Start the tour at the step with stepId or at the specified index
62 |
end()
63 |
Ends the tour
64 |
pause()
65 |
Pauses the tour
66 |
resume()
67 |
Resumes the tour
68 |
next()
69 |
Goes to the next step
70 |
prev()
71 |
Goes to the previous step
72 |
73 | 74 |

Step Configuration

75 |

Each step can have the following properties.

76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 134 | 137 | 141 | 142 | 143 | 144 | 145 | 146 | 150 | 151 | 152 | 153 | 154 | 155 | 158 | 159 | 160 | 161 | 162 | 163 | 166 | 167 | 168 | 169 | 170 | 171 | 174 | 175 | 176 |
NameTypeDefaultDescription
stepIdstring""A unique identifier for the step
anchorIdstringrequiredThe anchor to which the step will be attached
titlestring""The title of the tour step
contentstring""The content text of the tour step
routestring | UrlSegment[]undefined 115 | The route to which the tour should navigate before attempting to show this tour step. If undefined, no navigation is attempted. 116 |
nextStepnumber | stringundefinedThe step index or stepId of the next step. If undefined, the next step in the steps array is used.
prevStepnumber | stringundefinedThe step index or stepId of the previous step. If undefined, the previous step in the steps array is used.
placementPlacement of a popover accepts: "top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "left", "left-top", 133 | "left-bottom", "right", "right-top", "right-bottom" and array of above values. 135 | 'top' 136 | 138 | Where the tour step should placed with respect to the anchor. Supports all 139 | placement options of ng bootstrap. 140 |
preventScrollingbooleanfalse 147 | Tour steps automatically scroll to the middle of the screen, if they are off the screen when shown. Setting this value to 148 | true will disable the scroll behavior. 149 |
prevBtnTitlestringfalse 156 | Sets a custom prev button title for a given step. Default is "Prev" 157 |
nextBtnTitlestringfalse 164 | Sets a custom next button title for a given step. Default is "Next" 165 |
endBtnTitlestringfalse 172 | Sets a custom end button title for a given step. Default is "End" 173 |
177 | 178 |

Defaults

179 |

You can set default values in the 180 | TourService.initialize function.

181 |
182 | this.tourService.initialize(steps, {{ '{' }}
183 |   route: '',
184 |   placement: 'left',
185 |   preventScrolling: true,
186 | });
187 | 
188 |

Any value explicitly defined in a step will override the default value.

189 | 190 |

Hotkeys

191 |

192 | Hotkeys are provided using Angular's 193 | @HostListener decorator. Hotkeys are enabled when the tour starts and disabled when the tour ends. 194 |

195 |
    196 |
  • 197 | left arrow 198 | - previous step 199 |
  • 200 |
  • 201 | right arrow 202 | - next step 203 |
  • 204 |
  • 205 | esc 206 | - end tour 207 |
  • 208 |
209 |

210 | You can disable hotkeys by calling 211 | tourService.disableHotkeys() or re-enable with 212 | tourService.enableHotkeys() 213 |

214 | 215 |

Event Observables

216 |

The 217 | TourService emits events that can be subscribed to like this:

218 |
219 | this.tourService.initialize$.subscribe((steps: IStepOption[]) => {{ '{' }}
220 |   console.log('tour configured with these steps:', steps);
221 | });
222 | 
223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 |
NamePayloadEmitted When
stepShow$IStepOptionA step is shown
stepHide$IStepOptionA step is hidden
initialize$IStepOption[]The tour is configured with a set of steps
start$IStepOptionThe tour begins
end$anyThe tour ends
pause$IStepOptionThe tour is paused
resume$IStepOptionThe tour resumes
anchorRegister$stringAn anchor is registered with the tour
anchorUnregister$stringAn anchor is unregistered from the tour
279 | 280 |

Custom template

281 |

282 | You can also customize the tour step template by providing an 283 | <ng-template let-step="step" > inside the 284 | <tour-step-template> 285 |

286 |

287 | The default template is equivalent to this: 288 |

289 |
<tour-step-template>
290 |   <ng-template let-step="step">
291 |     <p class="tour-step-content">{{ '{{' }}step?.content}}</p>
292 |     <div class="tour-step-navigation">
293 |       <button *ngIf="tourService.hasPrev(step)" class="btn btn-sm btn-default" (click)="tourService.prev()">« {{ '{{' }}step?.prevBtnTitle}}</button>
294 |       <button *ngIf="tourService.hasNext(step)" class="btn btn-sm btn-default" (click)="tourService.next()">{{ '{{' }}step?.nextBtnTitle}} »</button>
295 |       <button class="btn btn-sm btn-default" (click)="tourService.end()">{{ '{{' }}step?.endBtnTitle}}</button>
296 |     </div>
297 |   </ng-template>
298 | </tour-step-template>
299 | 
300 | 301 |

Styling Active Tour Anchor

302 |

303 | The currently active tour anchor element has a 304 | touranchor--is-active class applied to it, so you can apply your own custom styles to that class to highlight the element being referenced. 305 |

-------------------------------------------------------------------------------- /src/app/ng-bootstrap/docs.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'docs', 6 | templateUrl: './docs.component.html', 7 | }) 8 | export class DocsComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/ng-bootstrap/ng-bootstrap.component.html: -------------------------------------------------------------------------------- 1 | View on GitHub 2 | Start Demo Tour 3 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /src/app/ng-bootstrap/ng-bootstrap.component.ts: -------------------------------------------------------------------------------- 1 | import { TourService, IStepOption } from 'ngx-tour-ng-bootstrap'; 2 | import { Component } from '@angular/core'; 3 | 4 | @Component({ 5 | // tslint:disable-next-line:component-selector 6 | selector: 'ng-bootstrap-route', 7 | templateUrl: './ng-bootstrap.component.html', 8 | }) 9 | export class NgBootstrapComponent { 10 | constructor(public tourService: TourService) { 11 | this.tourService.events$.subscribe(console.log); 12 | this.tourService.initialize([{ 13 | anchorId: 'start.tour', 14 | content: 'Welcome to the Ngx-Tour tour!', 15 | placement: 'bottom', 16 | title: 'Welcome', 17 | }, { 18 | anchorId: 'angular-ui-tour', 19 | content: 'Thanks to angular-ui-tour for the inspiration for the library', 20 | title: 'angular-ui-tour', 21 | }, { 22 | anchorId: 'installation', 23 | content: 'First, install the library...', 24 | title: 'Installation', 25 | }, { 26 | anchorId: 'usage', 27 | content: '...then use it.', 28 | title: 'Usage', 29 | }, { 30 | anchorId: 'tourService.start', 31 | content: 'Don\'t forget to actually start the tour.', 32 | title: 'Start the tour', 33 | }, { 34 | anchorId: 'config.anchorId', 35 | content: 'Every step needs an anchor.', 36 | title: 'Anchor', 37 | }, { 38 | anchorId: 'config.route', 39 | content: 'Tours can span multiple routes.', 40 | title: 'Route', 41 | }, { 42 | anchorId: 'another.route', 43 | content: 'Like this!', 44 | route: 'ng-bootstrap/other', 45 | title: 'Another Route', 46 | }, { 47 | anchorId: 'config.route', 48 | content: 'And then back again.', 49 | placement: 'bottom', 50 | title: 'Route Return', 51 | }, { 52 | anchorId: 'config.placement.default', 53 | content: 'Steps can be positioned around an anchor. You can even have multiple steps use the same anchor.', 54 | title: 'Placement', 55 | }, { 56 | anchorId: 'config.placement.default', 57 | content: 'Sliiide to the left.', 58 | placement: 'left', 59 | title: 'Placement', 60 | }, { 61 | anchorId: 'config.placement.default', 62 | content: 'Sliiide to the right.', 63 | placement: 'right', 64 | title: 'Placement', 65 | }, { 66 | anchorId: 'config.placement.default', 67 | content: 'Take it back now y\'all. One hop this time.', 68 | placement: 'bottom', 69 | title: 'Placement', 70 | }, { 71 | anchorId: 'config.placement.default', 72 | content: 'And on the corners - left-top', 73 | placement: 'left-top', 74 | title: 'Placement', 75 | }, { 76 | anchorId: 'config.placement.default', 77 | content: 'And on the corners - top-left', 78 | placement: 'top-left', 79 | title: 'Placement', 80 | }, { 81 | anchorId: 'config.placement.default', 82 | content: 'And on the corners - top-right', 83 | placement: 'top-right', 84 | title: 'Placement', 85 | }, { 86 | anchorId: 'config.placement.default', 87 | content: 'And on the corners - right-top', 88 | placement: 'right-top', 89 | title: 'Placement', 90 | }, { 91 | anchorId: 'config.placement.default', 92 | content: 'And on the corners - right-bottom', 93 | placement: 'right-bottom', 94 | title: 'Placement', 95 | }, { 96 | anchorId: 'config.placement.default', 97 | content: 'And on the corners - bottom-right', 98 | placement: 'bottom-right', 99 | title: 'Placement', 100 | }, { 101 | anchorId: 'config.placement.default', 102 | content: 'And on the corners - bottom-left', 103 | placement: 'bottom-left', 104 | title: 'Placement', 105 | }, { 106 | anchorId: 'config.placement.default', 107 | content: 'And on the corners - left-bottom', 108 | placement: 'left-bottom', 109 | title: 'Placement', 110 | }, { 111 | anchorId: 'config.buttons.custom', 112 | content: 'You can set custom step button names', 113 | title: 'Button Titles', 114 | prevBtnTitle: 'My Prev', 115 | nextBtnTitle: 'My Next', 116 | endBtnTitle: 'My End' 117 | }, { 118 | anchorId: 'hotkeys', 119 | content: 'Try using the hotkeys to navigate through the tour.', 120 | title: 'Hotkeys', 121 | }, { 122 | anchorId: 'events', 123 | content: 'You can subscribe to events', 124 | title: 'Events', 125 | }], 126 | { 127 | route: 'ng-bootstrap', 128 | } 129 | ); 130 | this.tourService.start(); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/app/ng-bootstrap/ng-bootstrap.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | import { TourNgBootstrapModule } from 'ngx-tour-ng-bootstrap'; 5 | 6 | import { DocsComponent } from './docs.component'; 7 | import { NgBootstrapComponent } from './ng-bootstrap.component'; 8 | import { OtherRouteComponent } from './other-route.component'; 9 | 10 | @NgModule({ 11 | declarations: [NgBootstrapComponent, DocsComponent, OtherRouteComponent], 12 | imports: [ 13 | CommonModule, 14 | RouterModule.forChild([{ 15 | component: NgBootstrapComponent, 16 | path: '', 17 | children: [{ 18 | component: DocsComponent, 19 | path: '', 20 | }, { 21 | component: OtherRouteComponent, 22 | path: 'other', 23 | }] 24 | }]), 25 | TourNgBootstrapModule.forRoot(), 26 | ], 27 | }) 28 | export class NgBootstrapModule { } 29 | -------------------------------------------------------------------------------- /src/app/ng-bootstrap/other-route.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'other-route', 6 | template: `

This is the another route

`, 7 | }) 8 | export class OtherRouteComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/ngx-bootstrap/docs.component.html: -------------------------------------------------------------------------------- 1 |

About

2 | 3 |

This is a product tour library built with Angular (2+). It's inspired by 4 | angular-ui-tour.

5 | 6 |

7 | TourNgxBootstrapModule is an implementation of the tour UI that uses 8 | NgxBootstrap popovers to display tour steps.

10 | 11 |

Installation

12 |
    13 |
  1. 14 | npm install ngx-tour-core ngx-tour-ngx-bootstrap ngx-bootstrap 15 |
  2. 16 |
  3. Import 17 | TourNgxBootstrapModule.forRoot() into your app module
  4. 18 |
  5. Make sure 19 | RouterModule is imported in your app module
  6. 20 |
  7. Include bootstrap 4 CSS somehow - i.e. in your 21 | index.html add this line: 22 |
    23 | 24 | <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"> 25 | 26 |
  8. 27 |
  9. Or for Bootstrap 3:
  10. 28 |
    29 | 30 | <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 31 | 32 |
33 | 34 |

Usage

35 |
    36 |
  1. Add 37 | <tour-step-template></tour-step-template> to your root app component
  2. 38 |
  3. 39 | Define anchor points for the tour steps by adding the 40 | tourAnchor directive throughout your app. 41 |
    <div tourAnchor="some.anchor.id">...</div>
    42 |
  4. 43 |
  5. 44 | Define your tour steps using 45 | tourService.initialize(steps) 46 |
     47 | this.tourService.initialize([{{ '{' }}
     48 |   anchorId: 'some.anchor.id',
     49 |   content: 'Some content',
     50 |   title: 'First',
     51 | }, {{ '{' }}
     52 |   anchorId: 'another.anchor.id',
     53 |   content: 'Other content',
     54 |   title: 'Second',
     55 | }]);
    56 |
  6. 57 |
  7. Start the tour with 58 | tourService.start() 59 |
  8. 60 |
  9. Check out the 61 | demo source code for an example.
  10. 62 |
63 | 64 |

TourService

65 |

The 66 | TourService controls the tour. Some key functions include:

67 |
68 |
start()
69 |
Starts the tour
70 |
startAt(stepId: number | string)
71 |
Start the tour at the step with stepId or at the specified index
72 |
end()
73 |
Ends the tour
74 |
pause()
75 |
Pauses the tour
76 |
resume()
77 |
Resumes the tour
78 |
next()
79 |
Goes to the next step
80 |
prev()
81 |
Goes to the previous step
82 |
83 | 84 |

Step Configuration

85 |

Each step can have the following properties.

86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 146 | 150 | 151 | 152 | 153 | 154 | 155 | 158 | 159 | 160 | 161 | 162 | 163 | 167 | 168 | 169 | 170 | 171 | 172 | 175 | 176 | 177 | 178 | 179 | 180 | 183 | 184 | 185 | 186 | 187 | 188 | 191 | 192 | 193 |
NameTypeDefaultDescription
stepIdstring""A unique identifier for the step
anchorIdstringrequiredThe anchor to which the step will be attached
titlestring""The title of the tour step
contentstring""The content text of the tour step
routestring | UrlSegment[]undefined 125 | The route to which the tour should navigate before attempting to show this tour step. If undefined, no navigation is attempted. 126 |
nextStepnumber | stringundefinedThe step index or stepId of the next step. If undefined, the next step in the steps array is used.
prevStepnumber | stringundefinedThe step index or stepId of the previous step. If undefined, the previous step in the steps array is used.
placement'top' | 'bottom' | 'left' | 'right' | 'auto' 144 | 'top' 145 | 147 | Placement of a popover. See the 148 | ngx-bootstrap docs. 149 |
containerClassstring"" 156 | Custom CSS class for popover container. It helps when you want to add custom style only for tour step popovers. 157 |
preventScrollingbooleanfalse 164 | Tour steps automatically scroll to the middle of the screen, if they are off the screen when shown. Setting this value to 165 | true will disable the scroll behavior. 166 |
prevBtnTitlestringfalse 173 | Sets a custom prev button title for a given step. Default is "Prev" 174 |
nextBtnTitlestringfalse 181 | Sets a custom next button title for a given step. Default is "Next" 182 |
endBtnTitlestringfalse 189 | Sets a custom end button title for a given step. Default is "End" 190 |
194 | 195 |

Defaults

196 |

You can set default values in the 197 | TourService.initialize function.

198 |
199 | this.tourService.initialize(steps, {{ '{' }}
200 |   route: '',
201 |   placement: 'left',
202 |   preventScrolling: true,
203 | });
204 | 
205 |

Any value explicitly defined in a step will override the default value.

206 | 207 |

Hotkeys

208 |

209 | Hotkeys are provided using Angular's 210 | @HostListener decorator. Hotkeys are enabled when the tour starts and disabled when the tour ends. 211 |

212 |
    213 |
  • 214 | left arrow 215 | - previous step 216 |
  • 217 |
  • 218 | right arrow 219 | - next step 220 |
  • 221 |
  • 222 | esc 223 | - end tour 224 |
  • 225 |
226 |

227 | You can disable hotkeys by calling 228 | tourService.disableHotkeys() or re-enable with 229 | tourService.enableHotkeys() 230 |

231 | 232 |

Event Observables

233 |

The 234 | TourService emits events that can be subscribed to like this:

235 |
236 | this.tourService.initialize$.subscribe((steps: IStepOption[]) => {{ '{' }}
237 |   console.log('tour configured with these steps:', steps);
238 | });
239 | 
240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 |
NamePayloadEmitted When
stepShow$IStepOptionA step is shown
stepHide$IStepOptionA step is hidden
initialize$IStepOption[]The tour is configured with a set of steps
start$IStepOptionThe tour begins
end$anyThe tour ends
pause$IStepOptionThe tour is paused
resume$IStepOptionThe tour resumes
anchorRegister$stringAn anchor is registered with the tour
anchorUnregister$stringAn anchor is unregistered from the tour
296 | 297 |

Custom template

298 |

299 | You can also customize the tour step template by providing an 300 | <ng-template let-step="step" > inside the 301 | <tour-step-template> 302 |

303 |

304 | The default template is equivalent to this: 305 |

306 |
<tour-step-template>
307 |   <ng-template let-step="step">
308 |     <p class="tour-step-content">{{ '{{' }}step?.content}}</p>
309 |     <div class="tour-step-navigation">
310 |       <button *ngIf="tourService.hasPrev(step)" class="btn btn-sm btn-default" (click)="tourService.prev()">« {{ '{{' }}step?.prevBtnTitle}}</button>
311 |       <button *ngIf="tourService.hasNext(step)" class="btn btn-sm btn-default" (click)="tourService.next()">{{ '{{' }}step?.nextBtnTitle}} »</button>
312 |       <button class="btn btn-sm btn-default" (click)="tourService.end()">{{ '{{' }}step?.endBtnTitle}}</button>
313 |     </div>
314 |   </ng-template>
315 | </tour-step-template>
316 | 
317 | 318 |

Styling Active Tour Anchor

319 |

320 | The currently active tour anchor element has a 321 | touranchor--is-active class applied to it, so you can apply your own custom styles to that class to highlight the element being referenced. 322 |

-------------------------------------------------------------------------------- /src/app/ngx-bootstrap/docs.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'docs', 6 | templateUrl: './docs.component.html', 7 | }) 8 | export class DocsComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/app/ngx-bootstrap/ngx-bootstrap.component.css: -------------------------------------------------------------------------------- 1 | .custom-tour-class, 2 | .custom-tour-class .popover-header, 3 | .custom-tour-class .popover-body { 4 | color: #eee; 5 | background-color: #333; 6 | border-color: #333; 7 | } 8 | .custom-tour-class .popover-arrow:before, 9 | .custom-tour-class .popover-arrow:after { 10 | border-top-color: #333 !important; 11 | } -------------------------------------------------------------------------------- /src/app/ngx-bootstrap/ngx-bootstrap.component.html: -------------------------------------------------------------------------------- 1 | View on GitHub 2 | Start Demo Tour 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/ngx-bootstrap/ngx-bootstrap.component.ts: -------------------------------------------------------------------------------- 1 | import { TourService } from 'ngx-tour-ngx-bootstrap'; 2 | import { Component, ViewEncapsulation } from '@angular/core'; 3 | 4 | @Component({ 5 | // tslint:disable-next-line:component-selector 6 | selector: 'ngx-bootstrap-route', 7 | templateUrl: './ngx-bootstrap.component.html', 8 | styleUrls: ['./ngx-bootstrap.component.css'], 9 | encapsulation: ViewEncapsulation.None 10 | }) 11 | export class NgxBootstrapComponent { 12 | constructor(public tourService: TourService) { 13 | this.tourService.initialize( 14 | [ 15 | { 16 | anchorId: 'start.tour', 17 | content: 'Welcome to the Ngx-Tour tour!', 18 | placement: 'right', 19 | title: 'Welcome' 20 | }, 21 | { 22 | anchorId: 'angular-ui-tour', 23 | content: 24 | 'Thanks to angular-ui-tour for the inspiration for the library', 25 | placement: 'bottom', 26 | title: 'angular-ui-tour' 27 | }, 28 | { 29 | anchorId: 'usage', 30 | content: '...then use it.', 31 | placement: 'right', 32 | title: 'Usage' 33 | }, 34 | { 35 | anchorId: 'tourService.start', 36 | content: 'Don\'t forget to actually start the tour.', 37 | placement: 'top', 38 | title: 'Start the tour' 39 | }, 40 | { 41 | anchorId: 'config.anchorId', 42 | content: 'Every step needs an anchor.', 43 | title: 'Anchor' 44 | }, 45 | { 46 | anchorId: 'config.route', 47 | content: 'Tours can span multiple routes. No placement.', 48 | title: 'Route' 49 | }, 50 | { 51 | anchorId: 'config.containerClass', 52 | content: 'You can add custom container class.', 53 | title: 'Custom CSS Class', 54 | containerClass: 'custom-tour-class' 55 | }, 56 | { 57 | anchorId: 'another.route', 58 | content: 'Like this!', 59 | route: 'ngx-bootstrap/other', 60 | title: 'Another Route' 61 | }, 62 | { 63 | anchorId: 'config.route', 64 | content: 'And then back again.', 65 | placement: 'bottom', 66 | title: 'Route Return' 67 | }, 68 | { 69 | anchorId: 'config.placement.default', 70 | content: 71 | 'Steps can be positioned around an anchor. You can even have multiple steps use the same anchor.', 72 | title: 'No Placement' 73 | }, 74 | { 75 | anchorId: 'config.placement.default', 76 | content: 'Sliiide to the left.', 77 | placement: 'left', 78 | title: 'Left Placement' 79 | }, 80 | { 81 | anchorId: 'config.placement.default', 82 | content: 'Sliiide to the right.', 83 | placement: 'right', 84 | title: 'Right Placement' 85 | }, 86 | { 87 | anchorId: 'config.placement.default', 88 | content: 'Take it back now y\'all. One hop this time.', 89 | placement: 'bottom', 90 | title: 'Bottom Placement' 91 | }, 92 | { 93 | anchorId: 'config.buttons.custom', 94 | content: 'You can set custom step button names', 95 | title: 'Button Titles', 96 | prevBtnTitle: 'My Prev', 97 | nextBtnTitle: 'My Next', 98 | endBtnTitle: 'My End' 99 | }, 100 | { 101 | anchorId: 'hotkeys', 102 | content: 'Try using the hotkeys to navigate through the tour.', 103 | title: 'Hotkeys' 104 | }, 105 | { 106 | anchorId: 'events', 107 | content: 'You can subscribe to events', 108 | title: 'Events' 109 | } 110 | ], 111 | { 112 | route: 'ngx-bootstrap' 113 | } 114 | ); 115 | this.tourService.start(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/app/ngx-bootstrap/ngx-bootstrap.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | import { TourNgxBootstrapModule } from 'ngx-tour-ngx-bootstrap'; 5 | 6 | import { DocsComponent } from './docs.component'; 7 | import { NgxBootstrapComponent } from './ngx-bootstrap.component'; 8 | import { OtherRouteComponent } from './other-route.component'; 9 | 10 | @NgModule({ 11 | declarations: [NgxBootstrapComponent, DocsComponent, OtherRouteComponent], 12 | imports: [ 13 | CommonModule, 14 | RouterModule.forChild([{ 15 | component: NgxBootstrapComponent, 16 | path: '', 17 | children: [{ 18 | component: DocsComponent, 19 | path: '', 20 | }, { 21 | component: OtherRouteComponent, 22 | path: 'other', 23 | }] 24 | }]), 25 | TourNgxBootstrapModule.forRoot(), 26 | ], 27 | }) 28 | export class NgxBootstrapModule { } 29 | -------------------------------------------------------------------------------- /src/app/ngx-bootstrap/other-route.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | // tslint:disable-next-line:component-selector 5 | selector: 'other-route', 6 | template: `

This is the another route

`, 7 | }) 8 | export class OtherRouteComponent { 9 | } 10 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isaacplmann/ngx-tour/0eb37de8b0644fe15ed2b206f5c815b981bf89df/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isaacplmann/ngx-tour/0eb37de8b0644fe15ed2b206f5c815b981bf89df/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ngx-Tour 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | Loading... 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { DemoModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(DemoModule); 12 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /*************************************************************************************************** 2 | * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. 3 | */ 4 | import '@angular/localize/init'; 5 | /** 6 | * This file includes polyfills needed by Angular and is loaded before the app. 7 | * You can add your own extra polyfills to this file. 8 | * 9 | * This file is divided into 2 sections: 10 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 11 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 12 | * file. 13 | * 14 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 15 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 16 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 17 | * 18 | * Learn more in https://angular.io/guide/browser-support 19 | */ 20 | 21 | /*************************************************************************************************** 22 | * BROWSER POLYFILLS 23 | */ 24 | 25 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 26 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 27 | 28 | /** 29 | * Web Animations `@angular/platform-browser/animations` 30 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 31 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 32 | */ 33 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 34 | 35 | /** 36 | * By default, zone.js will patch all possible macroTask and DomEvents 37 | * user can disable parts of macroTask/DomEvents patch by setting following flags 38 | * because those flags need to be set before `zone.js` being loaded, and webpack 39 | * will put import in the top of bundle, so user need to create a separate file 40 | * in this directory (for example: zone-flags.ts), and put the following flags 41 | * into that file, and then add the following code before importing zone.js. 42 | * import './zone-flags'; 43 | * 44 | * The flags allowed in zone-flags.ts are listed here. 45 | * 46 | * The following flags will work for all browsers. 47 | * 48 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 49 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 50 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 51 | * 52 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 53 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 54 | * 55 | * (window as any).__Zone_enable_cross_context_check = true; 56 | * 57 | */ 58 | 59 | /*************************************************************************************************** 60 | * Zone JS is required by default for Angular itself. 61 | */ 62 | import 'zone.js/dist/zone'; // Included with Angular CLI. 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @import '~@angular/material/prebuilt-themes/indigo-pink.css'; 3 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare var __karma__: any; 17 | declare var require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "main.ts", 9 | "polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "test.ts", 12 | "polyfills.ts" 13 | ], 14 | "include": [ 15 | "**/*.spec.ts", 16 | "**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "downlevelIteration": true, 6 | "importHelpers": true, 7 | "module": "es2020", 8 | "outDir": "./dist/out-tsc", 9 | "sourceMap": true, 10 | "declaration": false, 11 | "moduleResolution": "node", 12 | "emitDecoratorMetadata": true, 13 | "experimentalDecorators": true, 14 | "target": "es2015", 15 | "typeRoots": ["node_modules/@types"], 16 | "lib": ["es2017", "dom"], 17 | "paths": { 18 | "ngx-tour-core": ["dist/ngx-tour-core"], 19 | "ngx-tour-console": ["dist/ngx-tour-console"], 20 | "ngx-tour-md-menu": ["dist/ngx-tour-md-menu"], 21 | "ngx-tour-ng-bootstrap": ["dist/ngx-tour-ng-bootstrap"], 22 | "ngx-tour-ngx-bootstrap": ["dist/ngx-tour-ngx-bootstrap"], 23 | "ngx-tour-ngx-popper": ["dist/ngx-tour-ngx-popper"] 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience. 3 | It is not intended to be used to perform a compilation. 4 | 5 | To learn more about this file see: https://angular.io/config/solution-tsconfig. 6 | */ 7 | { 8 | "files": [], 9 | "references": [ 10 | { 11 | "path": "./src/tsconfig.app.json" 12 | }, 13 | { 14 | "path": "./src/tsconfig.spec.json" 15 | }, 16 | { 17 | "path": "./projects/ngx-tour-console/tsconfig.lib.json" 18 | }, 19 | { 20 | "path": "./projects/ngx-tour-console/tsconfig.spec.json" 21 | }, 22 | { 23 | "path": "./projects/ngx-tour-core/tsconfig.lib.json" 24 | }, 25 | { 26 | "path": "./projects/ngx-tour-core/tsconfig.spec.json" 27 | }, 28 | { 29 | "path": "./projects/ngx-tour-md-menu/tsconfig.lib.json" 30 | }, 31 | { 32 | "path": "./projects/ngx-tour-md-menu/tsconfig.spec.json" 33 | }, 34 | { 35 | "path": "./projects/ngx-tour-ng-bootstrap/tsconfig.lib.json" 36 | }, 37 | { 38 | "path": "./projects/ngx-tour-ng-bootstrap/tsconfig.spec.json" 39 | }, 40 | { 41 | "path": "./projects/ngx-tour-ngx-bootstrap/tsconfig.lib.json" 42 | }, 43 | { 44 | "path": "./projects/ngx-tour-ngx-bootstrap/tsconfig.spec.json" 45 | }, 46 | { 47 | "path": "./projects/ngx-tour-ngx-popper/tsconfig.lib.json" 48 | }, 49 | { 50 | "path": "./projects/ngx-tour-ngx-popper/tsconfig.spec.json" 51 | } 52 | ] 53 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "callable-types": true, 7 | "class-name": true, 8 | "comment-format": [ 9 | true, 10 | "check-space" 11 | ], 12 | "curly": true, 13 | "deprecation": { 14 | "severity": "warning" 15 | }, 16 | "eofline": true, 17 | "forin": true, 18 | "import-blacklist": [ 19 | true 20 | ], 21 | "import-spacing": true, 22 | "indent": [ 23 | true, 24 | "spaces" 25 | ], 26 | "interface-over-type-literal": true, 27 | "label-position": true, 28 | "max-line-length": [ 29 | true, 30 | 140 31 | ], 32 | "member-access": false, 33 | "member-ordering": [ 34 | true, 35 | { 36 | "order": [ 37 | "public-static-field", 38 | "public-instance-field", 39 | "public-static-method", 40 | "public-instance-method" 41 | ] 42 | } 43 | ], 44 | "no-arg": true, 45 | "no-bitwise": true, 46 | "no-console": [ 47 | true, 48 | "debug", 49 | "info", 50 | "time", 51 | "timeEnd", 52 | "trace" 53 | ], 54 | "no-construct": true, 55 | "no-debugger": true, 56 | "no-empty": false, 57 | "no-empty-interface": true, 58 | "no-eval": true, 59 | "no-inferrable-types": [ 60 | true, 61 | "ignore-params" 62 | ], 63 | "no-shadowed-variable": true, 64 | "no-string-literal": false, 65 | "no-string-throw": true, 66 | "no-switch-case-fall-through": true, 67 | "no-trailing-whitespace": true, 68 | "no-unused-expression": true, 69 | "no-var-keyword": true, 70 | "object-literal-sort-keys": false, 71 | "one-line": [ 72 | true, 73 | "check-open-brace", 74 | "check-catch", 75 | "check-else", 76 | "check-whitespace" 77 | ], 78 | "prefer-const": true, 79 | "quotemark": [ 80 | true, 81 | "single" 82 | ], 83 | "radix": true, 84 | "semicolon": true, 85 | "triple-equals": [ 86 | true, 87 | "allow-null-check" 88 | ], 89 | "typedef-whitespace": [ 90 | true, 91 | { 92 | "call-signature": "nospace", 93 | "index-signature": "nospace", 94 | "parameter": "nospace", 95 | "property-declaration": "nospace", 96 | "variable-declaration": "nospace" 97 | } 98 | ], 99 | "unified-signatures": true, 100 | "variable-name": false, 101 | "whitespace": [ 102 | true, 103 | "check-branch", 104 | "check-decl", 105 | "check-operator", 106 | "check-separator", 107 | "check-type" 108 | ], 109 | "directive-selector": [ 110 | true, 111 | "attribute", 112 | "app", 113 | "camelCase" 114 | ], 115 | "component-selector": [ 116 | true, 117 | "element", 118 | "app", 119 | "kebab-case" 120 | ], 121 | "no-inputs-metadata-property": true, 122 | "no-outputs-metadata-property": true, 123 | "no-host-metadata-property": true, 124 | "no-input-rename": true, 125 | "no-output-rename": true, 126 | "use-lifecycle-interface": true, 127 | "use-pipe-transform-interface": true, 128 | "component-class-suffix": true, 129 | "directive-class-suffix": true 130 | } 131 | } 132 | --------------------------------------------------------------------------------