├── .editorconfig
├── .gitignore
├── .prettierrc
├── .releaserc
├── .stylelintrc
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── angular.json
├── commitlint.config.js
├── docs
├── app
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── codes.ts
│ ├── examples
│ │ ├── control-example
│ │ │ ├── control-example.component.html
│ │ │ ├── control-example.component.scss
│ │ │ └── control-example.component.ts
│ │ ├── drag-example
│ │ │ ├── drag-example.component.html
│ │ │ └── drag-example.component.ts
│ │ ├── dropdown-example
│ │ │ ├── dropdown-example.component.html
│ │ │ ├── dropdown-example.component.scss
│ │ │ └── dropdown-example.component.ts
│ │ ├── dynamic-text-example
│ │ │ ├── dynamic-text-example.component.html
│ │ │ └── dynamic-text-example.component.ts
│ │ ├── fullscreen-position-example
│ │ │ ├── fullscreen-position-example.component.html
│ │ │ └── fullscreen-position-example.component.ts
│ │ ├── global-position-example
│ │ │ ├── global-position-example.component.html
│ │ │ └── global-position-example.component.ts
│ │ ├── modal-example
│ │ │ ├── modal-example.component.html
│ │ │ ├── modal-example.component.scss
│ │ │ └── modal-example.component.ts
│ │ ├── relative-position-example
│ │ │ ├── relative-position-example.component.html
│ │ │ └── relative-position-example.component.ts
│ │ ├── ribbon-example
│ │ │ ├── ribbon-example.component.html
│ │ │ ├── ribbon-example.component.scss
│ │ │ └── ribbon-example.component.ts
│ │ └── slide-position-example
│ │ │ ├── slide-position-example.component.html
│ │ │ └── slide-position-example.component.ts
│ ├── host-components
│ │ ├── hero-screen
│ │ │ ├── hero-screen.component.html
│ │ │ └── hero-screen.component.ts
│ │ ├── simple-list
│ │ │ ├── simple-list.component.html
│ │ │ └── simple-list.component.ts
│ │ ├── simple-modal
│ │ │ ├── simple-modal.component.html
│ │ │ └── simple-modal.component.ts
│ │ └── tooltip
│ │ │ ├── tooltip.component.html
│ │ │ └── tooltip.component.ts
│ ├── test
│ │ ├── test.component.html
│ │ ├── test.component.scss
│ │ ├── test.component.spec.ts
│ │ └── test.component.ts
│ └── utils
│ │ ├── content
│ │ ├── content.component.html
│ │ ├── content.component.scss
│ │ └── content.component.ts
│ │ ├── scollspy.directive.ts
│ │ ├── section
│ │ ├── section.component.html
│ │ └── section.component.ts
│ │ └── sub-section
│ │ ├── sub-section.component.html
│ │ └── sub-section.component.ts
├── assets
│ ├── .gitkeep
│ ├── archived-versions.json
│ ├── favicon.png
│ ├── favicon
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-256x256.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon.ico
│ │ ├── mstile-150x150.png
│ │ ├── og-image.jpg
│ │ └── safari-pinned-tab.svg
│ ├── icons
│ │ ├── icons8-beer-50.png
│ │ ├── icons8-cafe-50.png
│ │ ├── icons8-cocktail-50.png
│ │ ├── icons8-cola-50.png
│ │ ├── icons8-comments-50.png
│ │ ├── icons8-confetti-50.png
│ │ ├── icons8-dynamite-50.png
│ │ ├── icons8-explosive-50.png
│ │ ├── icons8-firework-explosion-100.png
│ │ ├── icons8-french-fries-50.png
│ │ ├── icons8-fried-chicken-50.png
│ │ ├── icons8-hamburger-50.png
│ │ ├── icons8-orange-50.png
│ │ ├── icons8-pears-50.png
│ │ ├── icons8-pizza-50.png
│ │ ├── icons8-sandwich-50.png
│ │ ├── icons8-scooter-50.png
│ │ ├── icons8-sweet-banana-50.png
│ │ ├── icons8-tequila-shot-50.png
│ │ ├── icons8-watch-50.png
│ │ ├── icons8-watermelon-50.png
│ │ └── icons8-whiskey-50.png
│ ├── illus
│ │ ├── congrats.svg
│ │ └── undraw_content_vbqo.svg
│ ├── img
│ │ ├── blast.png
│ │ ├── bomb.png
│ │ ├── clock.png
│ │ ├── cow.png
│ │ ├── five.png
│ │ ├── fly.png
│ │ ├── four.png
│ │ ├── goat.png
│ │ ├── mail.png
│ │ ├── one.png
│ │ ├── snake.png
│ │ ├── three.png
│ │ └── two.png
│ ├── lo-logo.png
│ ├── toppy-favicon.png
│ ├── toppy-logo-white.png
│ └── toppy-logo.png
├── browserslist
├── environments
│ ├── environment.prod.ts
│ ├── environment.ts
│ └── version.ts
├── favicon.ico
├── index.html
├── karma.conf.js
├── main.ts
├── markdown
│ └── main.md
├── polyfills.ts
├── styles
│ ├── _common.scss
│ ├── _config.scss
│ ├── _temp.scss
│ ├── animations
│ │ ├── __index.scss
│ │ └── _slide_in.scss
│ ├── base
│ │ ├── __index.scss
│ │ ├── _buttons.scss
│ │ ├── _fonts.scss
│ │ ├── _icons.scss
│ │ ├── _input.scss
│ │ ├── _pre.scss
│ │ ├── _reset.scss
│ │ ├── _typography.scss
│ │ └── _utility.scss
│ ├── browsers
│ │ ├── __index.scss
│ │ ├── _chrome.scss
│ │ ├── _firefox.scss
│ │ └── _ie11.scss
│ ├── components
│ │ ├── __index.scss
│ │ ├── _blade.scss
│ │ ├── _controls.scss
│ │ ├── _hero.scss
│ │ ├── _menu.scss
│ │ ├── _modal.scss
│ │ ├── _table.scss
│ │ └── _target-element-container.scss
│ ├── elements
│ │ ├── __index.scss
│ │ ├── _btn.scss
│ │ ├── _hr.scss
│ │ ├── _toast.scss
│ │ └── _tooltip.scss
│ ├── helpers
│ │ ├── __index.scss
│ │ ├── _debug.scss
│ │ ├── functions
│ │ │ ├── __index.scss
│ │ │ ├── _clr.scss
│ │ │ ├── _fs.scss
│ │ │ ├── _rem.scss
│ │ │ └── _z.scss
│ │ └── mixins
│ │ │ ├── __index.scss
│ │ │ ├── _acceleration.scss
│ │ │ ├── _ellipsis.scss
│ │ │ ├── _gradient.scss
│ │ │ ├── _placeholder.scss
│ │ │ └── _smooth-font.scss
│ ├── icons
│ │ ├── toppy.svg
│ │ ├── toppy.ttf
│ │ └── toppy.woff
│ ├── layouts
│ │ └── __index.scss
│ ├── pages
│ │ └── __index.scss
│ ├── responsive
│ │ ├── __index.scss
│ │ ├── _lg.scss
│ │ ├── _md.scss
│ │ └── _xl.scss
│ ├── root.scss
│ └── vendors
│ │ ├── __index.scss
│ │ ├── _bootstrap.scss
│ │ ├── _pretty-checkbox.scss
│ │ └── _prism.scss
├── test.ts
├── tsconfig.app.json
├── tsconfig.spec.json
└── tslint.json
├── e2e
├── protractor.conf.js
├── src
│ ├── app.e2e-spec.ts
│ └── app.po.ts
└── tsconfig.e2e.json
├── package-lock.json
├── package.json
├── projects
└── toppy
│ ├── karma.conf.js
│ ├── ng-package.json
│ ├── package.json
│ ├── src
│ ├── lib
│ │ ├── config.ts
│ │ ├── models.ts
│ │ ├── position
│ │ │ ├── fullscreen-position.ts
│ │ │ ├── global-position.ts
│ │ │ ├── index.ts
│ │ │ ├── position.ts
│ │ │ ├── relative-position.ts
│ │ │ └── slide-position.ts
│ │ ├── styles.scss
│ │ ├── template.html
│ │ ├── toppy-control.ts
│ │ ├── toppy.component.ts
│ │ ├── toppy.module.ts
│ │ ├── toppy.ts
│ │ └── utils.ts
│ ├── public_api.ts
│ ├── test.ts
│ └── tests
│ │ ├── positions
│ │ ├── fullscreen-position.spec.ts
│ │ ├── global-position.spec.ts
│ │ ├── relative-position.spec.ts
│ │ └── slide-position.spec.ts
│ │ ├── toppy-control.spec.ts
│ │ ├── toppy.component.spec.ts
│ │ ├── toppy.spec.ts
│ │ └── utils.spec.ts
│ ├── tsconfig.lib.json
│ ├── tsconfig.spec.json
│ └── tslint.json
├── scripts
├── archive.js
├── build-md.js
├── gh-pages.js
└── version.sh
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 |
20 | # IDE - VSCode
21 | .vscode/*
22 | .history/*
23 | !.vscode/settings.json
24 | !.vscode/tasks.json
25 | !.vscode/launch.json
26 | !.vscode/extensions.json
27 |
28 | # misc
29 | /.sass-cache
30 | /connect.lock
31 | /coverage
32 | /documentation
33 | /libpeerconnection.log
34 | npm-debug.log
35 | yarn-error.log
36 | testem.log
37 | /typings
38 |
39 | # System Files
40 | .DS_Store
41 | Thumbs.db
42 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "singleQuote": true,
4 | "useTabs": false,
5 | "tabWidth": 2,
6 | "semi": true,
7 | "bracketSpacing": true
8 | }
9 |
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | {
2 | "branch": "master",
3 | "plugins": [
4 | [
5 | "@semantic-release/exec",
6 | {
7 | "prepareCmd": "npm run archive:app -- ${nextRelease.version} && chmod a+x ./scripts/version.sh && ./scripts/version.sh ${nextRelease.version} && cp -r ./README.md ./dist/toppy && npx json -I -f package.json -e 'this.version=\"${nextRelease.version}\"'",
8 | "successCmd": "npm run postpublish -- ${nextRelease.version}"
9 | }
10 | ],
11 | [
12 | "@semantic-release/commit-analyzer",
13 | {
14 | "releaseRules": [
15 | { "type": "feat", "release": "minor" },
16 | { "type": "fix", "release": "patch" },
17 | { "type": "perf", "release": "patch" },
18 | { "breaking": true, "release": "major" },
19 | { "revert": true, "release": "patch" },
20 | { "type": "docs", "release": "patch" },
21 | { "type": "refactor", "release": "patch" },
22 | { "type": "style", "release": "patch" }
23 | ],
24 | "parserOpts": {
25 | "noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"]
26 | }
27 | }
28 | ],
29 | "@semantic-release/changelog",
30 | "@semantic-release/release-notes-generator",
31 | [
32 | "@semantic-release/npm",
33 | {
34 | "npmPublish": true,
35 | "tarballDir": "dist/toppy",
36 | "pkgRoot": "dist/toppy"
37 | }
38 | ],
39 | "@semantic-release/github",
40 | [
41 | "@semantic-release/git",
42 | {
43 | "assets": [
44 | "projects/toppy/package.json",
45 | "package.json",
46 | "package-lock.json",
47 | "CHANGELOG.md",
48 | "docs/environments/version.ts",
49 | "docs/assets/archived-versions.json"
50 | ],
51 | "message": ":fire: chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
52 | }
53 | ]
54 | ],
55 | "preset": "angular"
56 | }
57 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-recommended-scss",
3 | "rules": {
4 | "selector-type-no-unknown": [true, { "ignoreTypes": ["/choosy-/"] }]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | cache:
3 | directories:
4 | - '~/.npm'
5 | - node_modules
6 | notifications:
7 | email: false
8 | slack:
9 | secure: E3zMq5rOujXNqci/8aKxtDDFYNb3QqEi8O9n2enTpLzuK5qVPnaVDzXre7MxLN13LYsRMzT3hpzngOu09Zj1Gt49MCXBDjseF6tVddEE2hURVCVSF87Of4pMUbxxC8zmIwMk33UBGGkS2F5fvkKiX1KL2LdqoJ+2GwD6xq0swPXC+LvbbT0bMif0jFzyJKYyqvT13UzMg+6m4obrfKbaXUdrG7woFs1UMhwkSY4i167w/l3+hYGY4TsOENhoqdUahP3CGu1v6zesLacwGk8A8H00A8dS5oXu0XuWZ+AdFOBpNBHj0JOWkFmMdDTtwOzKIYrGnPHbE1U0/ROdqguT6EBVqnOIHnGsjvBkqUN9mVrR+9iLcdODnsv9MkDEKnxrcpUcCITfTdsaCktIC17Xoe14WsIAB+doxq9fYGvBqqTj7GzMA+8a36ae2AaQDNrAJ+YojbqkisWc/BkkFFHd2EISges/nYmDqDcdk0UpfNuAeheynEiIFKISoxGjd5w/VI9oopY250u2qAwEPdvV8tn31WOxLlx00oe928bY4yPzMv/CkRInXzhmddCZidBGKh7nKTDut4VST/nwawkey5G1xYzHOzxSX1z7X8RQkMocWZ5etGv9bCxiOV/RSkhjzu8eLHKqUd5xs/+PYDxmG3iFzmVXEf4mELm7Bw2JuxE=
10 | node_js:
11 | - 9.3.0
12 | install:
13 | - npm install
14 | - npm install -g codecov
15 | before_script:
16 | - export CHROME_BIN=/usr/bin/google-chrome
17 | - export DISPLAY=:99.0
18 | - sh -e /etc/init.d/xvfb start
19 | - sudo apt-get update
20 | - sudo apt-get install -y libappindicator1 fonts-liberation
21 | - wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
22 | - sudo dpkg -i google-chrome*.deb
23 | script:
24 | - npm run test:lib -- --watch=false
25 | - codecov
26 | - npm run build:lib
27 | - npm run build:app
28 | after_success:
29 | - npm run travis-deploy-once "npm run release"
30 | branches:
31 | except:
32 | - "/^v\\d+\\.\\d+\\.\\d+$/"
33 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [2.3.4](https://github.com/lokesh-coder/toppy/compare/v2.3.3...v2.3.4) (2019-07-31)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * backdrop custom class not added ([#35](https://github.com/lokesh-coder/toppy/issues/35)) ([23752b9](https://github.com/lokesh-coder/toppy/commit/23752b9))
7 |
8 | ## [2.3.3](https://github.com/lokesh-coder/toppy/compare/v2.3.2...v2.3.3) (2019-03-13)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * relative positon incorrect placement on `autoUpdate` ([f3c0106](https://github.com/lokesh-coder/toppy/commit/f3c0106))
14 |
15 | ## [2.3.2](https://github.com/lokesh-coder/toppy/compare/v2.3.1...v2.3.2) (2019-02-12)
16 |
17 | ## [2.3.1](https://github.com/lokesh-coder/toppy/compare/v2.3.0...v2.3.1) (2019-02-10)
18 |
19 | # [2.3.0](https://github.com/lokesh-coder/toppy/compare/v2.2.0...v2.3.0) (2019-01-05)
20 |
21 |
22 | ### Features
23 |
24 | * add support to access host component instance ([6cf180a](https://github.com/lokesh-coder/toppy/commit/6cf180a))
25 |
26 | # [2.2.0](https://github.com/lokesh-coder/toppy/compare/v2.1.0...v2.2.0) (2018-12-31)
27 |
28 |
29 | ### Features
30 |
31 | * attach component custom props on initialize without ToppyOverlay ([e96a5f4](https://github.com/lokesh-coder/toppy/commit/e96a5f4))
32 |
33 | # [2.1.0](https://github.com/lokesh-coder/toppy/compare/v2.0.5...v2.1.0) (2018-12-25)
34 |
35 |
36 | ### Bug Fixes
37 |
38 | * re-render when nested dynamic component ([68f5844](https://github.com/lokesh-coder/toppy/commit/68f5844))
39 |
40 |
41 | ### Features
42 |
43 | * add position classes to warpper element ([79fc1a5](https://github.com/lokesh-coder/toppy/commit/79fc1a5))
44 | * add position classes to warpper element ([b8ffb44](https://github.com/lokesh-coder/toppy/commit/b8ffb44))
45 |
46 | ## [2.0.5](https://github.com/lokesh-coder/toppy/compare/v2.0.4...v2.0.5) (2018-12-24)
47 |
48 | ## [2.0.4](https://github.com/lokesh-coder/toppy/compare/v2.0.3...v2.0.4) (2018-12-20)
49 |
50 |
51 | ### Bug Fixes
52 |
53 | * allow custom props to be accessed in host component ([9d8e4ba](https://github.com/lokesh-coder/toppy/commit/9d8e4ba))
54 |
55 | ## [2.0.3](https://github.com/lokesh-coder/toppy/compare/v2.0.2...v2.0.3) (2018-12-15)
56 |
57 | ## [2.0.2](https://github.com/lokesh-coder/toppy/compare/v2.0.1...v2.0.2) (2018-12-15)
58 |
59 |
60 | ### Bug Fixes
61 |
62 | * incorrect signature in API ([c80658e](https://github.com/lokesh-coder/toppy/commit/c80658e))
63 |
64 | ## [2.0.1](https://github.com/lokesh-coder/toppy/compare/v2.0.0...v2.0.1) (2018-12-14)
65 |
66 | # [2.0.0](https://github.com/lokesh-coder/toppy/compare/v1.3.1...v2.0.0) (2018-12-14)
67 |
68 |
69 | ### Bug Fixes
70 |
71 | * remove unused components ([10a3fd8](https://github.com/lokesh-coder/toppy/commit/10a3fd8))
72 | * ss class method [skip ci] ([521c2d1](https://github.com/lokesh-coder/toppy/commit/521c2d1))
73 |
74 |
75 | ### Features
76 |
77 | * access custom props in Component, Template and Plain text contents ([b8550c8](https://github.com/lokesh-coder/toppy/commit/b8550c8))
78 | * add template ref context ([e3e4ff1](https://github.com/lokesh-coder/toppy/commit/e3e4ff1)), closes [#19](https://github.com/lokesh-coder/toppy/issues/19)
79 | * added support for custom key to reference later ([3901878](https://github.com/lokesh-coder/toppy/commit/3901878))
80 | * include context data in templateref ([a865929](https://github.com/lokesh-coder/toppy/commit/a865929))
81 |
82 |
83 | ### BREAKING CHANGES
84 |
85 | * API has been changed. `.overlay()` to `.position()` , `.host()` to `.content()` , `updateHost()` to `updateContent()` , `ToppyRef` to `ToppyControl`. Introduced `.config()`. Performance improvement.
86 |
87 | ## [1.3.1](https://github.com/lokesh-coder/toppy/compare/v1.3.0...v1.3.1) (2018-12-05)
88 |
89 |
90 | ### Bug Fixes
91 |
92 | * **global position:** calculate proper left and top co-ordinates when `hostWidth` and `hostHeight` in percentage ([59dd68b](https://github.com/lokesh-coder/toppy/commit/59dd68b))
93 |
94 | # [1.3.0](https://github.com/lokesh-coder/toppy/compare/v1.2.4...v1.3.0) (2018-12-04)
95 |
96 |
97 | ### Features
98 |
99 | * **relative position:** added support for content sticking with target element when `autoUpdate` is set to true ([6fa37e7](https://github.com/lokesh-coder/toppy/commit/6fa37e7))
100 |
101 | ## [1.2.4](https://github.com/lokesh-coder/toppy/compare/v1.2.3...v1.2.4) (2018-11-28)
102 |
103 |
104 | ### Bug Fixes
105 |
106 | * replace codeclimate with codecov config in travis ([af9d16f](https://github.com/lokesh-coder/toppy/commit/af9d16f))
107 |
108 | ## [1.2.3](https://github.com/lokesh-coder/toppy/compare/v1.2.2...v1.2.3) (2018-11-28)
109 |
110 |
111 | ### Bug Fixes
112 |
113 | * **docs:** update font path ([29834a5](https://github.com/lokesh-coder/toppy/commit/29834a5))
114 | * move artifacts after build ([d7ff131](https://github.com/lokesh-coder/toppy/commit/d7ff131))
115 |
116 | ## [1.2.2](https://github.com/lokesh-coder/toppy/compare/v1.2.1...v1.2.2) (2018-11-28)
117 |
118 |
119 | ### Bug Fixes
120 |
121 | * updated vulnerable dependencies ([ace393d](https://github.com/lokesh-coder/toppy/commit/ace393d))
122 | * **docs:** update icon fonts path ([eedca4c](https://github.com/lokesh-coder/toppy/commit/eedca4c))
123 |
124 | ## [1.2.1](https://github.com/lokesh-coder/toppy/compare/v1.2.0...v1.2.1) (2018-11-26)
125 |
126 |
127 | ### Bug Fixes
128 |
129 | * **docs:** set font icons path properly ([1d26809](https://github.com/lokesh-coder/toppy/commit/1d26809))
130 | * **docs:** set font icons path properly ([0ae8424](https://github.com/lokesh-coder/toppy/commit/0ae8424))
131 |
132 | # [1.2.0](https://github.com/lokesh-coder/toppy/compare/v1.1.1...v1.2.0) (2018-11-24)
133 |
134 |
135 | ### Features
136 |
137 | * added new config prop 'bodyClassNameOnOpen' ([0e047bf](https://github.com/lokesh-coder/toppy/commit/0e047bf))
138 | * add new config 'closeOnEsc' ([fc1577e](https://github.com/lokesh-coder/toppy/commit/fc1577e))
139 | * added support to change content after create ([02182b3](https://github.com/lokesh-coder/toppy/commit/02182b3))
140 | * added version selector in doc ([7554f7b](https://github.com/lokesh-coder/toppy/commit/7554f7b))
141 | * minor improvements and fixes ([8152b1c](https://github.com/lokesh-coder/toppy/commit/8152b1c))
142 |
143 | ## [1.1.1](https://github.com/lokesh-coder/toppy/compare/v1.1.0...v1.1.1) (2018-11-22)
144 |
145 |
146 | ### Bug Fixes
147 |
148 | * multiple toppy config override ([#8](https://github.com/lokesh-coder/toppy/issues/8)) ([ca0ce7e](https://github.com/lokesh-coder/toppy/commit/ca0ce7e))
149 |
150 | # [1.1.0](https://github.com/lokesh-coder/toppy/compare/v1.0.18...v1.1.0) (2018-11-18)
151 |
152 |
153 | ### Features
154 |
155 | * fade in content once position is updated ([3520ef6](https://github.com/lokesh-coder/toppy/commit/3520ef6))
156 | * fade in content only after final position is updated ([abbfc8f](https://github.com/lokesh-coder/toppy/commit/abbfc8f))
157 |
158 | ## [1.0.18](https://github.com/lokesh-coder/toppy/compare/v1.0.17...v1.0.18) (2018-11-16)
159 |
160 | ## [1.0.17](https://github.com/lokesh-coder/toppy/compare/v1.0.16...v1.0.17) (2018-11-13)
161 |
162 | ## [1.0.16](https://github.com/lokesh-coder/toppy/compare/v1.0.15...v1.0.16) (2018-11-09)
163 |
164 | ## [1.0.15](https://github.com/lokesh-coder/toppy/compare/v1.0.14...v1.0.15) (2018-11-06)
165 |
166 | ## [1.0.14](https://github.com/lokesh-coder/toppy/compare/v1.0.13...v1.0.14) (2018-11-03)
167 |
168 | ## [1.0.13](https://github.com/lokesh-coder/toppy/compare/v1.0.12...v1.0.13) (2018-11-02)
169 |
170 |
171 | ### Bug Fixes
172 |
173 | * override files on ghpages instead of replace ([d282266](https://github.com/lokesh-coder/toppy/commit/d282266))
174 |
175 | ## [1.0.12](https://github.com/lokesh-coder/toppy/compare/v1.0.11...v1.0.12) (2018-11-02)
176 |
177 |
178 | ### Bug Fixes
179 |
180 | * add and sort details in package file ([6db7797](https://github.com/lokesh-coder/toppy/commit/6db7797))
181 | * merge conflict resolve ([a412259](https://github.com/lokesh-coder/toppy/commit/a412259))
182 |
183 | ## [1.0.11](https://github.com/lokesh-coder/toppy/compare/v1.0.10...v1.0.11) (2018-11-01)
184 |
185 |
186 | ### Bug Fixes
187 |
188 | * move archive logic to verfiyRelease stage ([cdce3c1](https://github.com/lokesh-coder/toppy/commit/cdce3c1))
189 |
190 | ## [1.0.10](https://github.com/lokesh-coder/toppy/compare/v1.0.9...v1.0.10) (2018-11-01)
191 |
192 |
193 | ### Bug Fixes
194 |
195 | * archive version before publishing ([6dd714a](https://github.com/lokesh-coder/toppy/commit/6dd714a))
196 |
197 | ## [1.0.9](https://github.com/lokesh-coder/toppy/compare/v1.0.8...v1.0.9) (2018-11-01)
198 |
199 |
200 | ### Bug Fixes
201 |
202 | * publish gh-pages with achived versions ([19a34c2](https://github.com/lokesh-coder/toppy/commit/19a34c2))
203 |
204 | ## [1.0.8](https://github.com/lokesh-coder/toppy/compare/v1.0.7...v1.0.8) (2018-11-01)
205 |
206 |
207 | ### Bug Fixes
208 |
209 | * ghpages publish path ([f5d2f47](https://github.com/lokesh-coder/toppy/commit/f5d2f47))
210 |
211 | ## [1.0.7](https://github.com/lokesh-coder/toppy/compare/v1.0.6...v1.0.7) (2018-11-01)
212 |
213 |
214 | ### Bug Fixes
215 |
216 | * set archive version properly ([b01d0ab](https://github.com/lokesh-coder/toppy/commit/b01d0ab))
217 |
218 | ## [1.0.6](https://github.com/lokesh-coder/toppy/compare/v1.0.5...v1.0.6) (2018-11-01)
219 |
220 |
221 | ### Bug Fixes
222 |
223 | * archive doc build versions ([06226c4](https://github.com/lokesh-coder/toppy/commit/06226c4))
224 |
225 | ## [1.0.5](https://github.com/lokesh-coder/toppy/compare/v1.0.4...v1.0.5) (2018-11-01)
226 |
227 |
228 | ### Bug Fixes
229 |
230 | * change gh pages publish package ([a5ef149](https://github.com/lokesh-coder/toppy/commit/a5ef149))
231 |
232 | ## [1.0.4](https://github.com/lokesh-coder/toppy/compare/v1.0.3...v1.0.4) (2018-11-01)
233 |
234 |
235 | ### Bug Fixes
236 |
237 | * update build command in package json ([0ed8a10](https://github.com/lokesh-coder/toppy/commit/0ed8a10))
238 |
239 | ## [1.0.3](https://github.com/lokesh-coder/toppy/compare/v1.0.2...v1.0.3) (2018-11-01)
240 |
241 |
242 | ### Bug Fixes
243 |
244 | * remove assets release in github ([8fb1ec8](https://github.com/lokesh-coder/toppy/commit/8fb1ec8))
245 |
246 | ## [1.0.2](https://github.com/lokesh-coder/toppy/compare/v1.0.1...v1.0.2) (2018-11-01)
247 |
248 |
249 | ### Bug Fixes
250 |
251 | * release doc assets to github pages ([87b460b](https://github.com/lokesh-coder/toppy/commit/87b460b))
252 |
253 | ## [1.0.1](https://github.com/lokesh-coder/toppy.git/compare/v1.0.0...v1.0.1) (2018-11-01)
254 |
255 | # 1.0.0 (2018-11-01)
256 |
257 |
258 | ### Bug Fixes
259 |
260 | * package json scripts and travis ([bc4f996](https://github.com/lokesh-coder/toppy.git/commit/bc4f996))
261 |
262 |
263 | ### Features
264 |
265 | * add support for ghpages auto publish ([a8c8b7c](https://github.com/lokesh-coder/toppy.git/commit/a8c8b7c))
266 | * initial commit ([6464f1a](https://github.com/lokesh-coder/toppy.git/commit/6464f1a))
267 | * **docs:** installation API update ([a80fab0](https://github.com/lokesh-coder/toppy.git/commit/a80fab0))
268 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Lokesh Rajendran ( mexican.dirtyfellow@gmail.com )
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
10 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "toppy-app": {
7 | "root": "",
8 | "sourceRoot": "docs",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {
12 | "@schematics/angular:component": {
13 | "styleext": "scss",
14 | "spec": false
15 | },
16 | "@schematics/angular:class": {
17 | "spec": false
18 | },
19 | "@schematics/angular:directive": {
20 | "spec": false
21 | },
22 | "@schematics/angular:guard": {
23 | "spec": false
24 | },
25 | "@schematics/angular:module": {
26 | "spec": false
27 | },
28 | "@schematics/angular:pipe": {
29 | "spec": false
30 | },
31 | "@schematics/angular:service": {
32 | "spec": false
33 | }
34 | },
35 | "architect": {
36 | "build": {
37 | "builder": "@angular-devkit/build-angular:browser",
38 | "options": {
39 | "outputPath": "dist/toppy-app",
40 | "index": "docs/index.html",
41 | "main": "docs/main.ts",
42 | "polyfills": "docs/polyfills.ts",
43 | "tsConfig": "docs/tsconfig.app.json",
44 | "assets": ["docs/favicon.ico", "docs/assets"],
45 | "styles": ["docs/styles/root.scss", "node_modules/prismjs/themes/prism.css"],
46 | "scripts": [
47 | "node_modules/marked/lib/marked.js",
48 | "node_modules/prismjs/prism.js",
49 | "node_modules/prismjs/components/prism-css.min.js",
50 | "node_modules/prismjs/components/prism-typescript.min.js",
51 | "node_modules/prismjs/components/prism-powershell.min.js",
52 | "node_modules/prismjs/components/prism-javascript.min.js"
53 | ]
54 | },
55 | "configurations": {
56 | "production": {
57 | "fileReplacements": [
58 | {
59 | "replace": "docs/environments/environment.ts",
60 | "with": "docs/environments/environment.prod.ts"
61 | }
62 | ],
63 | "optimization": true,
64 | "outputHashing": "all",
65 | "sourceMap": false,
66 | "extractCss": true,
67 | "namedChunks": false,
68 | "aot": true,
69 | "extractLicenses": true,
70 | "vendorChunk": false,
71 | "buildOptimizer": true,
72 | "budgets": [
73 | {
74 | "type": "initial",
75 | "maximumWarning": "2mb",
76 | "maximumError": "5mb"
77 | }
78 | ]
79 | }
80 | }
81 | },
82 | "serve": {
83 | "builder": "@angular-devkit/build-angular:dev-server",
84 | "options": {
85 | "browserTarget": "toppy-app:build"
86 | },
87 | "configurations": {
88 | "production": {
89 | "browserTarget": "toppy-app:build:production"
90 | }
91 | }
92 | },
93 | "extract-i18n": {
94 | "builder": "@angular-devkit/build-angular:extract-i18n",
95 | "options": {
96 | "browserTarget": "toppy-app:build"
97 | }
98 | },
99 | "test": {
100 | "builder": "@angular-devkit/build-angular:karma",
101 | "options": {
102 | "main": "docs/test.ts",
103 | "polyfills": "docs/polyfills.ts",
104 | "tsConfig": "docs/tsconfig.spec.json",
105 | "karmaConfig": "docs/karma.conf.js",
106 | "styles": ["docs/styles/root.scss"],
107 | "scripts": [],
108 | "assets": ["docs/favicon.ico", "docs/assets"]
109 | }
110 | },
111 | "lint": {
112 | "builder": "@angular-devkit/build-angular:tslint",
113 | "options": {
114 | "tsConfig": ["docs/tsconfig.app.json", "docs/tsconfig.spec.json"],
115 | "exclude": ["**/node_modules/**"]
116 | }
117 | }
118 | }
119 | },
120 | "toppy-app-e2e": {
121 | "root": "e2e/",
122 | "projectType": "application",
123 | "prefix": "",
124 | "architect": {
125 | "e2e": {
126 | "builder": "@angular-devkit/build-angular:protractor",
127 | "options": {
128 | "protractorConfig": "e2e/protractor.conf.js",
129 | "devServerTarget": "toppy-app:serve"
130 | },
131 | "configurations": {
132 | "production": {
133 | "devServerTarget": "toppy-app:serve:production"
134 | }
135 | }
136 | },
137 | "lint": {
138 | "builder": "@angular-devkit/build-angular:tslint",
139 | "options": {
140 | "tsConfig": "e2e/tsconfig.e2e.json",
141 | "exclude": ["**/node_modules/**"]
142 | }
143 | }
144 | }
145 | },
146 | "toppy": {
147 | "root": "projects/toppy",
148 | "sourceRoot": "projects/toppy/src",
149 | "projectType": "library",
150 | "prefix": "lib",
151 | "architect": {
152 | "build": {
153 | "builder": "@angular-devkit/build-ng-packagr:build",
154 | "options": {
155 | "tsConfig": "projects/toppy/tsconfig.lib.json",
156 | "project": "projects/toppy/ng-package.json"
157 | }
158 | },
159 | "test": {
160 | "builder": "@angular-devkit/build-angular:karma",
161 | "options": {
162 | "main": "projects/toppy/src/test.ts",
163 | "tsConfig": "projects/toppy/tsconfig.spec.json",
164 | "karmaConfig": "projects/toppy/karma.conf.js",
165 | "codeCoverage": true
166 | }
167 | },
168 | "lint": {
169 | "builder": "@angular-devkit/build-angular:tslint",
170 | "options": {
171 | "tsConfig": ["projects/toppy/tsconfig.lib.json", "projects/toppy/tsconfig.spec.json"],
172 | "exclude": ["**/node_modules/**"]
173 | }
174 | }
175 | }
176 | }
177 | },
178 | "defaultProject": "toppy-app"
179 | }
180 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ['@commitlint/config-conventional'] };
2 |
--------------------------------------------------------------------------------
/docs/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Tiny Overlay library for Angular apps. Easy and simple API
10 |
11 | tooltip modal sidemenu dropdowns
12 | popup menu toaster alerts datepicker
13 | popovers
14 |
15 |
16 |
17 |
18 |
19 |
26 |
34 |
42 |
50 |
51 |
56 |
57 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
123 |
124 |
129 |
130 |
131 |
134 |
--------------------------------------------------------------------------------
/docs/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from "@angular/core/testing";
2 | import { AppComponent } from "./app.component";
3 | describe("AppComponent", () => {
4 | beforeEach(async(() => {
5 | TestBed.configureTestingModule({
6 | declarations: [AppComponent]
7 | }).compileComponents();
8 | }));
9 | it("should create the app", async(() => {
10 | const fixture = TestBed.createComponent(AppComponent);
11 | const app = fixture.debugElement.componentInstance;
12 | expect(app).toBeTruthy();
13 | }));
14 | it(`should have as title 'toppy app'`, async(() => {
15 | const fixture = TestBed.createComponent(AppComponent);
16 | const app = fixture.debugElement.componentInstance;
17 | expect(app.title).toEqual("toppy-app");
18 | }));
19 | it("should render title in a h1 tag", async(() => {
20 | const fixture = TestBed.createComponent(AppComponent);
21 | fixture.detectChanges();
22 | const compiled = fixture.debugElement.nativeElement;
23 | expect(compiled.querySelector("h1").textContent).toContain("Welcome to toppy App!");
24 | }));
25 | });
26 |
--------------------------------------------------------------------------------
/docs/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Component, ElementRef, ViewChild } from '@angular/core';
3 | import { fromEvent } from 'rxjs';
4 | import { TOPPY_VERSION } from '../environments/version';
5 | // import { Toppy } from 'toppy';
6 | import { code } from './codes';
7 |
8 | @Component({
9 | selector: 'app-root',
10 | templateUrl: './app.component.html'
11 | })
12 | export class AppComponent {
13 | latestVersion = '';
14 | versions = [];
15 | title = 'toppy-app';
16 | selectedVersion = '';
17 | currentVersion = TOPPY_VERSION;
18 | @ViewChild('el', { read: ElementRef })
19 | el: ElementRef;
20 | ins;
21 | code = code;
22 | constructor(private http: HttpClient) {
23 | this.http.get('./assets/archived-versions.json').subscribe(data => {
24 | this.versions = Object.keys(data)
25 | .filter(a => a !== 'undefined')
26 | .sort((a, b) => ('' + b).localeCompare(a));
27 | this.latestVersion = this.versions[0];
28 | this.getCurrentVerison();
29 | });
30 | }
31 | currentSection = '';
32 |
33 | onSectionChange(sectionId: string) {
34 | this.currentSection = sectionId;
35 | }
36 |
37 | scrollTo(section) {
38 | this.currentSection = section;
39 | document.querySelector('#' + section).scrollIntoView();
40 | }
41 |
42 | ngOnInit() {
43 | this.onScroll();
44 | }
45 |
46 | ngafterViewInit() {
47 | this.getCurrentVerison();
48 | }
49 |
50 | getCurrentVerison() {
51 | const parts = window.location.pathname.split('/').filter(a => a.length > 0);
52 | if (parts.length === 2) {
53 | this.selectedVersion = parts[1];
54 | } else {
55 | this.selectedVersion = this.latestVersion;
56 | }
57 | }
58 |
59 | onVersionChange(version) {
60 | (window as any).location = `https://lokesh-coder.github.io/toppy/${version}`;
61 | }
62 |
63 | onScroll() {
64 | fromEvent(window, 'scroll')
65 | .pipe()
66 | .subscribe(res => {
67 | const heroHeight = document.querySelector('.hero').getBoundingClientRect().height;
68 | const scrolledTo = document.documentElement.scrollTop;
69 | if (scrolledTo >= heroHeight) {
70 | document.querySelector('body').classList.add('sidebar-fixed');
71 | } else {
72 | document.querySelector('body').classList.remove('sidebar-fixed');
73 | }
74 | });
75 | }
76 |
77 | tweet(e) {
78 | const getWindowOptions = function() {
79 | const width = 500;
80 | const height = 350;
81 | const left = window.innerWidth / 2 - width / 2;
82 | const top = window.innerHeight / 2 - height / 2;
83 |
84 | return ['resizable,scrollbars,status', 'height=' + height, 'width=' + width, 'left=' + left, 'top=' + top].join();
85 | };
86 | // const text = encodeURIComponent('Hey everyone, come & see how good I look!');
87 | const shareUrl = `https://twitter.com/intent/tweet?hashtags=angular&original_referer=http%3A%2F%2Flocalhost%3A4200%2F&ref_src=twsrc%5Etfw&text=Cute%20overlay%20library%20for%20Angular%20-%20tooltips%2C%20modals%2C%20toastr%2C%20menu%2C%20dropdowns%2C%20alerts%2C%20popovers%2C%20sidebar%20and%20more...%20&tw_p=tweetbutton&url=https%3A%2F%2Flokesh-coder.github.io%2Ftoppy%2F&via=lokesh_coder`;
88 |
89 | e.preventDefault();
90 | const win = window.open(shareUrl, 'ShareOnTwitter', getWindowOptions());
91 | win.opener = null; // 2
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/docs/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { HttpClientModule } from '@angular/common/http';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule } from '@angular/forms';
4 | import { BrowserModule } from '@angular/platform-browser';
5 | import { ToppyModule } from 'toppy';
6 | import { AppComponent } from './app.component';
7 | import { ControlExampleComponent } from './examples/control-example/control-example.component';
8 | import { DragExampleComponent } from './examples/drag-example/drag-example.component';
9 | import { DropdownExampleComponent } from './examples/dropdown-example/dropdown-example.component';
10 | import { DynamicTextExampleComponent } from './examples/dynamic-text-example/dynamic-text-example.component';
11 | import { FullscreenPositionExampleComponent } from './examples/fullscreen-position-example/fullscreen-position-example.component';
12 | import { GlobalPositionExampleComponent } from './examples/global-position-example/global-position-example.component';
13 | import { ModalExampleComponent } from './examples/modal-example/modal-example.component';
14 | import { RelativePositionExampleComponent } from './examples/relative-position-example/relative-position-example.component';
15 | import { RibbonExampleComponent } from './examples/ribbon-example/ribbon-example.component';
16 | import { SlidePositionExampleComponent } from './examples/slide-position-example/slide-position-example.component';
17 | import { HeroScreenComponent } from './host-components/hero-screen/hero-screen.component';
18 | import { SimpleListComponent } from './host-components/simple-list/simple-list.component';
19 | import { SimpleModalComponent } from './host-components/simple-modal/simple-modal.component';
20 | import { TooltipComponent } from './host-components/tooltip/tooltip.component';
21 | import { TestComponent } from './test/test.component';
22 | import { ContentComponent } from './utils/content/content.component';
23 | import { ScrollSpyDirective } from './utils/scollspy.directive';
24 | import { SectionComponent } from './utils/section/section.component';
25 | import { SubSectionComponent } from './utils/sub-section/sub-section.component';
26 |
27 | @NgModule({
28 | declarations: [
29 | AppComponent,
30 | TestComponent,
31 | SectionComponent,
32 | SubSectionComponent,
33 | RelativePositionExampleComponent,
34 | TooltipComponent,
35 | SimpleModalComponent,
36 | SimpleListComponent,
37 | GlobalPositionExampleComponent,
38 | SlidePositionExampleComponent,
39 | FullscreenPositionExampleComponent,
40 | DragExampleComponent,
41 | HeroScreenComponent,
42 | ModalExampleComponent,
43 | ContentComponent,
44 | DynamicTextExampleComponent,
45 | DropdownExampleComponent,
46 | RibbonExampleComponent,
47 | ControlExampleComponent,
48 | ScrollSpyDirective
49 | ],
50 | imports: [BrowserModule, FormsModule, HttpClientModule, ToppyModule],
51 | providers: [],
52 | entryComponents: [TestComponent, TooltipComponent, SimpleModalComponent, SimpleListComponent, HeroScreenComponent],
53 | bootstrap: [AppComponent],
54 | exports: []
55 | })
56 | export class AppModule {}
57 |
--------------------------------------------------------------------------------
/docs/app/codes.ts:
--------------------------------------------------------------------------------
1 | const code: any = {};
2 |
3 | code.NPM_INSTALL = `> npm install toppy --save //or
4 | > yarn add toppy
5 | `;
6 |
7 | code.INSTALL = `const position = new GlobalPosition();
8 | const ref = this.toppy.overlay(position).host().create();
9 | ref.open(); // use it anywhere`;
10 |
11 | export { code };
12 |
--------------------------------------------------------------------------------
/docs/app/examples/control-example/control-example.component.html:
--------------------------------------------------------------------------------
1 | open dropdown
2 |
--------------------------------------------------------------------------------
/docs/app/examples/control-example/control-example.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/app/examples/control-example/control-example.component.scss
--------------------------------------------------------------------------------
/docs/app/examples/control-example/control-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { Toppy } from '../../../../projects/toppy/src/lib/toppy';
3 |
4 | @Component({
5 | selector: 'app-control-example',
6 | templateUrl: './control-example.component.html',
7 | styleUrls: ['./control-example.component.scss']
8 | })
9 | export class ControlExampleComponent implements OnInit {
10 | constructor(private toppy: Toppy) {}
11 |
12 | ngOnInit() {}
13 | open() {
14 | this.toppy.getCtrl('sonia').open();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docs/app/examples/drag-example/drag-example.component.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 |
18 |
19 |
20 | Reset
21 |
22 |
--------------------------------------------------------------------------------
/docs/app/examples/drag-example/drag-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { Subject } from 'rxjs';
3 | import { OutsidePlacement } from '../../../../projects/toppy/src/lib/models';
4 | import { RelativePosition, Toppy, ToppyControl } from '../../../../projects/toppy/src/public_api';
5 |
6 | @Component({
7 | selector: 'app-drag-example',
8 | templateUrl: './drag-example.component.html'
9 | })
10 | export class DragExampleComponent implements OnInit {
11 | pos1 = 0;
12 | pos2 = 0;
13 | pos3 = 0;
14 | pos4 = 0;
15 | @ViewChild('el') el: ElementRef;
16 | private _toppyControl: ToppyControl;
17 | pauser = new Subject();
18 | constructor(private toppy: Toppy) {}
19 |
20 | ngOnInit() {
21 | this._toppyControl = this.toppy
22 | .position(
23 | new RelativePosition({
24 | placement: OutsidePlacement.TOP,
25 | src: this.el.nativeElement,
26 | width: 'auto',
27 | autoUpdate: true
28 | })
29 | )
30 | .content('Drag me', { class: 'tooltip' })
31 | .create();
32 | }
33 |
34 | ngAfterViewInit() {
35 | this.dragElement();
36 | }
37 | reset() {
38 | this.el.nativeElement.style.left = '0px';
39 | this.el.nativeElement.style.top = '0px';
40 | }
41 | onMouseOver() {
42 | this._toppyControl.open();
43 | }
44 | onMouseLeave() {
45 | this._toppyControl.close();
46 | }
47 | dragMouseDown(e) {
48 | e = e || window.event;
49 | e.preventDefault();
50 | // get the mouse cursor position at startup:
51 | this.pos3 = e.clientX;
52 | this.pos4 = e.clientY;
53 | document.onmouseup = this.closeDragElement.bind(this);
54 | // call a function whenever the cursor moves:
55 | document.onmousemove = this.elementDrag.bind(this);
56 | }
57 |
58 | elementDrag(e) {
59 | e = e || window.event;
60 | e.preventDefault();
61 | // calculate the new cursor position:
62 | this.pos1 = this.pos3 - e.clientX;
63 | this.pos2 = this.pos4 - e.clientY;
64 | this.pos3 = e.clientX;
65 | this.pos4 = e.clientY;
66 | this.el.nativeElement.style.top = this.el.nativeElement.offsetTop - this.pos2 + 'px';
67 | this.el.nativeElement.style.left = this.el.nativeElement.offsetLeft - this.pos1 + 'px';
68 | }
69 |
70 | closeDragElement() {
71 | document.onmouseup = null;
72 | document.onmousemove = null;
73 | }
74 |
75 | dragElement() {
76 | this.el.nativeElement.onmousedown = this.dragMouseDown.bind(this);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/docs/app/examples/dropdown-example/dropdown-example.component.html:
--------------------------------------------------------------------------------
1 |
2 |
{{ selectedData.name }}
3 |
4 |
5 |
6 | I like {{ selectedEatable.name }}
7 |
8 |
9 |
10 |
11 |
12 | {{ item.name }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/docs/app/examples/dropdown-example/dropdown-example.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/app/examples/dropdown-example/dropdown-example.component.scss
--------------------------------------------------------------------------------
/docs/app/examples/dropdown-example/dropdown-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, TemplateRef, ViewChild } from '@angular/core';
2 | import { OutsidePlacement } from '../../../../projects/toppy/src/lib/models';
3 | import { RelativePosition, Toppy, ToppyControl } from '../../../../projects/toppy/src/public_api';
4 |
5 | @Component({
6 | selector: 'app-dropdown-example',
7 | templateUrl: './dropdown-example.component.html',
8 | styleUrls: ['./dropdown-example.component.scss']
9 | })
10 | export class DropdownExampleComponent implements OnInit {
11 | @ViewChild('el') el: ElementRef;
12 | @ViewChild('el2') el2: ElementRef;
13 | private _toppyControl: ToppyControl;
14 | private _toppyControl2: ToppyControl;
15 | @ViewChild('tpl', { read: TemplateRef }) tpl: TemplateRef;
16 | @ViewChild('tpl2', { read: TemplateRef }) tpl2: TemplateRef;
17 | items = [
18 | { name: 'Beer', icon: 'icons8-beer-50' },
19 | { name: 'Coffee', icon: 'icons8-cafe-50' },
20 | { name: 'Cocktail', icon: 'icons8-cocktail-50' },
21 | { name: 'Cola', icon: 'icons8-cola-50' },
22 | { name: 'Tequila', icon: 'icons8-tequila-shot-50' },
23 | { name: 'Whiskey', icon: 'icons8-whiskey-50' }
24 | ];
25 | eatables = [
26 | { name: 'French fries', icon: 'icons8-french-fries-50' },
27 | { name: 'Fried chicken', icon: 'icons8-fried-chicken-50' },
28 | { name: 'Hamburger', icon: 'icons8-hamburger-50' },
29 | { name: 'Pizza', icon: 'icons8-pizza-50' },
30 | { name: 'Sandwich', icon: 'icons8-sandwich-50' }
31 | ];
32 | selectedData;
33 | selectedEatable;
34 | isOpen = false;
35 | constructor(private toppy: Toppy) {
36 | this.selectedData = this.items[0];
37 | this.selectedEatable = this.eatables[0];
38 | }
39 |
40 | ngOnInit() {
41 | this._toppyControl = this.toppy
42 | .position(
43 | new RelativePosition({
44 | placement: OutsidePlacement.BOTTOM,
45 | src: this.el.nativeElement,
46 | width: '100%',
47 | autoUpdate: true
48 | })
49 | )
50 | .config({
51 | closeOnDocClick: true,
52 | docClickCallback: () => {
53 | this.isOpen = false;
54 | }
55 | })
56 | .content(this.tpl)
57 | .create('sonia');
58 |
59 | this._toppyControl2 = this.toppy
60 | .position(
61 | new RelativePosition({
62 | placement: OutsidePlacement.TOP,
63 | src: this.el2.nativeElement,
64 | width: 'auto',
65 | autoUpdate: true
66 | })
67 | )
68 | .config({
69 | docClickCallback: () => {
70 | this.isOpen = false;
71 | }
72 | })
73 | .content(this.tpl2)
74 | .create();
75 | }
76 |
77 | open() {
78 | this.isOpen = true;
79 | this._toppyControl.open();
80 | }
81 | open2() {
82 | this._toppyControl2.open();
83 | }
84 | close() {
85 | this.isOpen = false;
86 | this._toppyControl.close();
87 | }
88 | close2() {
89 | this._toppyControl2.close();
90 | }
91 | select(item) {
92 | this.selectedData = item;
93 | this.close();
94 | }
95 | selectEatable(item) {
96 | this.selectedEatable = item;
97 | this.close2();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/docs/app/examples/dynamic-text-example/dynamic-text-example.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docs/app/examples/dynamic-text-example/dynamic-text-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import * as format from 'date-fns/format';
3 | import { never, Observable, Subject, timer } from 'rxjs';
4 | import { map, switchMap, timeInterval } from 'rxjs/operators';
5 | import { OutsidePlacement } from '../../../../projects/toppy/src/lib/models';
6 | import { RelativePosition, Toppy, ToppyControl } from '../../../../projects/toppy/src/public_api';
7 |
8 | @Component({
9 | selector: 'app-dynamic-text-example',
10 | templateUrl: './dynamic-text-example.component.html'
11 | })
12 | export class DynamicTextExampleComponent implements OnInit {
13 | @ViewChild('el') el: ElementRef;
14 | private _toppyControl: ToppyControl;
15 | pauser = new Subject();
16 | constructor(private toppy: Toppy) {
17 | this.pauser.pipe(switchMap(paused => (paused ? never() : this.source()))).subscribe(x => console.log(x));
18 | }
19 |
20 | source(): Observable {
21 | return new Observable(observer => {
22 | timer(0, 100)
23 | .pipe(
24 | timeInterval(),
25 | map(() => this._toppyControl.updateTextContent.next(this.formatedTime()))
26 | )
27 | .subscribe();
28 | });
29 | }
30 |
31 | formatedTime() {
32 | return format(new Date(), 'HH:mm:ss A');
33 | }
34 |
35 | ngOnInit() {
36 | this._toppyControl = this.toppy
37 | .position(
38 | new RelativePosition({
39 | placement: OutsidePlacement.RIGHT,
40 | src: this.el.nativeElement,
41 | width: 'auto',
42 | autoUpdate: true
43 | })
44 | )
45 | .content(this.formatedTime(), { class: 'tooltip' })
46 | .create();
47 | }
48 |
49 | onMouseOver() {
50 | this._toppyControl.open();
51 | this.pauser.next(false);
52 | }
53 | onMouseLeave() {
54 | this._toppyControl.close();
55 | this.pauser.next(true);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/docs/app/examples/fullscreen-position-example/fullscreen-position-example.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Open fullscreen demo
3 |
4 |
--------------------------------------------------------------------------------
/docs/app/examples/fullscreen-position-example/fullscreen-position-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { FullscreenPosition, Toppy, ToppyControl } from 'toppy';
3 | import { HeroScreenComponent } from '../../host-components/hero-screen/hero-screen.component';
4 |
5 | @Component({
6 | selector: 'app-fullscreen-position-example',
7 | templateUrl: './fullscreen-position-example.component.html'
8 | })
9 | export class FullscreenPositionExampleComponent implements OnInit {
10 | private _toppyControl: ToppyControl;
11 | constructor(private toppy: Toppy) {}
12 |
13 | ngOnInit() {
14 | this._toppyControl = this.toppy
15 | .position(new FullscreenPosition())
16 | .config({
17 | closeOnEsc: true
18 | })
19 | .content(HeroScreenComponent)
20 | .create();
21 | this._toppyControl.listen('t_compins').subscribe(d => {
22 | console.log('HeroScreenComponent initiated', d);
23 | });
24 | }
25 |
26 | open() {
27 | this._toppyControl.open();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/docs/app/examples/global-position-example/global-position-example.component.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
11 |
18 |
19 | {{ placement.name }}
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/app/examples/global-position-example/global-position-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewEncapsulation } from '@angular/core';
2 | import { GlobalPosition, InsidePlacement, Toppy, ToppyControl } from 'toppy';
3 | import { SimpleModalComponent } from '../../host-components/simple-modal/simple-modal.component';
4 |
5 | @Component({
6 | selector: 'app-global-position-example',
7 | templateUrl: './global-position-example.component.html',
8 | encapsulation: ViewEncapsulation.None,
9 | styles: [
10 | `
11 | .global-content-wrapper {
12 | background: #e91e63;
13 | padding: 1rem 2rem;
14 | border: 2px solid #cc1a57;
15 | border-radius: 3px;
16 | color: #fff;
17 | font-weight: 500;
18 | }
19 | `
20 | ]
21 | })
22 | export class GlobalPositionExampleComponent implements OnInit {
23 | placements: { name: string; value: InsidePlacement }[] = [
24 | { name: 'Bottom', value: InsidePlacement.BOTTOM },
25 | { name: 'Bottom left', value: InsidePlacement.BOTTOM_LEFT },
26 | { name: 'Bottom right', value: InsidePlacement.BOTTOM_RIGHT },
27 | { name: 'Left', value: InsidePlacement.LEFT },
28 | { name: 'Right', value: InsidePlacement.RIGHT },
29 | { name: 'Top', value: InsidePlacement.TOP },
30 | { name: 'Top left', value: InsidePlacement.TOP_LEFT },
31 | { name: 'Top right', value: InsidePlacement.TOP_RIGHT },
32 | { name: 'Center', value: InsidePlacement.CENTER }
33 | ];
34 | selectedPlacement = this.placements[8].value;
35 | private _toppyControl: ToppyControl;
36 | constructor(private toppy: Toppy) {}
37 |
38 | ngOnInit() {
39 | this._toppyControl = this.toppy
40 | .position(new GlobalPosition({ placement: this.selectedPlacement, height: 'auto', width: 'auto', offset: 10 }))
41 | .config({
42 | docClickCallback: () => {
43 | console.log('doc click callback');
44 | },
45 | closeOnDocClick: true,
46 | wrapperClass: 'global-content-wrapper',
47 | backdrop: true,
48 | bodyClass: 'global-toastr'
49 | })
50 | .content(SimpleModalComponent)
51 | .create();
52 | }
53 |
54 | open() {
55 | const content = this.placements.find(a => a.value === this.selectedPlacement).name;
56 | this._toppyControl.updateContent(content);
57 | this._toppyControl.open();
58 | }
59 |
60 | onOptionChange() {
61 | this._toppyControl.updatePosition({
62 | placement: this.selectedPlacement
63 | });
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/docs/app/examples/modal-example/modal-example.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Wow, You made it!
15 |
16 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/docs/app/examples/modal-example/modal-example.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/app/examples/modal-example/modal-example.component.scss
--------------------------------------------------------------------------------
/docs/app/examples/modal-example/modal-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
2 | import { GlobalPosition, InsidePlacement, Toppy, ToppyControl } from 'toppy';
3 |
4 | @Component({
5 | selector: 'app-modal-example',
6 | templateUrl: './modal-example.component.html',
7 | styleUrls: ['./modal-example.component.scss']
8 | })
9 | export class ModalExampleComponent implements OnInit {
10 | _toppyControl: ToppyControl;
11 | _toppyControl2: ToppyControl;
12 | @ViewChild('modalTpl', { read: TemplateRef }) modalTpl: TemplateRef;
13 |
14 | constructor(private toppy: Toppy) {}
15 |
16 | ngOnInit() {
17 | this._toppyControl = this.toppy
18 | .position(
19 | new GlobalPosition({
20 | placement: InsidePlacement.CENTER,
21 | width: 300,
22 | height: 'auto'
23 | })
24 | )
25 | .config({
26 | backdrop: true,
27 | closeOnDocClick: false,
28 | closeOnEsc: true
29 | })
30 | .content(this.modalTpl)
31 | .create();
32 |
33 | this._toppyControl2 = this.toppy
34 | .position(
35 | new GlobalPosition({
36 | placement: InsidePlacement.CENTER,
37 | width: 'auto',
38 | height: 'auto'
39 | })
40 | )
41 | .config({
42 | closeOnEsc: true,
43 | closeOnDocClick: true
44 | })
45 | .content(' ', { hasHTML: true })
46 | .create();
47 | }
48 | open() {
49 | this._toppyControl.open();
50 | }
51 | openImage() {
52 | this._toppyControl2.open();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/docs/app/examples/relative-position-example/relative-position-example.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | I am a target element
4 | Hover me
5 |
6 |
7 |
8 |
9 |
10 |
14 |
22 |
23 |
24 | {{ placement.name }}
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/docs/app/examples/relative-position-example/relative-position-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { Subject } from 'rxjs';
3 | import { OutsidePlacement, RelativePosition, Toppy } from 'toppy';
4 | import { ToppyControl } from '../../../../projects/toppy/src/lib/toppy-control';
5 |
6 | @Component({
7 | selector: 'app-relative-position-example',
8 | templateUrl: './relative-position-example.component.html',
9 | styles: [],
10 | providers: [Toppy]
11 | })
12 | export class RelativePositionExampleComponent implements OnInit {
13 | @ViewChild('targetEl', { read: ElementRef })
14 | targetEl: ElementRef;
15 |
16 | placements: { name: string; value: OutsidePlacement }[] = [
17 | { name: 'Bottom', value: OutsidePlacement.BOTTOM },
18 | { name: 'Bottom left', value: OutsidePlacement.BOTTOM_LEFT },
19 | { name: 'Bottom right', value: OutsidePlacement.BOTTOM_RIGHT },
20 | { name: 'Left', value: OutsidePlacement.LEFT },
21 | { name: 'Left bottom', value: OutsidePlacement.LEFT_BOTTOM },
22 | { name: 'Left top', value: OutsidePlacement.LEFT_TOP },
23 | { name: 'Right', value: OutsidePlacement.RIGHT },
24 | { name: 'Right bottom', value: OutsidePlacement.RIGHT_BOTTOM },
25 | { name: 'Right top', value: OutsidePlacement.RIGHT_TOP },
26 | { name: 'Top', value: OutsidePlacement.TOP },
27 | { name: 'Top left', value: OutsidePlacement.TOP_LEFT },
28 | { name: 'Top right', value: OutsidePlacement.TOP_RIGHT }
29 | ];
30 | selectedPlacement = this.placements[0].value;
31 | private _toppyControl: ToppyControl;
32 | destroy$ = new Subject();
33 | constructor(private toppy: Toppy) {}
34 |
35 | ngOnInit() {
36 | this._toppyControl = this.toppy
37 | .position(
38 | new RelativePosition({
39 | placement: this.selectedPlacement,
40 | src: this.targetEl.nativeElement,
41 | autoUpdate: true
42 | })
43 | )
44 | .content('hello')
45 | .create();
46 | }
47 |
48 | onOptionChange() {
49 | this._toppyControl.updatePosition({
50 | placement: this.selectedPlacement
51 | });
52 | }
53 | onMouseOver() {
54 | const content = this.placements.find(a => a.value === this.selectedPlacement).name;
55 | this._toppyControl.updateContent(content, { class: 'tooltip' });
56 | this._toppyControl.open();
57 | }
58 | onMouseLeave() {
59 | this._toppyControl.close();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/docs/app/examples/ribbon-example/ribbon-example.component.html:
--------------------------------------------------------------------------------
1 | Open ribbon
2 |
3 |
4 |
5 |
6 |
7 |
8 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Consectetur natus, esse amet nisi laboriosam omnis
9 | tenetur accusantium vero at totam ducimus itaque soluta adipisci mollitia expedita dolores quaerat ratione
10 | iure?
11 |
12 |
Close
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docs/app/examples/ribbon-example/ribbon-example.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/app/examples/ribbon-example/ribbon-example.component.scss
--------------------------------------------------------------------------------
/docs/app/examples/ribbon-example/ribbon-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
2 | import { InsidePlacement } from '../../../../projects/toppy/src/lib/models';
3 | import { GlobalPosition, Toppy, ToppyControl } from '../../../../projects/toppy/src/public_api';
4 |
5 | @Component({
6 | selector: 'app-ribbon-example',
7 | templateUrl: './ribbon-example.component.html',
8 | styleUrls: ['./ribbon-example.component.scss']
9 | })
10 | export class RibbonExampleComponent implements OnInit {
11 | private _toppyControl: ToppyControl;
12 | @ViewChild('tpl', { read: TemplateRef }) tpl: TemplateRef;
13 | constructor(private toppy: Toppy) {}
14 |
15 | ngOnInit() {
16 | this._toppyControl = this.toppy
17 | .position(
18 | new GlobalPosition({
19 | placement: InsidePlacement.BOTTOM,
20 | width: '100%',
21 | height: 'auto'
22 | })
23 | )
24 | .config({
25 | closeOnDocClick: false
26 | })
27 | .content(this.tpl)
28 | .create();
29 | }
30 | open() {
31 | this._toppyControl.open();
32 | }
33 | close() {
34 | this._toppyControl.close();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/docs/app/examples/slide-position-example/slide-position-example.component.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
11 |
18 |
19 | {{ placement.name }}
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/app/examples/slide-position-example/slide-position-example.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { SlidePlacement, SlidePosition, Toppy, ToppyControl } from 'toppy';
3 | import { SimpleListComponent } from '../../host-components/simple-list/simple-list.component';
4 |
5 | @Component({
6 | selector: 'app-slide-position-example',
7 | templateUrl: './slide-position-example.component.html',
8 | styles: []
9 | })
10 | export class SlidePositionExampleComponent implements OnInit {
11 | placements: { name: string; value: SlidePlacement }[] = [
12 | { name: 'Left', value: SlidePlacement.LEFT },
13 | { name: 'Right', value: SlidePlacement.RIGHT }
14 | ];
15 | selectedPlacement = this.placements[0].value;
16 | private _toppyControl: ToppyControl;
17 | constructor(private toppy: Toppy) {}
18 |
19 | ngOnInit() {}
20 |
21 | open() {
22 | if (this._toppyControl) {
23 | this._toppyControl.close();
24 | }
25 | this._toppyControl = this.toppy
26 | .position(new SlidePosition({ placement: this.selectedPlacement }))
27 | .config({
28 | closeOnDocClick: true
29 | })
30 | .content(SimpleListComponent)
31 | .create();
32 | this._toppyControl.open();
33 | }
34 |
35 | onOptionChange() {
36 | console.log('option changed');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/docs/app/host-components/hero-screen/hero-screen.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Hello, Its fullscreen overlay
4 |
5 | It occupies complete screen width and height. Please click ESCAPE key or click close button to close the overlay
6 |
7 |
8 | Close
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/app/host-components/hero-screen/hero-screen.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-hero-screen',
5 | templateUrl: './hero-screen.component.html',
6 | styles: []
7 | })
8 | export class HeroScreenComponent {
9 | close;
10 | dispose() {
11 | this.close();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/docs/app/host-components/simple-list/simple-list.component.html:
--------------------------------------------------------------------------------
1 |
Slide example
2 |
--------------------------------------------------------------------------------
/docs/app/host-components/simple-list/simple-list.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-simple-list',
5 | templateUrl: './simple-list.component.html',
6 | styles: []
7 | })
8 | export class SimpleListComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/docs/app/host-components/simple-modal/simple-modal.component.html:
--------------------------------------------------------------------------------
1 |
2 | Globally positioned!
3 |
--------------------------------------------------------------------------------
/docs/app/host-components/simple-modal/simple-modal.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-simple-modal',
5 | templateUrl: './simple-modal.component.html',
6 | styles: []
7 | })
8 | export class SimpleModalComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/docs/app/host-components/tooltip/tooltip.component.html:
--------------------------------------------------------------------------------
1 |
2 | tooltip works!
3 |
--------------------------------------------------------------------------------
/docs/app/host-components/tooltip/tooltip.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-tooltip',
5 | templateUrl: './tooltip.component.html',
6 | styles: []
7 | })
8 | export class TooltipComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/docs/app/test/test.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Hello Everyone!
3 |
close
4 |
5 |
--------------------------------------------------------------------------------
/docs/app/test/test.component.scss:
--------------------------------------------------------------------------------
1 | .box {
2 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji',
3 | 'Segoe UI Emoji', 'Segoe UI Symbol';
4 | background: #e91e63;
5 | padding: 5px;
6 | border-radius: 3px;
7 | font-size: 14px;
8 | margin-top: 0.2rem;
9 | color: #fff;
10 | }
11 |
12 | p {
13 | margin: 0;
14 | font-weight: 500;
15 | margin-bottom: 10px;
16 | }
17 |
--------------------------------------------------------------------------------
/docs/app/test/test.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { TestComponent } from './test.component';
4 |
5 | describe('TestComponent', () => {
6 | let component: TestComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ TestComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(TestComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/docs/app/test/test.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-test',
5 | templateUrl: './test.component.html',
6 | styleUrls: ['./test.component.scss']
7 | })
8 | export class TestComponent implements OnInit {
9 | close;
10 | constructor() {}
11 |
12 | ngOnInit() {}
13 | dismiss() {
14 | this.close();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docs/app/utils/content/content.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/app/utils/content/content.component.scss
--------------------------------------------------------------------------------
/docs/app/utils/content/content.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-content',
5 | templateUrl: './content.component.html'
6 | })
7 | export class ContentComponent implements OnInit {
8 | constructor() {}
9 |
10 | ngOnInit() {}
11 | }
12 |
--------------------------------------------------------------------------------
/docs/app/utils/scollspy.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[scrollSpy]'
5 | })
6 | export class ScrollSpyDirective {
7 | @Input() public spiedTags = [];
8 | @Output() public sectionChange = new EventEmitter();
9 | private currentSection: string;
10 |
11 | constructor(private _el: ElementRef) {}
12 |
13 | @HostListener('window:scroll', ['$event'])
14 | onScroll(event: any) {
15 | let currentSection: string;
16 | const children = document.querySelectorAll('h3');
17 | const scrollTop = document.documentElement.scrollTop;
18 | const parentOffset = document.documentElement.offsetTop;
19 | for (let i = 0; i < children.length; i++) {
20 | const element = children[i];
21 | if (this.spiedTags.some(spiedTag => spiedTag === element.tagName)) {
22 | if (element.offsetTop - parentOffset <= scrollTop) {
23 | currentSection = element.id;
24 | }
25 | }
26 | }
27 | if (currentSection !== this.currentSection) {
28 | this.currentSection = currentSection;
29 | this.sectionChange.emit(this.currentSection);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/docs/app/utils/section/section.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{ heading }}
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/app/utils/section/section.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-section',
5 | templateUrl: './section.component.html'
6 | })
7 | export class SectionComponent implements OnInit {
8 | @Input()
9 | heading = '';
10 | @Input()
11 | icon = '';
12 | constructor() {}
13 |
14 | ngOnInit() {}
15 | }
16 |
--------------------------------------------------------------------------------
/docs/app/utils/sub-section/sub-section.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{ heading }}
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/app/utils/sub-section/sub-section.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-sub-section',
5 | templateUrl: './sub-section.component.html',
6 | styles: []
7 | })
8 | export class SubSectionComponent implements OnInit {
9 | @Input()
10 | heading;
11 | constructor() {}
12 |
13 | ngOnInit() {}
14 | }
15 |
--------------------------------------------------------------------------------
/docs/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/.gitkeep
--------------------------------------------------------------------------------
/docs/assets/archived-versions.json:
--------------------------------------------------------------------------------
1 | {"undefined":1541115139547,"1.0.11":1541115874348,"1.0.12":1541117479211,"1.0.13":1541118084059,"1.0.14":1541236752420,"1.0.15":1541524275096,"1.0.16":1541786515110,"1.0.17":1542127897095,"1.0.18":1542339601683,"1.1.0":1542548397540,"1.1.1":1542860347098,"1.2.0":1543048207817,"1.2.2":1543389399932,"1.2.3":1543405671424,"1.2.4":1543409608479,"1.3.0":1543944610263,"1.3.1":1543996147918,"2.0.0":1544793410445,"2.0.1":1544794243418,"2.0.2":1544841561628,"2.0.3":1544845267568,"2.0.4":1545292006287,"2.0.5":1545654967450,"2.1.0":1545763951127,"2.2.0":1546233019376,"2.3.0":1546714578991,"2.3.1":1549813301631,"2.3.2":1549952769013,"2.3.3":1552500395017,"2.3.4":1564588293511}
2 |
--------------------------------------------------------------------------------
/docs/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon.png
--------------------------------------------------------------------------------
/docs/assets/favicon/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/android-chrome-192x192.png
--------------------------------------------------------------------------------
/docs/assets/favicon/android-chrome-256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/android-chrome-256x256.png
--------------------------------------------------------------------------------
/docs/assets/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/docs/assets/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/assets/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/assets/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/favicon.ico
--------------------------------------------------------------------------------
/docs/assets/favicon/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/mstile-150x150.png
--------------------------------------------------------------------------------
/docs/assets/favicon/og-image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/favicon/og-image.jpg
--------------------------------------------------------------------------------
/docs/assets/favicon/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.11, written by Peter Selinger 2001-2013
9 |
10 |
12 |
17 |
21 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-beer-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-beer-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-cafe-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-cafe-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-cocktail-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-cocktail-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-cola-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-cola-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-comments-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-comments-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-confetti-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-confetti-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-dynamite-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-dynamite-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-explosive-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-explosive-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-firework-explosion-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-firework-explosion-100.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-french-fries-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-french-fries-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-fried-chicken-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-fried-chicken-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-hamburger-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-hamburger-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-orange-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-orange-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-pears-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-pears-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-pizza-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-pizza-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-sandwich-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-sandwich-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-scooter-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-scooter-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-sweet-banana-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-sweet-banana-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-tequila-shot-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-tequila-shot-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-watch-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-watch-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-watermelon-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-watermelon-50.png
--------------------------------------------------------------------------------
/docs/assets/icons/icons8-whiskey-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/icons/icons8-whiskey-50.png
--------------------------------------------------------------------------------
/docs/assets/img/blast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/blast.png
--------------------------------------------------------------------------------
/docs/assets/img/bomb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/bomb.png
--------------------------------------------------------------------------------
/docs/assets/img/clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/clock.png
--------------------------------------------------------------------------------
/docs/assets/img/cow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/cow.png
--------------------------------------------------------------------------------
/docs/assets/img/five.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/five.png
--------------------------------------------------------------------------------
/docs/assets/img/fly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/fly.png
--------------------------------------------------------------------------------
/docs/assets/img/four.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/four.png
--------------------------------------------------------------------------------
/docs/assets/img/goat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/goat.png
--------------------------------------------------------------------------------
/docs/assets/img/mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/mail.png
--------------------------------------------------------------------------------
/docs/assets/img/one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/one.png
--------------------------------------------------------------------------------
/docs/assets/img/snake.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/snake.png
--------------------------------------------------------------------------------
/docs/assets/img/three.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/three.png
--------------------------------------------------------------------------------
/docs/assets/img/two.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/img/two.png
--------------------------------------------------------------------------------
/docs/assets/lo-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/lo-logo.png
--------------------------------------------------------------------------------
/docs/assets/toppy-favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/toppy-favicon.png
--------------------------------------------------------------------------------
/docs/assets/toppy-logo-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/toppy-logo-white.png
--------------------------------------------------------------------------------
/docs/assets/toppy-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/assets/toppy-logo.png
--------------------------------------------------------------------------------
/docs/browserslist:
--------------------------------------------------------------------------------
1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 | #
5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
6 |
7 | > 0.5%
8 | last 2 versions
9 | Firefox ESR
10 | not dead
11 | not IE 9-11
--------------------------------------------------------------------------------
/docs/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/docs/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/docs/environments/version.ts:
--------------------------------------------------------------------------------
1 | export const TOPPY_VERSION='2.3.4'
2 |
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Toppy - Overlay library for Angular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/docs/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 | };
--------------------------------------------------------------------------------
/docs/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
14 |
--------------------------------------------------------------------------------
/docs/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/weak-map';
35 | // import 'core-js/es6/set';
36 |
37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
38 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
39 |
40 | /** IE10 and IE11 requires the following for the Reflect API. */
41 | // import 'core-js/es6/reflect';
42 |
43 |
44 | /** Evergreen browsers require these. **/
45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
46 |
47 |
48 |
49 | /**
50 | * Web Animations `@angular/platform-browser/animations`
51 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
52 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
53 | **/
54 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
55 |
56 | /**
57 | * By default, zone.js will patch all possible macroTask and DomEvents
58 | * user can disable parts of macroTask/DomEvents patch by setting following flags
59 | */
60 |
61 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
62 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
63 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
64 |
65 | /*
66 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
67 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
68 | */
69 | // (window as any).__Zone_enable_cross_context_check = true;
70 |
71 | /***************************************************************************************************
72 | * Zone JS is required by default for Angular itself.
73 | */
74 | import 'zone.js/dist/zone'; // Included with Angular CLI.
75 |
76 |
77 |
78 | /***************************************************************************************************
79 | * APPLICATION IMPORTS
80 | */
81 |
--------------------------------------------------------------------------------
/docs/styles/_common.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable scss/at-import-no-partial-leading-underscore */
2 | @import './config';
3 | @import './helpers/_index';
4 | @import './themes/_index';
5 |
--------------------------------------------------------------------------------
/docs/styles/_config.scss:
--------------------------------------------------------------------------------
1 | $toppy--base-font-size: 13px;
2 | $toppy--base-font-size-xl: 16px;
3 | $toppy--app-name: 'TOPPY';
4 | $toppy--debug: false;
5 | $toppy--font-family: 'Rubik', acumin-pro, 'Inconsolata', 'Inter UI', 'Nunito Sans';
6 | $toppy--font-family-headings: 'acumin-pro';
7 | $toppy--font-family-monospace: 'Roboto mono', 'calling-code', 'Courier New', 'Lucida Console', Monaco, Courier,
8 | monospace;
9 |
10 | $toppy--colors: (
11 | 'bg': #fafafa,
12 | 'text': #88889a,
13 | 'heading': #9590d4,
14 | 'border': #e9edff,
15 | 'dark': #585c6d,
16 | 'shadow': #dddde9,
17 | 'primary': #3F51B5,
18 | 'secondary': #ef8fb7,
19 | 'success': #3fc782,
20 | 'warning': #f78f1e,
21 | 'danger': #e3505a,
22 | 'info': #03a9f4,
23 | 'yellow': #cabcb1,
24 | 'alt': #3F51B5
25 | );
26 |
27 | $toppy--font-sizes: (
28 | 'sm': 0.9rem,
29 | 'md': 1rem,
30 | 'lg': 1.4rem,
31 | 'xl': 4rem,
32 | 'h1': 3.2rem,
33 | 'h2': 2rem,
34 | 'h3': 1.75rem,
35 | 'h4': 1.5rem,
36 | 'h5': 1.25rem,
37 | 'h6': 1rem
38 | );
39 |
40 | $toppy--border-rad: 3px;
41 | $toppy--icons-font: 'toppy';
42 | $toppy--icon-font-path: './icons';
43 |
44 | $toppy--grid-breakpoints: (
45 | xs: 0,
46 | sm: 576px,
47 | md: 768px,
48 | lg: 992px,
49 | xl: 1600px
50 | );
51 |
--------------------------------------------------------------------------------
/docs/styles/animations/__index.scss:
--------------------------------------------------------------------------------
1 | @import './slide_in';
2 |
--------------------------------------------------------------------------------
/docs/styles/animations/_slide_in.scss:
--------------------------------------------------------------------------------
1 | /* ----------------------------------------------
2 | .slide-in-left {
3 | animation: slide-in-left 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
4 | }
5 | ---------------------------------------------- */
6 |
7 | @keyframes slide-in-left {
8 | 0% {
9 | opacity: 0;
10 | transform: translateX(-10px);
11 | }
12 |
13 | 100% {
14 | opacity: 1;
15 | transform: translateX(0);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/docs/styles/base/__index.scss:
--------------------------------------------------------------------------------
1 | @import './fonts';
2 | @import './icons';
3 | @import './reset';
4 | @import './typography';
5 | @import './utility';
6 | @import './input';
7 | @import './buttons';
8 | @import './pre';
9 |
--------------------------------------------------------------------------------
/docs/styles/base/_buttons.scss:
--------------------------------------------------------------------------------
1 | button.btn.-is-plain {
2 | background-color: transparent;
3 | border-color: transparent;
4 | }
5 |
6 | button.btn.-is-compact {
7 | padding: 0;
8 | }
9 |
--------------------------------------------------------------------------------
/docs/styles/base/_fonts.scss:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,500,700');
2 | @import url('https://use.typekit.net/uur7gsm.css');
3 | @import url('https://fonts.googleapis.com/css?family=Rubik:300,400,500,700');
4 |
--------------------------------------------------------------------------------
/docs/styles/base/_icons.scss:
--------------------------------------------------------------------------------
1 | $icons: (
2 | alert-circle: '\e902',
3 | alert-triangle: '\e904',
4 | arrow-left: '\e910',
5 | arrow-right: '\e912',
6 | check-circle: '\e92c',
7 | copy: '\e944',
8 | edit: '\e958',
9 | external-link: '\e95b',
10 | file: '\e964',
11 | filter: '\e966',
12 | github: '\e970',
13 | hash: '\e975',
14 | heart: '\e977',
15 | help: '\e978',
16 | home: '\e979',
17 | link: '\e982',
18 | loader: '\e986',
19 | maximize-2: '\e98e',
20 | menu: '\e98f',
21 | minimize-2: '\e995',
22 | more-horizontal: '\e99b',
23 | navigation: '\e9a0',
24 | plus-circle: '\e9b2',
25 | radio: '\e9b7',
26 | repeat: '\e9ba',
27 | rss: '\e9be',
28 | settings: '\e9c4',
29 | share-2: '\e9c6',
30 | sliders: '\e9d1',
31 | tag: '\e9db',
32 | terminal: '\e9dd',
33 | twitter: '\e9ea',
34 | users: '\e9f6',
35 | x: '\ea02',
36 | x-circle: '\ea03',
37 | zap: '\ea06'
38 | );
39 |
40 | @font-face {
41 | font-family: 'toppy';
42 | font-style: normal;
43 | font-weight: normal;
44 | src: url('#{$toppy--icon-font-path}/toppy.ttf?olqd7c') format('truetype'),
45 | url('#{$toppy--icon-font-path}/toppy.woff?olqd7c') format('woff'),
46 | url('#{$toppy--icon-font-path}/toppy.svg?olqd7c#choosy') format('svg');
47 | }
48 |
49 | .toppy-icon {
50 | /* use !important to prevent issues with browser extensions that change fonts */
51 | font-family: $toppy--icons-font !important;
52 |
53 | /* Better Font Rendering =========== */
54 | -webkit-font-smoothing: antialiased;
55 | font-style: normal;
56 | font-variant: normal;
57 | font-weight: normal;
58 | line-height: 1;
59 | -moz-osx-font-smoothing: grayscale;
60 | speak: none;
61 | text-transform: none;
62 | font-size: 80%;
63 | }
64 | @each $icon in $icons {
65 | .icon-#{nth($icon, 1)} {
66 | &:before {
67 | content: nth($icon, 2);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/docs/styles/base/_input.scss:
--------------------------------------------------------------------------------
1 | input.form-control {
2 | font-weight: 500;
3 | font-size: 1.25rem;
4 | border: 0;
5 | padding: 0.75rem 1rem;
6 | line-height: 1;
7 | background: clr('bg2');
8 | }
9 |
10 | input.form-control.-is-inline {
11 | padding: 0.4rem 1rem;
12 | color: clr('heading');
13 | }
14 |
--------------------------------------------------------------------------------
/docs/styles/base/_pre.scss:
--------------------------------------------------------------------------------
1 | markdown .inline-code {
2 | padding: 1rem;
3 | pre[class*='language-'] {
4 | display: inline-block;
5 | line-height: 1;
6 | padding: 0;
7 | margin: 0;
8 | background: transparent;
9 | code {
10 | font-size: 1rem;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/docs/styles/base/_reset.scss:
--------------------------------------------------------------------------------
1 | html {
2 | @include smooth-font();
3 | font-size: $toppy--base-font-size;
4 | }
5 |
6 | .custom-select {
7 | -moz-appearance: none;
8 | -webkit-appearance: none;
9 | }
10 |
11 | .btn.btn-link {
12 | color: clr('link-alt');
13 | font-weight: 500;
14 | &:hover {
15 | text-decoration: none;
16 | }
17 | }
18 |
19 | .btn.btn-lg {
20 | font-size: 1rem;
21 | }
22 |
23 | button.btn,
24 | a.btn {
25 | line-height: 1;
26 | padding: 0.5rem 1rem;
27 | }
28 |
29 | .btn.btn-success,
30 | .btn.btn-danger,
31 | .btn.btn-primary {
32 | color: #fff;
33 | }
34 | a:not([href]):not([tabindex]) {
35 | color: none !important;
36 | }
37 |
--------------------------------------------------------------------------------
/docs/styles/base/_typography.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/base/_typography.scss
--------------------------------------------------------------------------------
/docs/styles/base/_utility.scss:
--------------------------------------------------------------------------------
1 | .doc-util-flex-2 {
2 | flex: 2 !important;
3 | }
4 |
5 | .doc-util-valign-middle {
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | }
10 |
11 | .doc-util-tt-lowercase {
12 | text-transform: lowercase;
13 | }
14 |
15 | .doc-util-cover-span {
16 | display: flex;
17 | flex-direction: column;
18 | }
19 |
20 | .doc-util-cursor-pointer {
21 | cursor: pointer;
22 | }
23 |
24 | .doc-util-pos-right {
25 | right: 0;
26 | left: auto !important;
27 | }
28 |
29 | .ff-asap {
30 | }
31 |
32 | .--only-on-parent-hover {
33 | display: none !important;
34 | }
35 |
--------------------------------------------------------------------------------
/docs/styles/browsers/__index.scss:
--------------------------------------------------------------------------------
1 | @import './ie11';
2 | @import './chrome';
3 | @import './firefox';
4 |
--------------------------------------------------------------------------------
/docs/styles/browsers/_chrome.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable media-feature-name-no-vendor-prefix */
2 | @media all and (-webkit-min-device-pixel-ratio: 1) {
3 | }
4 |
5 |
6 | /* Change the white to any color ;) */
7 |
8 | @-webkit-keyframes autofill {
9 | to {
10 | color: #666;
11 | background: transparent;
12 | }
13 | }
14 |
15 | input:-webkit-autofill {
16 | -webkit-animation-name: autofill;
17 | -webkit-animation-fill-mode: both;
18 | }
--------------------------------------------------------------------------------
/docs/styles/browsers/_firefox.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable function-url-quotes*/
2 | @-moz-document url-prefix() {
3 | /* empty */
4 | }
5 |
--------------------------------------------------------------------------------
/docs/styles/browsers/_ie11.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/browsers/_ie11.scss
--------------------------------------------------------------------------------
/docs/styles/components/__index.scss:
--------------------------------------------------------------------------------
1 | @import 'target-element-container';
2 | @import 'controls';
3 | @import 'blade';
4 | @import 'hero';
5 | @import 'menu';
6 | @import 'modal';
7 | @import 'table';
8 |
--------------------------------------------------------------------------------
/docs/styles/components/_blade.scss:
--------------------------------------------------------------------------------
1 | .comp.blade {
2 | background: #3a3d40;
3 | height: 100%;
4 | color: #fff;
5 | h3 {
6 | font-weight: 300;
7 | text-align: center;
8 | display: flex;
9 | align-items: center;
10 | justify-content: center;
11 | flex: 1;
12 | height: 100%;
13 | opacity: 0.9;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/docs/styles/components/_controls.scss:
--------------------------------------------------------------------------------
1 | .comp.controls {
2 | display: flex;
3 | flex-wrap: wrap;
4 | align-items: center;
5 | justify-content: start;
6 | line-height: 3;
7 | // background: #f4f4f9;
8 | padding: 1rem;
9 | li {
10 | display: flex;
11 | flex: 0 0 9rem;
12 | margin: 0.5rem;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/docs/styles/components/_hero.scss:
--------------------------------------------------------------------------------
1 | .comp.hero {
2 | background: #24283c;
3 | height: 100%;
4 | display: flex;
5 | align-items: center;
6 | flex-direction: column;
7 | justify-content: center;
8 | h1 {
9 | font-weight: 300;
10 | color: #fff;
11 | }
12 | p {
13 | color: #aaa;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/docs/styles/components/_menu.scss:
--------------------------------------------------------------------------------
1 | ul.comp.menu {
2 | li {
3 | background-color: transparent;
4 | border: none;
5 | color: clr('heading');
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/docs/styles/components/_modal.scss:
--------------------------------------------------------------------------------
1 | .modal-container {
2 | background: #fff;
3 | border-radius: 4px;
4 | box-shadow: 4px 5px 19px #62616b;
5 | overflow: hidden;
6 | color: clr('dark');
7 | }
8 |
9 | .modal-header {
10 | padding: 20px;
11 | font-weight: 400;
12 | background: #f0f0ff;
13 | text-align: center;
14 | font-size: 1.4rem;
15 | }
16 | .modal-body {
17 | padding: 20px;
18 | .illus {
19 | min-height: 192px;
20 | }
21 | }
22 | .modal-footer {
23 | text-align: right;
24 | padding: 20px;
25 | }
26 |
--------------------------------------------------------------------------------
/docs/styles/components/_table.scss:
--------------------------------------------------------------------------------
1 | table {
2 | // @include .table;
3 | width: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/docs/styles/components/_target-element-container.scss:
--------------------------------------------------------------------------------
1 | .comp.target-element-container {
2 | padding: 2rem;
3 | display: flex;
4 | align-items: center;
5 | justify-content: center;
6 | .target-element {
7 | background: clr('primary');
8 | padding: 1rem;
9 | border-radius: 2px;
10 | color: #fff;
11 | font-weight: 500;
12 | box-shadow: 0px 3px 6px #c6c6d8;
13 | cursor: pointer;
14 | }
15 |
16 | .target-element-basic {
17 | padding: 1rem 2rem;
18 | border: 1px dashed #d8d8e3;
19 | cursor: pointer;
20 | }
21 |
22 | .target-element-basic:hover {
23 | border-color: #cfd2de;
24 | color: clr('dark');
25 | background-color: #fff;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/styles/elements/__index.scss:
--------------------------------------------------------------------------------
1 | @import './btn';
2 | @import './hr';
3 | @import './tooltip';
4 | @import './toast';
5 |
--------------------------------------------------------------------------------
/docs/styles/elements/_btn.scss:
--------------------------------------------------------------------------------
1 | .btn.btn-transparent {
2 | background-color: transparent;
3 | border-color: transparent;
4 | }
5 |
--------------------------------------------------------------------------------
/docs/styles/elements/_hr.scss:
--------------------------------------------------------------------------------
1 | .doc-el-hr {
2 | background-color: transparentize(#fff, 0.8);
3 | // height: 0.1rem;
4 | height: 1px;
5 | &.hr-dark{
6 | background-color: transparentize(#000, 0.9);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/docs/styles/elements/_toast.scss:
--------------------------------------------------------------------------------
1 | .el.toast {
2 | background: #76cc7a;
3 | padding: 1rem;
4 | border: 1px solid #7dbf81;
5 | border-radius: 3px;
6 | color: #fff;
7 | }
8 |
--------------------------------------------------------------------------------
/docs/styles/elements/_tooltip.scss:
--------------------------------------------------------------------------------
1 | .el.tooltip {
2 | background: #e75676bd;
3 | padding: 0.3rem 0.5rem;
4 | border-radius: 3px;
5 | font-size: 11px;
6 | color: #fff;
7 | text-shadow: 1px 1px 1px #a55b6b;
8 | margin: 0;
9 | }
10 |
--------------------------------------------------------------------------------
/docs/styles/helpers/__index.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable scss/at-import-no-partial-leading-underscore */
2 | @import './functions/_index';
3 | @import './mixins/_index';
4 | @import './debug';
5 |
--------------------------------------------------------------------------------
/docs/styles/helpers/_debug.scss:
--------------------------------------------------------------------------------
1 | @if ($toppy--debug) {
2 | div,
3 | ul {
4 | box-shadow: 0px 0px 1px 0px #e3505a;
5 | }
6 | section {
7 | box-shadow: 0px 0px 1px 1px #187fe5;
8 | }
9 |
10 | span,
11 | li {
12 | box-shadow: 0px 0px 1px 0px #212529;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/docs/styles/helpers/functions/__index.scss:
--------------------------------------------------------------------------------
1 | @import './clr';
2 | @import './fs';
3 | @import './rem';
4 | @import './z';
5 |
--------------------------------------------------------------------------------
/docs/styles/helpers/functions/_clr.scss:
--------------------------------------------------------------------------------
1 | @function clr($key: 'primary') {
2 | @return map-get($toppy--colors, $key);
3 | }
4 |
--------------------------------------------------------------------------------
/docs/styles/helpers/functions/_fs.scss:
--------------------------------------------------------------------------------
1 | @function fs($key: 'md') {
2 | @return map-get($toppy--font-sizes, $key);
3 | }
4 |
--------------------------------------------------------------------------------
/docs/styles/helpers/functions/_rem.scss:
--------------------------------------------------------------------------------
1 | @function rem($pixels, $context: $toppy--base-font-size) {
2 | @if (unitless($pixels)) {
3 | $pixels: $pixels * 1px;
4 | }
5 | @if (unitless($context)) {
6 | $context: $context * 1px;
7 | }
8 | @return $pixels / $context * 1rem;
9 | }
10 |
--------------------------------------------------------------------------------
/docs/styles/helpers/functions/_z.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/helpers/functions/_z.scss
--------------------------------------------------------------------------------
/docs/styles/helpers/mixins/__index.scss:
--------------------------------------------------------------------------------
1 | @import './acceleration';
2 | @import './ellipsis';
3 | @import './placeholder';
4 | @import './smooth-font';
5 | @import './gradient';
6 |
--------------------------------------------------------------------------------
/docs/styles/helpers/mixins/_acceleration.scss:
--------------------------------------------------------------------------------
1 | @mixin hardware($backface: true, $perspective: 1000) {
2 | @if $backface {
3 | backface-visibility: hidden;
4 | }
5 | perspective: $perspective;
6 | }
7 |
--------------------------------------------------------------------------------
/docs/styles/helpers/mixins/_ellipsis.scss:
--------------------------------------------------------------------------------
1 | /// div {
2 | /// @include ellipsis;
3 | /// }
4 | ///
5 | /// .box {
6 | /// @include ellipsis(3);
7 | /// }
8 |
9 | /* stylelint-disable */
10 |
11 | @mixin ellipsis($lines: 1, $substract: 0) {
12 | @if $lines == 1 {
13 | overflow: hidden;
14 | text-overflow: ellipsis;
15 | white-space: nowrap;
16 | width: 100% - $substract;
17 | } @else {
18 | -webkit-box-orient: vertical;
19 | box-orient: vertical;
20 | display: -webkit-box;
21 | display: box;
22 | -webkit-line-clamp: $lines;
23 | line-clamp: $lines;
24 | overflow: hidden;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/docs/styles/helpers/mixins/_gradient.scss:
--------------------------------------------------------------------------------
1 | @function is-direction($value) {
2 | $is-keyword: index(
3 |
4 | (
5 | to top,
6 | to top right,
7 | to right top,
8 | to right,
9 | to bottom right,
10 | to right bottom,
11 | to bottom,
12 | to bottom left,
13 | to left bottom,
14 | to left,
15 | to left top,
16 | to top left
17 | ),
18 | $value
19 | );
20 | $is-angle: type-of($value)=='number' and index('deg' 'grad' 'turn' 'rad', unit($value));
21 | @return $is-keyword or $is-angle;
22 | }
23 | @mixin linear-gradient($direction, $color-stops...) {
24 | @if is-direction($direction) ==false {
25 | $color-stops: $direction, $color-stops;
26 | $direction: 180deg;
27 | }
28 | background: nth(nth($color-stops, 1), 1);
29 | background: -webkit-linear-gradient(legacy-direction($direction), $color-stops);
30 | background: linear-gradient($direction, $color-stops);
31 | }
32 |
--------------------------------------------------------------------------------
/docs/styles/helpers/mixins/_placeholder.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable selector-no-vendor-prefix */
2 | @mixin input-placeholder {
3 | &.placeholder {
4 | @content;
5 | }
6 | &:-moz-placeholder {
7 | @content;
8 | }
9 | &::-moz-placeholder {
10 | @content;
11 | }
12 | &:-ms-input-placeholder {
13 | @content;
14 | }
15 | &::-webkit-input-placeholder {
16 | @content;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/docs/styles/helpers/mixins/_smooth-font.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable */
2 |
3 | @mixin smooth-font($lines: 1, $substract: 0) {
4 | font-size: 100%;
5 | -webkit-text-size-adjust: 100%;
6 | font-variant-ligatures: none;
7 | -webkit-font-variant-ligatures: none;
8 | text-rendering: optimizeLegibility;
9 | -moz-osx-font-smoothing: grayscale;
10 | font-smoothing: antialiased;
11 | -webkit-font-smoothing: antialiased;
12 | text-shadow: rgba(0, 0, 0, 0.01) 0 0 1px;
13 | }
14 |
--------------------------------------------------------------------------------
/docs/styles/icons/toppy.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/icons/toppy.ttf
--------------------------------------------------------------------------------
/docs/styles/icons/toppy.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/icons/toppy.woff
--------------------------------------------------------------------------------
/docs/styles/layouts/__index.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/layouts/__index.scss
--------------------------------------------------------------------------------
/docs/styles/pages/__index.scss:
--------------------------------------------------------------------------------
1 | // @import "./playground";
2 |
--------------------------------------------------------------------------------
/docs/styles/responsive/__index.scss:
--------------------------------------------------------------------------------
1 | @import './lg';
2 | @import './xl';
3 | @import './md';
4 |
--------------------------------------------------------------------------------
/docs/styles/responsive/_lg.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/responsive/_lg.scss
--------------------------------------------------------------------------------
/docs/styles/responsive/_md.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lokesh-coder/toppy/3129723f99f430b0448eb52b433250a4816d558a/docs/styles/responsive/_md.scss
--------------------------------------------------------------------------------
/docs/styles/responsive/_xl.scss:
--------------------------------------------------------------------------------
1 | @include media-breakpoint-up(xl) {
2 | html {
3 | // font-size: $toppy--base-font-size-xl;
4 | }
5 | }
--------------------------------------------------------------------------------
/docs/styles/root.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable scss/at-import-no-partial-leading-underscore */
2 |
3 | @import './config';
4 | @import './helpers/_index';
5 | @import './base/_index';
6 | @import './vendors/_index';
7 | @import './pages/_index';
8 | @import './animations/_index';
9 | @import './components/_index';
10 | @import './layouts/_index';
11 | @import './elements/_index';
12 | @import './browsers/_index';
13 | @import './responsive/_index';
14 | @import './temp';
15 |
--------------------------------------------------------------------------------
/docs/styles/vendors/__index.scss:
--------------------------------------------------------------------------------
1 | @import './bootstrap';
2 | @import './pretty-checkbox';
3 | @import './prism';
4 |
--------------------------------------------------------------------------------
/docs/styles/vendors/_bootstrap.scss:
--------------------------------------------------------------------------------
1 | /* Bootstrap config */
2 | $body-bg: clr('bg');
3 | $body-color: clr('text');
4 | $link-color: clr('primary');
5 | $link-hover-color: clr('primary-o');
6 | $headings-color: clr('dark');
7 |
8 | $theme-colors: (
9 | primary: clr('primary'),
10 | secondary: clr('secondary'),
11 | success: clr('success'),
12 | warning: clr('warning'),
13 | danger: clr('danger'),
14 | info: clr('info'),
15 | dark: clr('dark'),
16 | alt: clr('alt'),
17 | );
18 | $border-radius: $toppy--border-rad;
19 | $font-family-base: $toppy--font-family;
20 | $headings-font-family: $toppy--font-family-headings;
21 | $breadcrumb-margin-bottom: 0;
22 |
23 | $h1-font-size: fs('h1');
24 | $h2-font-size: fs('h2');
25 | $h3-font-size: fs('h3');
26 | $h4-font-size: fs('h4');
27 | $h5-font-size: fs('h5');
28 | $h6-font-size: fs('h6');
29 | $input-btn-padding-y-lg: 0.8rem;
30 | $input-btn-padding-x-lg: 1.5rem;
31 |
32 | $grid-breakpoints: $toppy--grid-breakpoints;
33 |
34 | @import '~bootstrap/scss/functions';
35 | @import '~bootstrap/scss/variables';
36 | @import '~bootstrap/scss/mixins';
37 | // @import '~bootstrap/scss/print';
38 | @import '~bootstrap/scss/reboot';
39 | @import '~bootstrap/scss/type';
40 | @import '~bootstrap/scss/images';
41 | @import '~bootstrap/scss/code';
42 | @import '~bootstrap/scss/grid';
43 | @import '~bootstrap/scss/tables';
44 | @import '~bootstrap/scss/forms';
45 | @import '~bootstrap/scss/buttons';
46 | @import '~bootstrap/scss/transitions';
47 | //@import '~bootstrap/scss/dropdown';
48 | //@import '~bootstrap/scss/button-group';
49 | @import '~bootstrap/scss/input-group';
50 | @import '~bootstrap/scss/custom-forms';
51 | @import '~bootstrap/scss/nav';
52 | @import '~bootstrap/scss/navbar';
53 | @import '~bootstrap/scss/card';
54 | //@import '~bootstrap/scss/breadcrumb';
55 | // @import '~bootstrap/scss/pagination';
56 | @import '~bootstrap/scss/badge';
57 | // @import '~bootstrap/scss/jumbotron';
58 | @import '~bootstrap/scss/alert';
59 | //@import '~bootstrap/scss/progress';
60 | // @import '~bootstrap/scss/media';
61 | @import '~bootstrap/scss/list-group';
62 | @import '~bootstrap/scss/close';
63 | //@import '~bootstrap/scss/modal';
64 | //@import '~bootstrap/scss/tooltip';
65 | //@import '~bootstrap/scss/popover';
66 | // @import '~bootstrap/scss/carousel';
67 | @import '~bootstrap/scss/utilities';
68 |
--------------------------------------------------------------------------------
/docs/styles/vendors/_pretty-checkbox.scss:
--------------------------------------------------------------------------------
1 | $pretty--color-success: clr('success');
2 | @import '~pretty-checkbox/src/pretty-checkbox';
3 |
4 | .pretty.pretty-check {
5 | .state label:before,
6 | .pretty.p-round .state label:after {
7 | border-width: 0.15rem;
8 | }
9 | .icon {
10 | transform: scale(0.8);
11 | }
12 | }
13 |
14 | .pretty.p-switch .state label:before,
15 | .pretty.p-switch .state label:after {
16 | top: calc((0% - (100% - 1em)) - 12%);
17 | }
18 |
--------------------------------------------------------------------------------
/docs/styles/vendors/_prism.scss:
--------------------------------------------------------------------------------
1 | app-content pre[class*='language-'] {
2 | background: #fff;
3 | border: 1px solid clr('border');
4 | border-radius: $toppy--border-rad;
5 | code {
6 | font-size: 12px;
7 | font-family: $toppy--font-family-monospace;
8 | }
9 | }
10 | app-content .inline-code {
11 | display: flex;
12 | align-items: center;
13 | flex-wrap: wrap;
14 | pre[class*='language-'] {
15 | font-size: 13px !important;
16 | background-color: #f0f0f3;
17 | border: 0;
18 | margin: 6px;
19 | padding: 2px 8px;
20 | code{
21 |
22 | font-size: 10px !important;
23 | }
24 | }
25 | }
26 |
27 | app-content code[class*='language-'],
28 | app-content pre[class*='language-'] {
29 | color: #51585d;
30 | }
31 |
--------------------------------------------------------------------------------
/docs/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/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/docs/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "types": []
6 | },
7 | "exclude": [
8 | "test.ts",
9 | "**/*.spec.ts"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/docs/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.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 |
--------------------------------------------------------------------------------
/docs/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/e2e/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 | './src/**/*.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: require('path').join(__dirname, './tsconfig.e2e.json')
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('workspace-project App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to toppy-app!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
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.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "toppy-app",
3 | "version": "2.3.4",
4 | "description": "Overlay library for Angular 7+",
5 | "keywords": [
6 | "angular",
7 | "dropdown",
8 | "modal",
9 | "overlay",
10 | "popover",
11 | "popup",
12 | "sidebar",
13 | "tooltip"
14 | ],
15 | "homepage": "https://github.com/lokesh-coder/toppy",
16 | "bugs": {
17 | "url": "https://github.com/lokesh-coder/toppy/issues"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/lokesh-coder/toppy"
22 | },
23 | "license": "MIT",
24 | "author": {
25 | "name": "Lokesh Rajendran",
26 | "email": "mexican.dirtyfellow@gmail.com",
27 | "url": "https://github.com/lokesh-coder"
28 | },
29 | "scripts": {
30 | "archive:app": "node ./scripts/archive.js",
31 | "build:app": "ng build --prod --baseHref=/toppy/",
32 | "build:lib": "ng build toppy",
33 | "e2e": "ng e2e",
34 | "lint": "ng lint",
35 | "ng": "ng",
36 | "postpublish": "node ./scripts/gh-pages.js",
37 | "release": "semantic-release",
38 | "start": "ng serve",
39 | "test": "npm run test:lib",
40 | "test:app": "ng test --project toppy-app",
41 | "test:lib": "ng test --project toppy",
42 | "travis-deploy-once": "travis-deploy-once"
43 | },
44 | "dependencies": {
45 | "@angular/animations": "~7.1.0",
46 | "@angular/common": "~7.1.0",
47 | "@angular/compiler": "~7.1.0",
48 | "@angular/core": "~7.1.0",
49 | "@angular/forms": "~7.1.0",
50 | "@angular/http": "~7.1.0",
51 | "@angular/platform-browser": "~7.1.0",
52 | "@angular/platform-browser-dynamic": "~7.1.0",
53 | "@angular/router": "~7.1.0",
54 | "@ngx-prism/core": "^2.0.1",
55 | "@types/prismjs": "^1.9.0",
56 | "bootstrap": "^4.1.3",
57 | "core-js": "^2.5.7",
58 | "date-fns": "^1.29.0",
59 | "listr": "^0.14.3",
60 | "lodash-es": "^4.17.11",
61 | "npm-registry-client": "^8.6.0",
62 | "pretty-checkbox": "^3.0.3",
63 | "prismjs": "^1.15.0",
64 | "remark-bracketed-spans": "^3.0.0",
65 | "remark-custom-blocks": "^2.3.1",
66 | "rxjs": "~6.3.3",
67 | "zone.js": "~0.8.26"
68 | },
69 | "devDependencies": {
70 | "@angular-devkit/build-angular": "~0.11.0",
71 | "@angular-devkit/build-ng-packagr": "~0.11.0",
72 | "@angular/cli": "~7.1.0",
73 | "@angular/compiler-cli": "~7.1.0",
74 | "@angular/language-service": "~7.1.0",
75 | "@commitlint/cli": "7.2.1",
76 | "@commitlint/config-conventional": "7.1.2",
77 | "@commitlint/travis-cli": "7.2.1",
78 | "@semantic-release/changelog": "3.0.1",
79 | "@semantic-release/exec": "3.3.0",
80 | "@semantic-release/git": "7.0.5",
81 | "@semantic-release/github": "^5.2.5",
82 | "@semantic-release/release-notes-generator": "^7.1.4",
83 | "@types/jasmine": "~3.3.0",
84 | "@types/jasminewd2": "~2.0.6",
85 | "@types/node": "~10.12.10",
86 | "angular-cli-ghpages": "^0.5.3",
87 | "codelyzer": "~4.5.0",
88 | "conventional-changelog": "3.0.5",
89 | "fs-extra": "^7.0.1",
90 | "gh-pages": "^2.0.1",
91 | "github-release-notes": "0.17.0",
92 | "husky": "^1.2.0",
93 | "jasmine-core": "~3.3.0",
94 | "jasmine-spec-reporter": "~4.2.1",
95 | "json": "^9.0.6",
96 | "karma": "~3.1.1",
97 | "karma-chrome-launcher": "~2.2.0",
98 | "karma-coverage-istanbul-reporter": "~2.0.4",
99 | "karma-helpful-reporter": "^0.3.4",
100 | "karma-jasmine": "~2.0.1",
101 | "karma-jasmine-html-reporter": "^1.4.0",
102 | "karma-viewport": "^1.0.2",
103 | "ng-packagr": "^4.4.0",
104 | "nodemon": "^1.18.7",
105 | "protractor": "~5.4.1",
106 | "rehype-format": "^2.3.1",
107 | "rehype-highlight": "^2.2.1",
108 | "rehype-raw": "^4.0.0",
109 | "rehype-stringify": "^5.0.0",
110 | "remark-attr": "^0.8.0",
111 | "remark-autolink-headings": "^5.1.0",
112 | "remark-highlight.js": "^5.0.0",
113 | "remark-html": "^9.0.0",
114 | "remark-rehype": "^4.0.0",
115 | "remark-slug": "^5.1.1",
116 | "replace-in-file": "^3.4.2",
117 | "sane": "^4.0.2",
118 | "semantic-release": "^15.12.2",
119 | "stylelint": "^9.9.0",
120 | "stylelint-config-recommended-scss": "^3.2.0",
121 | "stylelint-scss": "^3.4.0",
122 | "travis-deploy-once": "5.0.9",
123 | "ts-node": "~7.0.1",
124 | "tsickle": "0.34.0",
125 | "tslib": "^1.9.3",
126 | "tslint": "~5.11.0",
127 | "typescript": "~3.1.6"
128 | },
129 | "husky": {
130 | "hooks": {
131 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/projects/toppy/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', 'viewport'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-viewport'),
11 | require('karma-chrome-launcher'),
12 | require('karma-jasmine-html-reporter'),
13 | require('karma-coverage-istanbul-reporter'),
14 | require('@angular-devkit/build-angular/plugins/karma')
15 | ],
16 | client: {
17 | clearContext: false // leave Jasmine Spec Runner output visible in browser
18 | },
19 | coverageIstanbulReporter: {
20 | dir: require('path').join(__dirname, '../../coverage'),
21 | reports: ['html', 'lcovonly', 'json'],
22 | fixWebpackSourcePaths: true
23 | },
24 | reporters: ['progress', 'kjhtml'],
25 | port: 9876,
26 | colors: true,
27 | logLevel: config.LOG_INFO,
28 | autoWatch: true,
29 | browsers: ['Chrome'],
30 | singleRun: false
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/projects/toppy/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/toppy",
4 | "lib": {
5 | "entryFile": "src/public_api.ts"
6 | }
7 | }
--------------------------------------------------------------------------------
/projects/toppy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "toppy",
3 | "version": "0.0.0-development",
4 | "description": "Overlay library for Angular 7+",
5 | "keywords": [
6 | "angular",
7 | "dropdown",
8 | "modal",
9 | "overlay",
10 | "popover",
11 | "popup",
12 | "sidebar",
13 | "tooltip"
14 | ],
15 | "homepage": "https://github.com/lokesh-coder/toppy",
16 | "bugs": {
17 | "url": "https://github.com/lokesh-coder/toppy/issues"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/lokesh-coder/toppy"
22 | },
23 | "license": "MIT",
24 | "author": {
25 | "name": "Lokesh Rajendran",
26 | "email": "mexican.dirtyfellow@gmail.com",
27 | "url": "https://github.com/lokesh-coder"
28 | },
29 | "peerDependencies": {
30 | "@angular/common": "^7.0.0",
31 | "@angular/core": "^7.0.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/config.ts:
--------------------------------------------------------------------------------
1 | import { ToppyConfig } from './models';
2 |
3 | export const DefaultConfig: ToppyConfig = {
4 | containerClass: 't-overlay',
5 | bodyClass: 't-open',
6 | wrapperClass: '',
7 | backdropClass: '',
8 | backdrop: false,
9 | closeOnDocClick: false,
10 | listenWindowEvents: true,
11 | closeOnEsc: false,
12 | windowResizeCallback: () => {},
13 | docClickCallback: () => {}
14 | };
15 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/models.ts:
--------------------------------------------------------------------------------
1 | import { TemplateRef } from '@angular/core';
2 | import { ToppyPosition } from './position/position';
3 |
4 | export interface PositionMeta {
5 | top?: number;
6 | left?: number;
7 | bottom?: number;
8 | right?: number;
9 | height?: number | string;
10 | width?: number | string;
11 | position?: string;
12 | extra?: string;
13 | }
14 |
15 | enum p {
16 | TOP = 't',
17 | LEFT = 'l',
18 | RIGHT = 'r',
19 | BOTTOM = 'b',
20 | TOP_LEFT = 'tl',
21 | TOP_RIGHT = 'tr',
22 | BOTTOM_LEFT = 'bl',
23 | BOTTOM_RIGHT = 'br'
24 | }
25 |
26 | enum o {
27 | LEFT_TOP = 'lt',
28 | RIGHT_TOP = 'rt',
29 | LEFT_BOTTOM = 'lb',
30 | RIGHT_BOTTOM = 'rb'
31 | }
32 |
33 | enum i {
34 | CENTER = 'c'
35 | }
36 | export const OutsidePlacement = {
37 | ...p,
38 | ...o
39 | };
40 | export const InsidePlacement = {
41 | ...p,
42 | ...i
43 | };
44 | export type OutsidePlacement = p | o;
45 | export type InsidePlacement = p | i;
46 |
47 | export enum SlidePlacement {
48 | LEFT = 'l',
49 | RIGHT = 'r'
50 | }
51 |
52 | export interface ContainerSize {
53 | width: string | number;
54 | height: string | number;
55 | }
56 |
57 | export interface ToppyConfig {
58 | backdrop: boolean;
59 | containerClass: string;
60 | wrapperClass: string;
61 | backdropClass: string;
62 | listenWindowEvents: boolean;
63 | closeOnDocClick: boolean;
64 | bodyClass: string;
65 | closeOnEsc: boolean;
66 | windowResizeCallback: () => void;
67 | docClickCallback: () => void;
68 | }
69 |
70 | export interface ComponentType {
71 | new (...args: any[]): T;
72 | }
73 |
74 | export type TID = string;
75 |
76 | export type ToppyEventName = 't_open' | 't_close' | 't_dynpos' | 't_detach' | 't_posupdate' | 't_compins';
77 |
78 | export interface ToppyEvent {
79 | from: TID;
80 | name: ToppyEventName;
81 | data?: any;
82 | }
83 |
84 | export const enum ContentType {
85 | STRING = 's',
86 | HTML = 'h',
87 | TEMPLATE = 't',
88 | COMPONENT = 'c'
89 | }
90 | export type ContentData = string | TemplateRef | ComponentType;
91 | export type ContentProps = { [x: string]: any } | any;
92 |
93 | export interface Content {
94 | type?: ContentType;
95 | data: ContentData;
96 | props?: ContentProps;
97 | }
98 |
99 | export interface Inputs {
100 | position: ToppyPosition | null;
101 | config: ToppyConfig;
102 | content: Content;
103 | tid: TID;
104 | }
105 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/position/fullscreen-position.ts:
--------------------------------------------------------------------------------
1 | import { PositionMeta } from '../models';
2 | import { ToppyPosition } from './position';
3 |
4 | export class FullscreenPosition extends ToppyPosition {
5 | getPositions(): PositionMeta {
6 | return { top: 0, left: 0, width: '100%', height: '100%', position: 'fixed' };
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/position/global-position.ts:
--------------------------------------------------------------------------------
1 | import { InsidePlacement } from '../models';
2 | import { setWH } from '../utils';
3 | import { ToppyPosition } from './position';
4 |
5 | interface GlobalPositionConfig {
6 | placement?: InsidePlacement;
7 | offset?: number;
8 | width?: string | number;
9 | height?: string | number;
10 | }
11 |
12 | export class GlobalPosition extends ToppyPosition {
13 | protected config: GlobalPositionConfig = { placement: InsidePlacement.CENTER, width: 100, height: 100, offset: 0 };
14 |
15 | constructor(config: GlobalPositionConfig) {
16 | super();
17 | this.updateConfig(config);
18 | }
19 | getPositions(hostEl?: HTMLElement) {
20 | const host = hostEl.getBoundingClientRect() as any;
21 | const src = {
22 | width: window['innerWidth'],
23 | height: window['innerHeight']
24 | };
25 | let { width: w, height: h } = this.config;
26 |
27 | w = setWH(src, host, 'width', w);
28 | h = setWH(src, host, 'height', h);
29 |
30 | const props = this.calc(this.config.placement, src, host);
31 | return {
32 | ...props,
33 | width: w,
34 | height: h,
35 | position: 'fixed',
36 | extra: this.config.placement
37 | };
38 | }
39 |
40 | private calc(placement: InsidePlacement, src, host) {
41 | const [main, sub] = placement.split('');
42 | const p: any = {};
43 |
44 | if (main === 't') {
45 | p.top = this.config.offset;
46 | }
47 | if (main === 'b') {
48 | p.bottom = this.config.offset;
49 | }
50 | if ((main === 'l' || main === 'r' || main === 'c') && !sub) {
51 | p.top = (src.height - host.height) / 2;
52 | }
53 |
54 | if ((main === 't' || main === 'b' || main === 'c') && !sub) {
55 | p.left = (src.width - host.width) / 2;
56 | }
57 | if ((main === 'l' && !sub) || sub === 'l') {
58 | p.left = this.config.offset;
59 | }
60 | if ((main === 'r' && !sub) || sub === 'r') {
61 | p.right = this.config.offset;
62 | }
63 |
64 | return p;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/position/index.ts:
--------------------------------------------------------------------------------
1 | export { FullscreenPosition } from './fullscreen-position';
2 | export { GlobalPosition } from './global-position';
3 | export { RelativePosition } from './relative-position';
4 | export { SlidePosition } from './slide-position';
5 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/position/position.ts:
--------------------------------------------------------------------------------
1 | export abstract class ToppyPosition {
2 | protected config = {};
3 | abstract getPositions(host: HTMLElement): any;
4 |
5 | getClassName(): string {
6 | return this.constructor.name.replace('Pos', '-pos').toLowerCase();
7 | }
8 |
9 | updateConfig(config) {
10 | this.config = { ...this.config, ...config };
11 | }
12 |
13 | init(tid: string) {}
14 | }
15 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/position/relative-position.ts:
--------------------------------------------------------------------------------
1 | import { OutsidePlacement, PositionMeta } from '../models';
2 | import { Bus, setWH } from '../utils';
3 | import { ToppyPosition } from './position';
4 |
5 | interface RelativePositionConfig {
6 | src: HTMLElement;
7 | placement?: OutsidePlacement;
8 | autoUpdate?: boolean;
9 | width?: string | number;
10 | height?: string | number;
11 | }
12 |
13 | export class RelativePosition extends ToppyPosition {
14 | protected config: RelativePositionConfig = {
15 | src: null,
16 | placement: OutsidePlacement.TOP,
17 | autoUpdate: false,
18 | width: 'auto',
19 | height: 'auto'
20 | };
21 | obs: MutationObserver;
22 | constructor(config: RelativePositionConfig) {
23 | super();
24 | this.updateConfig(config);
25 | }
26 | init(tid: string): void {
27 | if (this.config.autoUpdate) this.listenDrag(tid);
28 | }
29 |
30 | getPositions(targetEl: HTMLElement): Pick {
31 | const s = this.getCoords(this.config.src);
32 | const h = this.getCoords(targetEl);
33 | let { width: w, height: ht } = this.config;
34 |
35 | w = setWH(s, h, 'width', w);
36 | ht = setWH(s, h, 'height', ht);
37 |
38 | const { pos, props } = this.calculatePos(this.config.placement, s, h);
39 | return { ...this.round(props), width: w, height: ht, extra: pos };
40 | }
41 |
42 | private getCoords(elem: HTMLElement): PositionMeta {
43 | return elem.getBoundingClientRect();
44 | }
45 |
46 | private calc(placement: OutsidePlacement, src, host): object {
47 | const [main, sub] = placement.split('');
48 | const p = { left: 0, top: 0 };
49 | if ((main === 't' || main === 'b') && !sub) {
50 | p.left = src.left + (src.width - host.width) / 2;
51 | }
52 |
53 | if ((main === 't' || main === 'b') && sub) {
54 | p.left = src.left;
55 | }
56 | if ((main === 't' || main === 'b') && sub === 'r') {
57 | p.left = src.left + src.width - host.width;
58 | }
59 | if (main === 'l') {
60 | p.left = src.left - host.width;
61 | }
62 | if (main === 'r') {
63 | p.left = src.right;
64 | }
65 |
66 | if (main === 't') {
67 | p.top = src.top - host.height;
68 | }
69 | if (main === 'b') {
70 | p.top = src.top + src.height;
71 | }
72 | if (main === 'l' || main === 'r') {
73 | p.top = src.top + (src.height - host.height) / 2;
74 | }
75 | if (sub === 't' && (main === 'l' || main === 'r')) {
76 | p.top = src.top;
77 | }
78 | if (sub === 'b' && (main === 'l' || main === 'r')) {
79 | p.top = src.top + src.height - host.height;
80 | }
81 | return p;
82 | }
83 |
84 | private calculatePos(pos, s, h, c = true): { [x: string]: any } {
85 | const props = this.calc(pos, s, h);
86 |
87 | if (c && this.config.autoUpdate && this.isOverflowed({ ...props, width: h.width, height: h.height })) {
88 | return this.calculatePos(this.nextPosition(pos), s, h, false);
89 | }
90 |
91 | return { pos, props };
92 | }
93 |
94 | private isOverflowed(props: { [x: string]: any }): boolean {
95 | const { innerHeight, innerWidth } = window;
96 | props.bottom = props.top + props.height;
97 | props.right = props.left + props.width;
98 | return props.bottom > innerHeight || props.top <= 0 || props.left <= 0 || props.right > innerWidth;
99 | }
100 |
101 | private nextPosition(current: OutsidePlacement): string {
102 | const placements = ['t', 'b', 'l', 'r', 'tl', 'bl', 'tr', 'br', 'lt', 'rt', 'lb', 'rb'];
103 |
104 | const index = placements.indexOf(current);
105 | const even = index % 2 === 0;
106 | return even ? placements[index + 1] : placements[index - 1];
107 | }
108 |
109 | private round(props: object): object {
110 | Object.keys(props).forEach(x => (props[x] = Math.round(props[x])));
111 | return props;
112 | }
113 |
114 | private listenDrag(tid: string): void {
115 | if (this.obs) this.obs.disconnect();
116 | this.obs = new MutationObserver(mutationsList => {
117 | for (const mutation of mutationsList) {
118 | if (mutation.type === 'attributes') Bus.send(tid, 't_dynpos');
119 | }
120 | });
121 |
122 | this.obs.observe(this.config.src, {
123 | attributeFilter: ['style']
124 | });
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/position/slide-position.ts:
--------------------------------------------------------------------------------
1 | import { PositionMeta, SlidePlacement } from '../models';
2 | import { ToppyPosition } from './position';
3 |
4 | interface SlidePlacementConfig {
5 | placement?: SlidePlacement;
6 | width?: string;
7 | }
8 |
9 | export class SlidePosition extends ToppyPosition {
10 | protected config: SlidePlacementConfig = { placement: SlidePlacement.LEFT, width: '30%' };
11 |
12 | constructor(config: SlidePlacementConfig) {
13 | super();
14 | this.config = { ...this.config, ...config };
15 | }
16 | getPositions(): PositionMeta {
17 | const props = this.config.placement === SlidePlacement.LEFT ? { left: 0 } : { right: 0 };
18 | return {
19 | ...props,
20 | top: 0,
21 | width: this.config.width,
22 | height: '100%',
23 | position: 'fixed',
24 | extra: this.config.placement
25 | };
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/styles.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | left: 0;
3 | position: fixed;
4 | top: 0;
5 | width: 100%;
6 | height: 100%;
7 | pointer-events: none;
8 | &.no-pointers {
9 | pointer-events: all;
10 | }
11 | .t-backdrop {
12 | left: 0;
13 | position: fixed;
14 | top: 0;
15 | width: 100%;
16 | height: 100%;
17 | background: rgba(0, 0, 0, 0.5);
18 | // pointer-events: none;
19 | }
20 | > div.t-wrapper {
21 | position: absolute;
22 | visibility: hidden;
23 | opacity: 0;
24 | transition: opacity 0.2s ease;
25 | overflow: hidden;
26 | pointer-events: all;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ content.data }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/toppy-control.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ApplicationRef,
3 | ComponentFactory,
4 | ComponentFactoryResolver,
5 | ComponentRef,
6 | Injector,
7 | ViewRef
8 | } from '@angular/core';
9 | import { animationFrameScheduler, fromEvent, merge as mergeObs, Observable, Subject } from 'rxjs';
10 | import { debounceTime, distinctUntilChanged, filter, map, observeOn, skipWhile, takeUntil, tap } from 'rxjs/operators';
11 | import { Content, ContentData, ContentProps, TID, ToppyConfig, ToppyEventName } from './models';
12 | import { ToppyPosition } from './position/position';
13 | import { ToppyComponent } from './toppy.component';
14 | import { BodyEl, Bus, getContent } from './utils';
15 |
16 | export class ToppyControl {
17 | position: ToppyPosition;
18 | config: ToppyConfig;
19 | content: Content;
20 | tid: TID;
21 | comp: ToppyComponent;
22 | updateTextContent: Subject = new Subject();
23 | hostView: ViewRef;
24 | compRef: ComponentRef;
25 |
26 | private viewEl: HTMLElement;
27 | private isOpen = false;
28 | private compFac: ComponentFactory;
29 | private die: Subject<1> = new Subject();
30 |
31 | constructor(
32 | private appRef: ApplicationRef,
33 | private compResolver: ComponentFactoryResolver,
34 | private injector: Injector
35 | ) {
36 | this.updateTextContent.subscribe(content => {
37 | if (this.isOpen) this.comp.updateTextContent(content);
38 | });
39 | }
40 |
41 | open(): void {
42 | if (this.isOpen) return;
43 |
44 | this.attach();
45 | if (this.viewEl) {
46 | mergeObs(this.onDocumentClick(), this.onWindowResize(), this.onEscClick()).subscribe();
47 | setTimeout(() => Bus.send(this.tid, 't_dynpos'), 1);
48 | }
49 |
50 | Bus.send(this.tid, 't_open');
51 | this.isOpen = true;
52 | }
53 |
54 | close(): void {
55 | if (!this.isOpen) return;
56 |
57 | this.dettach();
58 | this.die.next(1);
59 | Bus.send(this.tid, 't_close');
60 | this.isOpen = false;
61 | }
62 |
63 | toggle(): void {
64 | return this.isOpen ? this.close() : this.open();
65 | }
66 |
67 | onEscClick(): Observable {
68 | return fromEvent(BodyEl, 'keydown').pipe(
69 | takeUntil(this.die),
70 | skipWhile(() => !this.config.closeOnEsc),
71 | filter((e: any) => (e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27) && e.target.nodeName === 'BODY'),
72 | tap(e => e.preventDefault()),
73 | map(e => e.target),
74 | tap(() => this.close())
75 | );
76 | }
77 |
78 | onDocumentClick(): Observable {
79 | return fromEvent(this.viewEl, 'click').pipe(
80 | takeUntil(this.die),
81 | map((e: any) => e.target),
82 | skipWhile(() => !this.config.closeOnDocClick),
83 | filter(this.isNotHostElement.bind(this)),
84 | tap(() => {
85 | this.config.docClickCallback();
86 | this.close();
87 | })
88 | );
89 | }
90 |
91 | onWindowResize(): Observable {
92 | const onResize = fromEvent(window, 'resize');
93 | const onScroll = fromEvent(window, 'scroll', { passive: true });
94 | return mergeObs(onResize, onScroll).pipe(
95 | skipWhile(() => !this.config.listenWindowEvents),
96 | takeUntil(this.die),
97 | debounceTime(5),
98 | observeOn(animationFrameScheduler),
99 | distinctUntilChanged(),
100 | tap(() => {
101 | Bus.send(this.tid, 't_dynpos');
102 | this.config.windowResizeCallback();
103 | })
104 | );
105 | }
106 |
107 | changePosition(newPosition: ToppyPosition): void {
108 | this.position = newPosition;
109 | }
110 |
111 | updatePosition(positionConfig: any): void {
112 | this.position.updateConfig(positionConfig);
113 | }
114 |
115 | updateContent(content: ContentData, props: ContentProps = {}): void {
116 | this.content = getContent(content, { ...this.content.props, ...props });
117 | }
118 |
119 | listen(eventName: ToppyEventName) {
120 | return Bus.listen(this.tid, eventName);
121 | }
122 |
123 | private isNotHostElement(el): boolean {
124 | const wrapperEl = this.viewEl.querySelector('.t-wrapper');
125 | return el !== wrapperEl && !wrapperEl.contains(el);
126 | }
127 |
128 | private attach(): void {
129 | /* create component */
130 | this.compFac = this.compResolver.resolveComponentFactory(ToppyComponent);
131 | this.compRef = this.compFac.create(this.injector);
132 | this.comp = this.compRef.instance;
133 |
134 | /* assign props */
135 | const { position, content, config, tid } = this;
136 | content.props.close = this.close.bind(this);
137 | Object.assign(this.comp, { position, content, config, tid });
138 |
139 | /* attach view */
140 | this.hostView = this.compRef.hostView;
141 | this.appRef.attachView(this.hostView);
142 | this.viewEl = (this.hostView as any).rootNodes[0];
143 | BodyEl.appendChild(this.viewEl);
144 | }
145 |
146 | private dettach(): void {
147 | if (!this.hostView) return;
148 |
149 | this.appRef.detachView(this.hostView);
150 | this.compRef.destroy();
151 | this.hostView = this.viewEl = this.comp = null;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/toppy.component.ts:
--------------------------------------------------------------------------------
1 | import {
2 | AfterViewInit,
3 | ChangeDetectionStrategy,
4 | ChangeDetectorRef,
5 | Component,
6 | ComponentFactoryResolver,
7 | ElementRef,
8 | Injector,
9 | OnDestroy,
10 | OnInit,
11 | ViewChild,
12 | ViewContainerRef
13 | } from '@angular/core';
14 | import { Observable, Subject } from 'rxjs';
15 | import { startWith, takeUntil, tap } from 'rxjs/operators';
16 | import { Content, ContentType, TID, ToppyConfig } from './models';
17 | import { ToppyPosition } from './position/position';
18 | import { Bus, cssClass, toCss } from './utils';
19 |
20 | @Component({
21 | // tslint:disable-next-line:component-selector
22 | selector: 'toppy',
23 | templateUrl: './template.html',
24 | styleUrls: ['./styles.scss'],
25 | changeDetection: ChangeDetectionStrategy.OnPush
26 | })
27 | export class ToppyComponent implements OnInit, AfterViewInit, OnDestroy {
28 | @ViewChild('compOutlet', { read: ViewContainerRef }) compOutlet: ViewContainerRef;
29 | content: Content = {
30 | type: ContentType.STRING,
31 | data: '',
32 | props: {}
33 | };
34 | config: ToppyConfig;
35 | position: ToppyPosition;
36 | tid: TID;
37 | el: HTMLElement | any;
38 | wrapperEl: HTMLElement | any;
39 | extra: string;
40 | pinj: any;
41 | compInstance;
42 | private die: Subject<1> = new Subject();
43 |
44 | constructor(
45 | public inj: Injector,
46 | private cd: ChangeDetectorRef,
47 | private compResolver: ComponentFactoryResolver,
48 | private elRef: ElementRef
49 | ) {
50 | this.pinj = Injector;
51 | }
52 |
53 | ngOnInit() {
54 | this.el = this.elRef.nativeElement;
55 | this.wrapperEl = this.el.querySelector('.t-wrapper');
56 | let cls = ['t-container', this.config.containerClass, this.position.getClassName()];
57 | if (this.config.closeOnDocClick) {
58 | cls = cls.concat(['no-pointers']);
59 | }
60 | this.el.setAttribute('data-tid', this.tid);
61 | cssClass('add', cls, `[data-tid='${[this.tid]}']`);
62 | cssClass('add', [this.config.bodyClass]);
63 | }
64 |
65 | ngAfterViewInit() {
66 | this.listenPos().subscribe();
67 | if (this.content.type === ContentType.COMPONENT) {
68 | this.compInstance = this.setComponent(this.content.props);
69 | Bus.send(this.tid, 't_compins', this.compInstance);
70 | }
71 | }
72 |
73 | setComponent(props) {
74 | const compRef = this.compOutlet.createComponent(
75 | this.compResolver.resolveComponentFactory(this.content.data as any)
76 | );
77 | Object.assign(compRef.instance, props);
78 | compRef.changeDetectorRef.detectChanges();
79 | return compRef.instance;
80 | }
81 |
82 | updateTextContent(data: string): void {
83 | if (this.content.type === ContentType.STRING) {
84 | this.content.data = data;
85 | this.cd.detectChanges();
86 | }
87 | }
88 |
89 | ngOnDestroy(): void {
90 | cssClass('remove', [this.config.bodyClass]);
91 | this.die.next(1);
92 | Bus.send(this.tid, 't_detach');
93 | }
94 |
95 | private listenPos(): Observable {
96 | return Bus.listen(this.tid, 't_dynpos').pipe(
97 | startWith(1),
98 | takeUntil(this.die),
99 | tap(e => {
100 | if (!e || !e.x) return this.setPos();
101 | const coords = { left: e.x, top: e.y };
102 | this.wrapperEl.style = toCss(coords);
103 | })
104 | );
105 | }
106 |
107 | private setPos(): void {
108 | const { extra, ...coords } = this.position.getPositions(this.wrapperEl);
109 | if (this.extra !== extra) {
110 | this.extra = extra;
111 | this.cd.detectChanges();
112 | }
113 | Object.assign(coords, { visibility: 'visible', opacity: '1' });
114 | this.wrapperEl.style = toCss(coords);
115 | Bus.send(this.tid, 't_posupdate');
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/toppy.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { ToppyComponent } from './toppy.component';
4 |
5 | @NgModule({
6 | imports: [CommonModule],
7 | declarations: [ToppyComponent],
8 | entryComponents: [ToppyComponent]
9 | })
10 | export class ToppyModule {}
11 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/toppy.ts:
--------------------------------------------------------------------------------
1 | import { ApplicationRef, ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
2 | import { DefaultConfig } from './config';
3 | import { ContentData, ContentProps, ContentType, Inputs, InsidePlacement, TID, ToppyConfig } from './models';
4 | import { GlobalPosition } from './position';
5 | import { ToppyPosition } from './position/position';
6 | import { ToppyControl } from './toppy-control';
7 | import { Bus, createId, getContent } from './utils';
8 |
9 | @Injectable({
10 | providedIn: 'root'
11 | })
12 | export class Toppy {
13 | static controls: { [key: string]: ToppyControl } = {};
14 | private tid: TID;
15 | private inputs: Inputs = {
16 | position: null,
17 | config: DefaultConfig,
18 | content: { type: ContentType.STRING, data: 'hello', props: {} },
19 | tid: null
20 | };
21 |
22 | constructor(private injector: Injector) {
23 | this.inputs.position = new GlobalPosition({ placement: InsidePlacement.TOP });
24 | }
25 |
26 | position(position: ToppyPosition): Toppy {
27 | this.inputs.position = position;
28 | return this;
29 | }
30 |
31 | config(config: Partial): Toppy {
32 | this.inputs.config = { ...DefaultConfig, ...config };
33 | return this;
34 | }
35 |
36 | content(data: ContentData, props: ContentProps = {}): Toppy {
37 | this.inputs.content = getContent(data, props);
38 | return this;
39 | }
40 |
41 | create(key: string = null): ToppyControl {
42 | this.tid = this.inputs.tid = key || createId();
43 |
44 | const injector = Injector.create(
45 | [
46 | {
47 | provide: ToppyControl,
48 | deps: [ApplicationRef, ComponentFactoryResolver, Injector]
49 | }
50 | ],
51 | this.injector
52 | );
53 |
54 | const tc = injector.get(ToppyControl);
55 | if (Toppy.controls[this.tid]) {
56 | this.tid = createId();
57 | }
58 | this.inputs.position.init(this.tid);
59 | Toppy.controls[this.tid] = Object.assign(tc, this.inputs);
60 | return tc;
61 | }
62 |
63 | getCtrl(tid: TID): ToppyControl {
64 | return Toppy.controls[tid];
65 | }
66 |
67 | destroy() {
68 | // tslint:disable-next-line:forin
69 | for (const key in Toppy.controls) {
70 | Toppy.controls[key].close();
71 | }
72 | Toppy.controls = {};
73 | Bus.stop();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/projects/toppy/src/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { TemplateRef } from '@angular/core';
2 | import { Observable, Subject } from 'rxjs';
3 | import { filter, map } from 'rxjs/operators';
4 | import { Content, ContentData, ContentProps, ContentType, ToppyEvent, ToppyEventName } from './models';
5 |
6 | export function getContent(data: ContentData, props: ContentProps = {}): Content {
7 | let type: ContentType = ContentType.COMPONENT;
8 |
9 | if (typeof data === 'string' && props['hasHTML']) type = ContentType.HTML;
10 | else if (typeof data === 'string') type = ContentType.STRING;
11 | else if (data instanceof TemplateRef) type = ContentType.TEMPLATE;
12 |
13 | return { data, type, props };
14 | }
15 |
16 | export function createId() {
17 | return Math.random()
18 | .toString(36)
19 | .substr(2, 5);
20 | }
21 |
22 | /* html dom utils */
23 |
24 | export function cssClass(method: 'add' | 'remove', cls: string[], target: string = 'body') {
25 | document.querySelector(target).classList[method](...cls);
26 | }
27 |
28 | export function toCss(styleObj) {
29 | return Object.keys(styleObj)
30 | .map(x => `${x}:${styleObj[x]}${typeof styleObj[x] === 'number' ? 'px' : ''}`)
31 | .join(';');
32 | }
33 |
34 | export function percentToCss(max, percentage: string): string {
35 | let number = Number(percentage.slice(0, -1));
36 | if (number > 100) {
37 | number = 100;
38 | }
39 | return `calc(${max}px - ${100 - number}%)`;
40 | }
41 |
42 | export function setWH(src, host, key, value) {
43 | if (typeof value === 'number') {
44 | host[key] = value = Math.abs(value);
45 | }
46 |
47 | if (typeof value === 'string' && value.endsWith('%')) {
48 | value = percentToCss(src[key], value);
49 | }
50 |
51 | return value;
52 | }
53 |
54 | export const BodyEl = document.querySelector('body');
55 |
56 | /* events */
57 |
58 | class BusClass {
59 | private _e: Subject = new Subject();
60 | send(from: string, name: ToppyEventName, data: any = null): void {
61 | this._e.next({ from, name, data });
62 | }
63 | listen(from: string, name: ToppyEventName): Observable {
64 | return this._e.asObservable().pipe(
65 | filter(e => e.from === from && e.name === name),
66 | map(e => e.data)
67 | );
68 | }
69 |
70 | stop(): void {
71 | this._e.complete();
72 | }
73 | }
74 | export const Bus = new BusClass();
75 |
--------------------------------------------------------------------------------
/projects/toppy/src/public_api.ts:
--------------------------------------------------------------------------------
1 | export { InsidePlacement, OutsidePlacement, SlidePlacement } from './lib/models';
2 | export { FullscreenPosition, GlobalPosition, RelativePosition, SlidePosition } from './lib/position';
3 | export { Toppy } from './lib/toppy';
4 | export { ToppyControl } from './lib/toppy-control';
5 | export { ToppyModule } from './lib/toppy.module';
6 |
--------------------------------------------------------------------------------
/projects/toppy/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/toppy/src/tests/positions/fullscreen-position.spec.ts:
--------------------------------------------------------------------------------
1 | import { FullscreenPosition } from '../../lib/position';
2 |
3 | describe('@ FullscreenPosition', () => {
4 | describe('#getPositions', () => {
5 | it('should return proper position', () => {
6 | const slidePos = new FullscreenPosition();
7 | expect(slidePos.getPositions()).toEqual({
8 | top: 0,
9 | left: 0,
10 | width: '100%',
11 | height: '100%',
12 | position: 'fixed'
13 | });
14 | });
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/projects/toppy/src/tests/positions/global-position.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { InsidePlacement } from '../../lib/models';
4 | import { GlobalPosition } from '../../lib/position';
5 |
6 | describe('@ GlobalPosition', () => {
7 | let targetElement: HTMLElement;
8 | let hostElement: HTMLElement;
9 | let ww;
10 | let wh;
11 | beforeEach(() => {
12 | targetElement = document.createElement('div');
13 | targetElement.setAttribute('class', 'foobar');
14 | const textnode = document.createTextNode('Hello');
15 | targetElement.appendChild(textnode);
16 | document.getElementsByTagName('body')[0].appendChild(targetElement);
17 |
18 | hostElement = document.createElement('div');
19 | hostElement.setAttribute('class', 'hostelement');
20 | const textnode2 = document.createTextNode('Im host');
21 | hostElement.appendChild(textnode2);
22 | document.getElementsByTagName('body')[0].appendChild(hostElement);
23 | viewport.set(1000, 480);
24 |
25 | ww = window.innerWidth;
26 | wh = window.innerHeight;
27 | });
28 | afterEach(() => {
29 | document.getElementsByTagName('body')[0].removeChild(targetElement);
30 | document.getElementsByTagName('body')[0].removeChild(hostElement);
31 | viewport.set(1000, 480);
32 | });
33 |
34 | it('should have target element in document', () => {
35 | expect(document.querySelector('.foobar').textContent).toBe('Hello');
36 | });
37 | it('should get updated config', () => {
38 | const gloPos = new GlobalPosition({});
39 | gloPos.updateConfig({ offset: 2 });
40 | expect(gloPos['config']).toEqual({
41 | placement: InsidePlacement.CENTER,
42 | width: 100,
43 | height: 100,
44 | offset: 2
45 | });
46 | });
47 | it('should return correct class name', () => {
48 | const gloPos = new GlobalPosition({});
49 | expect(gloPos.getClassName()).toBe('global-position');
50 | });
51 |
52 | describe('#getPositions', () => {
53 | let srcCoords;
54 | beforeEach(() => {
55 | srcCoords = targetElement.getBoundingClientRect();
56 | });
57 | it('when exact width and height is provided in px', () => {
58 | const gloPos = new GlobalPosition({
59 | width: 4,
60 | height: 10,
61 | placement: InsidePlacement.TOP
62 | });
63 | expect(gloPos.getPositions(hostElement)).toEqual({
64 | left: (ww - 4) / 2,
65 | top: 0,
66 | width: 4,
67 | height: 10,
68 | position: 'fixed',
69 | extra: InsidePlacement.TOP
70 | });
71 | });
72 | it('when exact width and height is provided in negative px', () => {
73 | const gloPos = new GlobalPosition({
74 | width: -4,
75 | height: -10,
76 | placement: InsidePlacement.TOP
77 | });
78 | expect(gloPos.getPositions(hostElement)).toEqual({
79 | left: (ww - 4) / 2,
80 | top: 0,
81 | width: 4,
82 | height: 10,
83 | position: 'fixed',
84 | extra: InsidePlacement.TOP
85 | });
86 | });
87 | it('when exact width and height is provided in percentage', () => {
88 | const gloPos = new GlobalPosition({
89 | width: '50%',
90 | height: '50%',
91 | placement: InsidePlacement.TOP
92 | });
93 | expect(gloPos.getPositions(hostElement)).toEqual({
94 | left: (ww - hostElement.offsetWidth) / 2,
95 | top: 0,
96 | width: `calc(${ww}px - 50%)`,
97 | height: `calc(${wh}px - 50%)`,
98 | position: 'fixed',
99 | extra: InsidePlacement.TOP
100 | });
101 | });
102 | it('when exact width and height is provided in higher percentage', () => {
103 | const gloPos = new GlobalPosition({
104 | width: '150%',
105 | height: '150%',
106 | placement: InsidePlacement.TOP
107 | });
108 | expect(gloPos.getPositions(hostElement)).toEqual({
109 | left: (ww - hostElement.offsetWidth) / 2,
110 | top: 0,
111 | width: `calc(${ww}px - 0%)`,
112 | height: `calc(${wh}px - 0%)`,
113 | position: 'fixed',
114 | extra: InsidePlacement.TOP
115 | });
116 | });
117 | it('when no width and height is provided', () => {
118 | const gloPos = new GlobalPosition({ placement: InsidePlacement.TOP_RIGHT });
119 | expect(gloPos.getPositions(hostElement)).toEqual({
120 | right: 0,
121 | top: 0,
122 | width: 100,
123 | height: 100,
124 | position: 'fixed',
125 | extra: InsidePlacement.TOP_RIGHT
126 | });
127 | });
128 | });
129 | describe('#calc', () => {
130 | const targetElCoords = {
131 | width: (window as any).innerWidth,
132 | height: (window as any).innerHeight
133 | };
134 |
135 | const hostElCoords = {
136 | width: 4, // actual 967
137 | height: 10 // actual 18
138 | };
139 | getData().forEach(data => {
140 | it(data.name, () => {
141 | const gloPos = new GlobalPosition({
142 | width: hostElCoords.width,
143 | height: hostElCoords.height,
144 | placement: data.placement,
145 | offset: 2
146 | });
147 | const pos = (gloPos as any).calc(data.placement, targetElCoords, hostElCoords);
148 | expect(pos).toEqual(data.expected);
149 | });
150 | });
151 | });
152 | function getData() {
153 | // offset is 2
154 | ww = window.innerWidth;
155 | wh = window.innerHeight;
156 | const tests = [
157 | {
158 | name: 'bottom',
159 | placement: InsidePlacement.BOTTOM,
160 | method: `calculate_${InsidePlacement.BOTTOM}`,
161 | expected: { left: (ww - 4) / 2, bottom: 2 }
162 | },
163 | {
164 | name: 'top',
165 | placement: InsidePlacement.TOP,
166 | method: `calculate_${InsidePlacement.TOP}`,
167 | expected: { left: (ww - 4) / 2, top: 2 }
168 | },
169 | {
170 | name: 'left',
171 | placement: InsidePlacement.LEFT,
172 | method: `calculate_${InsidePlacement.LEFT}`,
173 | expected: { left: 2, top: (wh - 10) / 2 }
174 | },
175 | {
176 | name: 'right',
177 | placement: InsidePlacement.RIGHT,
178 | method: `calculate_${InsidePlacement.RIGHT}`,
179 | expected: { right: 2, top: (wh - 10) / 2 }
180 | },
181 | {
182 | name: 'center',
183 | placement: InsidePlacement.CENTER,
184 | method: `calculate_${InsidePlacement.CENTER}`,
185 | expected: { left: (ww - 4) / 2, top: (wh - 10) / 2 }
186 | },
187 | {
188 | name: 'top left',
189 | placement: InsidePlacement.TOP_LEFT,
190 | method: `calculate_${InsidePlacement.TOP_LEFT}`,
191 | expected: { left: 2, top: 2 }
192 | },
193 | {
194 | name: 'top right',
195 | placement: InsidePlacement.TOP_RIGHT,
196 | method: `calculate_${InsidePlacement.TOP_RIGHT}`,
197 | expected: { right: 2, top: 2 }
198 | },
199 | {
200 | name: 'bottom left',
201 | placement: InsidePlacement.BOTTOM_LEFT,
202 | method: `calculate_${InsidePlacement.BOTTOM_LEFT}`,
203 | expected: { left: 2, bottom: 2 }
204 | },
205 | {
206 | name: 'bottom right',
207 | placement: InsidePlacement.BOTTOM_RIGHT,
208 | method: `calculate_${InsidePlacement.BOTTOM_RIGHT}`,
209 | expected: { right: 2, bottom: 2 }
210 | }
211 | ];
212 |
213 | return tests;
214 | }
215 | });
216 |
--------------------------------------------------------------------------------
/projects/toppy/src/tests/positions/relative-position.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Subject } from 'rxjs';
4 | import { take } from 'rxjs/operators';
5 | import { Bus } from 'toppy/lib/utils';
6 | import { OutsidePlacement } from '../../lib/models';
7 | import { RelativePosition } from '../../lib/position';
8 |
9 | describe('@ RelativePosition', () => {
10 | let targetElement: HTMLElement;
11 | let hostElement: HTMLElement;
12 | let die: Subject;
13 | beforeEach(() => {
14 | targetElement = document.createElement('div');
15 | targetElement.setAttribute('class', 'foobar');
16 | const textnode = document.createTextNode('Hello');
17 | targetElement.appendChild(textnode);
18 | document.getElementsByTagName('body')[0].appendChild(targetElement);
19 |
20 | hostElement = document.createElement('div');
21 | hostElement.setAttribute('class', 'hostelement');
22 | const textnode2 = document.createTextNode('Im host');
23 | hostElement.appendChild(textnode2);
24 | document.getElementsByTagName('body')[0].appendChild(hostElement);
25 | viewport.set(1000, 480);
26 | });
27 | afterEach(() => {
28 | document.getElementsByTagName('body')[0].removeChild(targetElement);
29 | document.getElementsByTagName('body')[0].removeChild(hostElement);
30 | viewport.set(1000, 480);
31 | });
32 |
33 | beforeEach(() => {
34 | die = new Subject();
35 | Bus['_e'] = new Subject();
36 | });
37 |
38 | afterEach(function() {
39 | die.next(true);
40 | die.complete();
41 | Bus.stop();
42 | });
43 |
44 | it('should have target element in document', () => {
45 | expect(document.querySelector('.foobar').textContent).toBe('Hello');
46 | });
47 | it('should get updated config', () => {
48 | const relPos = new RelativePosition({ src: null });
49 | relPos.updateConfig({ autoUpdate: true });
50 | expect(relPos['config']).toEqual({
51 | src: null,
52 | placement: OutsidePlacement.TOP,
53 | autoUpdate: true,
54 | width: 'auto',
55 | height: 'auto'
56 | });
57 | });
58 | it('should return correct class name', () => {
59 | const relPos = new RelativePosition({ src: null });
60 | expect(relPos.getClassName()).toBe('relative-position');
61 | });
62 |
63 | describe('#autoUpdate', () => {
64 | it('should switch if it is true - case 1', () => {
65 | const relPos = new RelativePosition({
66 | src: targetElement,
67 | placement: OutsidePlacement.TOP,
68 | height: 500,
69 | autoUpdate: true
70 | });
71 | const srcCoords = targetElement.getBoundingClientRect();
72 | const hostElCoords = {
73 | width: 4, // actual 967
74 | height: 450
75 | };
76 | expect((relPos as any).calculatePos(OutsidePlacement.TOP, srcCoords, hostElCoords, true)).toEqual({
77 | props: {
78 | left: 8 + (srcCoords.width - 4) / 2,
79 | top: srcCoords.top + srcCoords.height
80 | },
81 | pos: OutsidePlacement.BOTTOM
82 | });
83 | });
84 | it('should switch if it is true - case 2', () => {
85 | const relPos = new RelativePosition({
86 | src: targetElement,
87 | placement: OutsidePlacement.TOP_LEFT,
88 | height: 500,
89 | autoUpdate: true
90 | });
91 | const srcCoords = targetElement.getBoundingClientRect();
92 | const hostElCoords = {
93 | width: 4, // actual 967
94 | height: 450
95 | };
96 | expect((relPos as any).calculatePos(OutsidePlacement.TOP_LEFT, srcCoords, hostElCoords, true)).toEqual({
97 | props: {
98 | left: 8,
99 | top: srcCoords.top + srcCoords.height
100 | },
101 | pos: OutsidePlacement.BOTTOM_LEFT
102 | });
103 | });
104 | it('should not switch if it is false', () => {
105 | const relPos = new RelativePosition({
106 | src: targetElement,
107 | placement: OutsidePlacement.TOP,
108 | height: 500,
109 | autoUpdate: false
110 | });
111 | const srcCoords = targetElement.getBoundingClientRect();
112 | const hostElCoords = {
113 | width: 4, // actual 967
114 | height: 150
115 | };
116 | expect((relPos as any).calculatePos(OutsidePlacement.TOP, srcCoords, hostElCoords, true)).toEqual({
117 | props: {
118 | left: 8 + (srcCoords.width - 4) / 2,
119 | top: srcCoords.top - 150
120 | },
121 | pos: OutsidePlacement.TOP
122 | });
123 | });
124 | });
125 | describe('#getPositions', () => {
126 | let srcCoords;
127 | beforeEach(() => {
128 | srcCoords = targetElement.getBoundingClientRect();
129 | });
130 | it('when exact width and height is provided', () => {
131 | const relPos = new RelativePosition({
132 | width: 4,
133 | height: 10,
134 | src: targetElement,
135 | placement: OutsidePlacement.TOP
136 | });
137 | expect(relPos.getPositions(hostElement)).toEqual({
138 | left: Math.round(8 + (targetElement.offsetWidth - 4) / 2),
139 | top: Math.round(srcCoords.top - 10),
140 | width: 4,
141 | height: 10,
142 | extra: OutsidePlacement.TOP
143 | });
144 | });
145 | it('when no width and height is provided', () => {
146 | const relPos = new RelativePosition({ src: targetElement, placement: OutsidePlacement.TOP });
147 | expect(relPos.getPositions(hostElement)).toEqual({
148 | left: Math.round(8 + (967 - 967) / 2),
149 | top: Math.round(srcCoords.top - 18),
150 | width: 'auto',
151 | height: 'auto',
152 | extra: OutsidePlacement.TOP
153 | });
154 | });
155 | });
156 | describe('#listenDrag', () => {
157 | let relPos;
158 | beforeEach(() => {
159 | relPos = new RelativePosition({ src: targetElement, autoUpdate: true });
160 | relPos.init('abc');
161 | });
162 |
163 | it('should emit proper event when drag', done => {
164 | Bus.listen('abc', 't_dynpos')
165 | .pipe(take(1))
166 | .subscribe(res => {
167 | expect(res).toEqual(null);
168 | done();
169 | });
170 | targetElement.style.left = '0px';
171 | });
172 | });
173 | describe('#calc', () => {
174 | const targetElCoords = {
175 | bottom: 76,
176 | height: 18,
177 | left: 8,
178 | right: 975,
179 | top: 58,
180 | width: 967
181 | };
182 |
183 | const hostElCoords = {
184 | width: 4, // actual 967
185 | height: 10 // actual 18
186 | };
187 | getData().forEach(data => {
188 | it(data.name, () => {
189 | const relPos = new RelativePosition({
190 | src: targetElement,
191 | width: hostElCoords.width,
192 | height: hostElCoords.height,
193 | placement: data.placement
194 | });
195 | const pos = (relPos as any).calc(data.placement, targetElCoords, hostElCoords);
196 | expect(pos).toEqual(data.expected);
197 | });
198 | });
199 | });
200 | });
201 |
202 | function getData() {
203 | const tests = [
204 | {
205 | name: 'bottom',
206 | placement: OutsidePlacement.BOTTOM,
207 | method: `calculate_${OutsidePlacement.BOTTOM}`,
208 | expected: { left: 8 + (967 - 4) / 2, top: 76 }
209 | },
210 | {
211 | name: 'top',
212 | placement: OutsidePlacement.TOP,
213 | method: `calculate_${OutsidePlacement.TOP}`,
214 | expected: { left: 8 + (967 - 4) / 2, top: 48 }
215 | },
216 | {
217 | name: 'left',
218 | placement: OutsidePlacement.LEFT,
219 | method: `calculate_${OutsidePlacement.LEFT}`,
220 | expected: { left: 8 - 4, top: 58 + (18 - 10) / 2 }
221 | },
222 | {
223 | name: 'right',
224 | placement: OutsidePlacement.RIGHT,
225 | method: `calculate_${OutsidePlacement.RIGHT}`,
226 | expected: { left: 975, top: 58 + (18 - 10) / 2 }
227 | },
228 | {
229 | name: 'top left',
230 | placement: OutsidePlacement.TOP_LEFT,
231 | method: `calculate_${OutsidePlacement.TOP_LEFT}`,
232 | expected: { left: 8, top: 58 - 10 }
233 | },
234 | {
235 | name: 'top right',
236 | placement: OutsidePlacement.TOP_RIGHT,
237 | method: `calculate_${OutsidePlacement.TOP_RIGHT}`,
238 | expected: { left: 8 + (967 - 4), top: 58 - 10 }
239 | },
240 | {
241 | name: 'bottom left',
242 | placement: OutsidePlacement.BOTTOM_LEFT,
243 | method: `calculate_${OutsidePlacement.BOTTOM_LEFT}`,
244 | expected: { left: 8, top: 76 }
245 | },
246 | {
247 | name: 'bottom right',
248 | placement: OutsidePlacement.BOTTOM_RIGHT,
249 | method: `calculate_${OutsidePlacement.BOTTOM_RIGHT}`,
250 | expected: { left: 8 + (967 - 4), top: 76 }
251 | },
252 | {
253 | name: 'right top',
254 | placement: OutsidePlacement.RIGHT_TOP,
255 | method: `calculate_${OutsidePlacement.RIGHT_TOP}`,
256 | expected: { left: 975, top: 58 }
257 | },
258 | {
259 | name: 'right bottom',
260 | placement: OutsidePlacement.RIGHT_BOTTOM,
261 | method: `calculate_${OutsidePlacement.RIGHT_BOTTOM}`,
262 | expected: { left: 975, top: 76 - 10 }
263 | },
264 | {
265 | name: 'left top',
266 | placement: OutsidePlacement.LEFT_TOP,
267 | method: `calculate_${OutsidePlacement.LEFT_TOP}`,
268 | expected: { left: 8 - 4, top: 58 }
269 | },
270 | {
271 | name: 'left bottom',
272 | placement: OutsidePlacement.LEFT_BOTTOM,
273 | method: `calculate_${OutsidePlacement.LEFT_BOTTOM}`,
274 | expected: { left: 8 - 4, top: 76 - 10 }
275 | }
276 | ];
277 |
278 | return tests;
279 | }
280 |
--------------------------------------------------------------------------------
/projects/toppy/src/tests/positions/slide-position.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { SlidePlacement } from '../../lib/models';
4 | import { SlidePosition } from '../../lib/position';
5 |
6 | describe('@ SlidePosition', () => {
7 | describe('#getPositions', () => {
8 | it('should return proper position when placement is left', () => {
9 | const slidePos = new SlidePosition({
10 | width: '200px',
11 | placement: SlidePlacement.LEFT
12 | });
13 | expect(slidePos.getPositions()).toEqual({
14 | left: 0,
15 | top: 0,
16 | width: '200px',
17 | height: '100%',
18 | position: 'fixed',
19 | extra: SlidePlacement.LEFT
20 | });
21 | });
22 | it('should return proper position when placement is right', () => {
23 | const slidePos = new SlidePosition({
24 | width: '500',
25 | placement: SlidePlacement.RIGHT
26 | });
27 | expect(slidePos.getPositions()).toEqual({
28 | right: 0,
29 | top: 0,
30 | width: '500',
31 | height: '100%',
32 | position: 'fixed',
33 | extra: SlidePlacement.RIGHT
34 | });
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/projects/toppy/src/tests/toppy.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { Component, DebugElement, EventEmitter, Input, NgModule, Output } from '@angular/core';
2 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
3 | import { By } from '@angular/platform-browser';
4 | import { Subject } from 'rxjs';
5 | import { skip, switchMap, take } from 'rxjs/operators';
6 | import { DefaultConfig } from '../lib/config';
7 | import { ContentType } from '../lib/models';
8 | import { ToppyComponent } from '../lib/toppy.component';
9 | import { Bus } from '../lib/utils';
10 |
11 | @Component({
12 | selector: 'test-comp',
13 | template: 'Hello {{name||"John"}}'
14 | })
15 | export class TestComponent {
16 | @Input() data = null;
17 | @Output() fire: EventEmitter = new EventEmitter();
18 | name;
19 | }
20 |
21 | @NgModule({
22 | declarations: [TestComponent],
23 | entryComponents: [TestComponent],
24 | exports: [TestComponent]
25 | })
26 | export class TestModule {}
27 |
28 | describe('@ ToppyComponent', () => {
29 | let fixture: ComponentFixture;
30 | let debugEl: DebugElement;
31 | let toppyComp: ToppyComponent;
32 | let el: HTMLElement;
33 | let die: Subject;
34 | beforeEach(async(() => {
35 | TestBed.configureTestingModule({
36 | imports: [TestModule],
37 | declarations: [ToppyComponent]
38 | }).compileComponents();
39 | fixture = TestBed.createComponent(ToppyComponent);
40 | debugEl = fixture.debugElement;
41 | el = debugEl.nativeElement;
42 | toppyComp = fixture.componentInstance;
43 | }));
44 |
45 | beforeEach(() => {
46 | toppyComp.tid = 'abc';
47 | toppyComp.config = { ...DefaultConfig, bodyClass: 'zzz' };
48 | toppyComp.position = {
49 | getClassName: () => 'relative',
50 | getPositions: c => ({ left: 45, top: 79, extra: 't' })
51 | } as any;
52 | die = new Subject();
53 | Bus['_e'] = new Subject();
54 | });
55 |
56 | afterEach(() => {
57 | fixture.destroy();
58 | die.next(true);
59 | die.complete();
60 | Bus.stop();
61 | });
62 |
63 | it('should be initialized', () => {
64 | expect(toppyComp).toBeTruthy();
65 | });
66 | describe('#ngOnInit', () => {
67 | it('should add data-tid attribute', () => {
68 | fixture.detectChanges();
69 | expect(el.getAttribute('data-tid')).toEqual('abc');
70 | });
71 | it('should add default classes', () => {
72 | fixture.detectChanges();
73 | expect(el.classList.value).toBe('t-container t-overlay relative');
74 | });
75 | it('should add class for docClick', () => {
76 | toppyComp.config.closeOnDocClick = true;
77 | fixture.detectChanges();
78 | expect(el.classList.value).toBe('t-container t-overlay relative no-pointers');
79 | });
80 | it('should add class for bodyClass', () => {
81 | fixture.detectChanges();
82 | expect(document.querySelector('body').classList.value).toEqual('zzz');
83 | });
84 | });
85 |
86 | describe('#ngAfterViewInit', () => {
87 | it('should call setPos', () => {
88 | fixture.detectChanges();
89 | spyOn(toppyComp as any, 'setPos');
90 | toppyComp.ngAfterViewInit();
91 | expect(toppyComp['setPos']).toHaveBeenCalled();
92 | });
93 | it('should subscribe to triggerPosChange', () => {
94 | spyOn(toppyComp as any, 'setPos');
95 | fixture.detectChanges();
96 | toppyComp.ngAfterViewInit();
97 | expect(toppyComp['setPos']).toHaveBeenCalled();
98 | });
99 | it('should subscribe to listenPos', () => {
100 | fixture.detectChanges();
101 | spyOn(toppyComp as any, 'setPos');
102 | Bus.send('abc', 't_dynpos', null);
103 | toppyComp.ngAfterViewInit();
104 | expect(toppyComp['setPos']).toHaveBeenCalled();
105 | });
106 | it('should subscribe to listenPos when custom data is arraived', () => {
107 | fixture.detectChanges();
108 | toppyComp.ngAfterViewInit();
109 | Bus.send('abc', 't_dynpos', { x: 10, y: 12 });
110 | expect(el.querySelector('.t-wrapper').getAttribute('style')).toEqual('left: 10px; top: 12px;');
111 | });
112 | it('should render custom props in the template', () => {
113 | toppyComp.content.data = TestComponent;
114 | toppyComp.content.type = ContentType.COMPONENT;
115 | toppyComp.content.props = {
116 | name: 'Peter',
117 | id: 22
118 | };
119 | fixture.detectChanges();
120 | expect(fixture.debugElement.query(By.css('test-comp')).nativeElement.textContent).toBe('Hello Peter');
121 | });
122 | it('should emit host component instance', done => {
123 | toppyComp.content.data = TestComponent;
124 | toppyComp.content.type = ContentType.COMPONENT;
125 | toppyComp.content.props = {
126 | name: 'Loky'
127 | };
128 | fixture.detectChanges();
129 | Bus.listen('abc', 't_compins').subscribe(data => {
130 | expect(data.name).toEqual('Loky');
131 | done();
132 | });
133 | toppyComp.ngAfterViewInit();
134 | });
135 | it('should able to access "@Output()"', done => {
136 | toppyComp.content.data = TestComponent;
137 | toppyComp.content.type = ContentType.COMPONENT;
138 | toppyComp.content.props = { name: 'SSSS' };
139 | fixture.detectChanges();
140 | Bus.listen('abc', 't_compins')
141 | .pipe(switchMap(a => a['fire']))
142 | .subscribe(data => {
143 | expect(data).toEqual('ABCXYZ');
144 | done();
145 | });
146 | toppyComp.ngAfterViewInit();
147 | toppyComp.compInstance.fire.emit('ABCXYZ');
148 | });
149 | });
150 |
151 | describe('#updateTextContent', () => {
152 | it('should not change the text if the content is not string', () => {
153 | toppyComp.content = {
154 | data: 'DUMMY',
155 | props: {},
156 | type: ContentType.HTML
157 | };
158 | const text = 'Little cute Dog';
159 | toppyComp.updateTextContent(text);
160 | fixture.detectChanges();
161 | expect(debugEl.query(By.css('.t-wrapper div')).nativeElement.textContent).toEqual('DUMMY');
162 | });
163 | it('should change the text content in template', () => {
164 | const text = 'Little cute Dog';
165 | toppyComp.updateTextContent(text);
166 | fixture.detectChanges();
167 | expect(debugEl.query(By.css('.t-wrapper div')).nativeElement.textContent).toEqual(text);
168 | });
169 | });
170 |
171 | describe('#ngOnDestroy', () => {
172 | it('should remove class name from body', () => {
173 | toppyComp.config.bodyClass = 'Bunny';
174 | fixture.detectChanges();
175 | expect(document.querySelector('body').classList.value).toEqual('Bunny');
176 | fixture.destroy();
177 | expect(document.querySelector('body').classList.value).toEqual('');
178 | });
179 | it('should unsubscribe all events', () => {
180 | spyOn(toppyComp as any, 'setPos');
181 | toppyComp.ngAfterViewInit();
182 | Bus.send('abc', 't_dynpos');
183 | expect(toppyComp['setPos']).toHaveBeenCalledTimes(2);
184 | fixture.destroy();
185 | Bus.send('abc', 't_dynpos');
186 | expect(toppyComp['setPos']).toHaveBeenCalledTimes(2);
187 | });
188 | it('should fire t_detach event', () => {
189 | const spy = jasmine.createSpy().and.callThrough();
190 | Bus.listen('abc', 't_detach')
191 | .pipe(take(1))
192 | .subscribe(() => {
193 | spy();
194 | spy();
195 | });
196 | fixture.destroy();
197 | expect(spy.calls.count()).toEqual(2);
198 | });
199 | });
200 |
201 | describe('#listenPos', () => {
202 | it('should return new position', done => {
203 | fixture.detectChanges();
204 | toppyComp['listenPos']().subscribe(data => {
205 | expect(data).toEqual(1);
206 | done();
207 | });
208 | });
209 | it('should add styles', done => {
210 | fixture.detectChanges();
211 | toppyComp['listenPos']()
212 | .pipe(take(1))
213 | .subscribe(() => {
214 | expect(el.querySelector('.t-wrapper').getAttribute('style')).toEqual(
215 | 'left: 45px; top: 79px; visibility: visible; opacity: 1;'
216 | );
217 | done();
218 | });
219 | });
220 | it('should add styles', done => {
221 | fixture.detectChanges();
222 | toppyComp['listenPos']()
223 | .pipe(skip(1))
224 | .subscribe(() => {
225 | expect(el.querySelector('.t-wrapper').getAttribute('style')).toEqual('left: 99px; top: 22px;');
226 | done();
227 | });
228 | Bus.send('abc', 't_dynpos', { x: 99, y: 22 });
229 | });
230 | });
231 |
232 | describe('#setPos', () => {
233 | it('should set positions to wrapper element', () => {
234 | fixture.detectChanges();
235 | toppyComp['setPos']();
236 | expect(el.querySelector('.t-wrapper').getAttribute('style')).toEqual(
237 | 'left: 45px; top: 79px; visibility: visible; opacity: 1;'
238 | );
239 | });
240 | it('should emit position change event', () => {
241 | const spy = jasmine.createSpy().and.callThrough();
242 | fixture.detectChanges();
243 | Bus.listen('abc', 't_posupdate')
244 | .pipe(take(1))
245 | .subscribe(() => {
246 | spy();
247 | spy();
248 | spy();
249 | });
250 | toppyComp['setPos']();
251 | expect(spy.calls.count()).toEqual(3);
252 | });
253 | it('should set extra class to wrapper element', () => {
254 | fixture.detectChanges();
255 | toppyComp['setPos']();
256 | expect(el.querySelector('.t-wrapper').classList.value).toEqual('t-wrapper t');
257 | });
258 | });
259 |
260 | describe('#config', () => {
261 | it('should set custom class names', () => {
262 | toppyComp.config.backdrop = true;
263 | toppyComp.config.wrapperClass = 'custom-wrapper-class';
264 | toppyComp.config.backdropClass = 'custom-backdrop-class';
265 | fixture.detectChanges();
266 | expect(el.querySelector('.t-wrapper').classList.value).toEqual('t-wrapper custom-wrapper-class t');
267 | expect(el.querySelector('.t-backdrop').classList.value).toEqual('t-backdrop custom-backdrop-class');
268 | });
269 | });
270 | });
271 |
--------------------------------------------------------------------------------
/projects/toppy/src/tests/toppy.spec.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ApplicationRef,
3 | Component,
4 | ComponentFactoryResolver,
5 | ElementRef,
6 | Injector,
7 | NgModule,
8 | TemplateRef,
9 | ViewChild
10 | } from '@angular/core';
11 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
12 | import { Subject } from 'rxjs';
13 | import { DefaultConfig } from '../lib/config';
14 | import { ContentType } from '../lib/models';
15 | import { GlobalPosition, RelativePosition } from '../lib/position';
16 | import { Toppy } from '../lib/toppy';
17 | import { ToppyControl } from '../lib/toppy-control';
18 | import { Bus } from '../lib/utils';
19 |
20 | @Component({
21 | selector: 'lib-template-ref-test-comp',
22 | template: `
23 | some content
24 | I am template
25 | `
26 | })
27 | export class TemplateRefTestComponent {
28 | @ViewChild('el', { read: ElementRef }) el: ElementRef;
29 | @ViewChild('tpl', { read: TemplateRef }) tpl;
30 | constructor(private toppy: Toppy) {}
31 | }
32 |
33 | @Component({
34 | template: 'Hi'
35 | })
36 | export class TestComponent {}
37 |
38 | @NgModule({
39 | declarations: [TestComponent, TemplateRefTestComponent],
40 | entryComponents: [TestComponent]
41 | })
42 | export class TemplateRefTestModule {}
43 |
44 | describe('@ Toppy', () => {
45 | let toppy: Toppy = null;
46 | let templateRefCompFixture: ComponentFixture;
47 | let templateRefComp: TemplateRefTestComponent;
48 | let appRef, compFact, inj;
49 | const config = DefaultConfig;
50 |
51 | beforeEach(async(() => {
52 | TestBed.configureTestingModule({
53 | imports: [TemplateRefTestModule],
54 | declarations: [],
55 | providers: [ApplicationRef, ComponentFactoryResolver, Injector]
56 | }).compileComponents();
57 |
58 | templateRefCompFixture = TestBed.createComponent(TemplateRefTestComponent);
59 | templateRefComp = templateRefCompFixture.componentInstance;
60 | toppy = TestBed.get(Toppy);
61 | appRef = TestBed.get(ApplicationRef);
62 | compFact = TestBed.get(ComponentFactoryResolver);
63 | inj = TestBed.get(Injector);
64 | spyOn(toppy, 'destroy').and.callThrough();
65 | }));
66 |
67 | afterEach(function() {
68 | templateRefCompFixture.destroy();
69 | document.querySelector('body').removeChild(templateRefCompFixture.debugElement.nativeElement);
70 | });
71 | afterAll(() => {
72 | Bus['_e'] = new Subject();
73 | });
74 |
75 | it('should be initialized', () => {
76 | expect(toppy).toBeTruthy();
77 | });
78 |
79 | describe('#basic', () => {
80 | let ctrl: ToppyControl;
81 | beforeEach(() => {
82 | ctrl = toppy.create();
83 | });
84 | afterEach(() => {
85 | toppy.destroy();
86 | });
87 | it('should return "ToppyControl"', () => {
88 | expect(ctrl instanceof ToppyControl).toBeTruthy();
89 | });
90 | it('should have default "GlobalPosition"', () => {
91 | expect(ctrl.position instanceof GlobalPosition).toBeTruthy();
92 | });
93 | it('should have default config', () => {
94 | expect(ctrl.config).toEqual(DefaultConfig);
95 | });
96 | it('should have default text content', () => {
97 | expect(ctrl.content).toEqual({ data: 'hello', type: ContentType.STRING, props: {} });
98 | });
99 | it('should add control to toppy', () => {
100 | expect(Object.keys(Toppy.controls).length).toEqual(1);
101 | });
102 | });
103 | describe('#config|#position|#content', () => {
104 | let ctrl: ToppyControl;
105 | let tid: string;
106 | beforeEach(() => {
107 | ctrl = toppy
108 | .position(new RelativePosition({ src: templateRefComp.el.nativeElement }))
109 | .config({ backdropClass: 't-custom-backdrop' })
110 | .content('random text')
111 | .create();
112 | tid = toppy['tid'];
113 | });
114 | afterEach(() => {
115 | toppy.destroy();
116 | });
117 | it('should set custom config in "Toppy"', () => {
118 | expect((toppy as any).inputs.config).toEqual({ ...DefaultConfig, backdropClass: 't-custom-backdrop' });
119 | });
120 | it('should set custom config in "ToppyControl"', () => {
121 | expect(toppy.getCtrl(tid).config).toEqual({ ...DefaultConfig, backdropClass: 't-custom-backdrop' });
122 | });
123 | it('should set custom position in "Toppy"', () => {
124 | expect((toppy as any).inputs.position instanceof RelativePosition).toBeTruthy();
125 | });
126 | it('should set custom position in "ToppyControl"', () => {
127 | expect(toppy.getCtrl(tid).position instanceof RelativePosition).toBeTruthy();
128 | });
129 | it('should set custom content in "Toppy"', () => {
130 | expect((toppy as any).inputs.content).toEqual({
131 | type: ContentType.STRING,
132 | data: 'random text',
133 | props: {}
134 | });
135 | });
136 | it('should set custom content in "ToppyControl"', () => {
137 | expect(toppy.getCtrl(tid).content).toEqual({ type: ContentType.STRING, data: 'random text', props: {} });
138 | });
139 | });
140 | describe('#content', () => {
141 | let t: Toppy;
142 | let tid: string;
143 | beforeEach(() => {
144 | t = toppy
145 | .position(new RelativePosition({ src: templateRefComp.el.nativeElement }))
146 | .config({ backdropClass: 't-custom-backdrop' });
147 | });
148 | afterEach(() => {
149 | toppy.destroy();
150 | });
151 | describe('should return content type as STRING', () => {
152 | it('when without props', () => {
153 | t.content('hello').create();
154 | tid = toppy['tid'];
155 | expect(toppy.getCtrl(tid).content).toEqual({ type: ContentType.STRING, data: 'hello', props: {} });
156 | });
157 | it('when with props', () => {
158 | t.content('hello', { class: 'abc' }).create();
159 | tid = toppy['tid'];
160 | expect(toppy.getCtrl(tid).content).toEqual({
161 | type: ContentType.STRING,
162 | data: 'hello',
163 | props: { class: 'abc' }
164 | });
165 | });
166 | });
167 | describe('should return content type as HTML', () => {
168 | it('when without props', () => {
169 | t.content('hello ').create();
170 | tid = toppy['tid'];
171 | expect(toppy.getCtrl(tid).content).toEqual({
172 | type: ContentType.STRING,
173 | data: 'hello ',
174 | props: {}
175 | });
176 | });
177 | it('when with props', () => {
178 | t.content('hello ', { hasHTML: true }).create();
179 | tid = toppy['tid'];
180 | expect(toppy.getCtrl(tid).content).toEqual({
181 | type: ContentType.HTML,
182 | data: 'hello ',
183 | props: { hasHTML: true }
184 | });
185 | });
186 | });
187 | describe('should return content type as TEMPLATE', () => {
188 | it('when without props', () => {
189 | t.content(templateRefComp.tpl).create();
190 | tid = toppy['tid'];
191 | expect(toppy.getCtrl(tid).content).toEqual({
192 | type: ContentType.TEMPLATE,
193 | data: templateRefComp.tpl,
194 | props: {}
195 | });
196 | });
197 | it('when with props', () => {
198 | t.content(templateRefComp.tpl, { name: 'Johny' }).create();
199 | tid = toppy['tid'];
200 | expect(toppy.getCtrl(tid).content).toEqual({
201 | type: ContentType.TEMPLATE,
202 | data: templateRefComp.tpl,
203 | props: { name: 'Johny' }
204 | });
205 | });
206 | });
207 | describe('should return content type as COMPONENT', () => {
208 | it('when without props', () => {
209 | t.content(TestComponent).create();
210 | tid = toppy['tid'];
211 | expect(toppy.getCtrl(tid).content).toEqual({
212 | type: ContentType.COMPONENT,
213 | data: TestComponent,
214 | props: {}
215 | });
216 | });
217 | it('when with props', () => {
218 | t.content(TestComponent, { name: 'Johny' }).create();
219 | tid = toppy['tid'];
220 | expect(toppy.getCtrl(tid).content).toEqual({
221 | type: ContentType.COMPONENT,
222 | data: TestComponent,
223 | props: { name: 'Johny' }
224 | });
225 | });
226 | });
227 | });
228 | describe('#create', () => {
229 | let ctrl1: ToppyControl;
230 | let t: Toppy;
231 | let firstTid, secondTid;
232 | beforeEach(() => {
233 | ctrl1 = toppy.create();
234 | firstTid = toppy['tid'];
235 |
236 | t = toppy.content('abc');
237 | (t as any).tid = firstTid;
238 | t.create();
239 | secondTid = toppy['tid'];
240 | });
241 | afterEach(() => {
242 | toppy.destroy();
243 | });
244 | it('should create new instance if the tid already exists', () => {
245 | expect(Object.keys(Toppy.controls)).toEqual([firstTid, secondTid]);
246 | });
247 | it('should add multiple new instances', () => {
248 | toppy.create();
249 | toppy.create();
250 | toppy.create();
251 | expect(Object.keys(Toppy.controls).length).toEqual(5);
252 | });
253 | it('should add new instance with custom key', () => {
254 | toppy.create('JKL');
255 | expect(Object.keys(Toppy.controls)).toContain('JKL');
256 | });
257 | it('should create new key if same key already exists', () => {
258 | toppy.create('ABCD');
259 | toppy.create('ABCD');
260 | expect(Object.keys(Toppy.controls).length).toEqual(4);
261 | expect(Object.keys(Toppy.controls).filter(x => x === 'ABCD').length).toEqual(1);
262 | });
263 | });
264 | describe('#destroy', () => {
265 | it('should remove all controls', () => {
266 | toppy.create();
267 | toppy.create();
268 | toppy.create();
269 | toppy.create();
270 |
271 | toppy.destroy();
272 | expect(Object.keys(Toppy.controls).length).toEqual(0);
273 | });
274 | });
275 | });
276 |
--------------------------------------------------------------------------------
/projects/toppy/src/tests/utils.spec.ts:
--------------------------------------------------------------------------------
1 | import { Component, TemplateRef, ViewChild } from '@angular/core';
2 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
3 | import { Subject } from 'rxjs';
4 | import { takeUntil } from 'rxjs/operators';
5 | import { ContentType } from '../lib/models';
6 | import { Bus, getContent } from '../lib/utils';
7 |
8 | @Component({
9 | selector: 'lib-test-component',
10 | template: `
11 | Hello
12 | I am a template!
13 | `
14 | })
15 | export class TestComponent {
16 | @ViewChild('tpl', { read: TemplateRef }) tpl: TemplateRef;
17 | }
18 |
19 | describe('@ Utils', () => {
20 | let component: TestComponent = null;
21 | let fixture: ComponentFixture = null;
22 | beforeEach(async(() => {
23 | TestBed.configureTestingModule({
24 | declarations: [TestComponent],
25 | providers: []
26 | }).compileComponents();
27 | fixture = TestBed.createComponent(TestComponent);
28 | component = fixture.componentInstance;
29 | }));
30 | afterEach(function() {
31 | fixture.destroy();
32 | document.body.removeChild(fixture.debugElement.nativeElement);
33 | });
34 |
35 | describe('#getContent', () => {
36 | it('should return as string type', () => {
37 | const result = getContent('hello');
38 | expect(result).toEqual({ data: 'hello', props: {}, type: ContentType.STRING });
39 | });
40 | it('should return html type', () => {
41 | const result = getContent('Hello
', { hasHTML: true });
42 | expect(result).toEqual({
43 | data: 'Hello
',
44 | props: { hasHTML: true },
45 | type: ContentType.HTML
46 | });
47 | });
48 | it('should return component type', () => {
49 | const result = getContent(fixture as any);
50 | expect(result as any).toEqual({ data: fixture, props: {}, type: ContentType.COMPONENT });
51 | });
52 | it('should return component type with props', () => {
53 | const result: any = getContent(fixture as any, { name: 'john' });
54 | expect(result).toEqual({
55 | data: fixture,
56 | props: { name: 'john' },
57 | type: ContentType.COMPONENT
58 | } as any);
59 | });
60 | it('should return component type with overlay id', () => {
61 | const result = getContent(fixture as any, { id: 'XYZ' });
62 | expect(result as any).toEqual({ data: fixture, props: { id: 'XYZ' }, type: ContentType.COMPONENT });
63 | });
64 | it('should return template type', () => {
65 | const result = getContent(component.tpl, { id: 'ABC' });
66 | expect(result as any).toEqual({ data: component.tpl, type: ContentType.TEMPLATE, props: { id: 'ABC' } });
67 | });
68 | });
69 | describe('#BusClass', () => {
70 | let die: Subject;
71 | // spyOn(Bus,'stop').and.callFake();
72 | beforeEach(() => {
73 | die = new Subject();
74 | Bus['_e'] = new Subject();
75 | });
76 | afterEach(() => {
77 | die.next(true);
78 | die.complete();
79 | Bus.stop();
80 | });
81 | afterAll(() => {
82 | Bus['_e'] = new Subject();
83 | });
84 | it('should send event on calling `sent` method', done => {
85 | Bus.listen('abc', 't_open')
86 | .pipe(takeUntil(die))
87 | .subscribe(data => {
88 | expect(data).toEqual({ test: true });
89 | done();
90 | });
91 | Bus.send('abc', 't_open', { test: true });
92 | });
93 | it('should send multiple event on calling many `sent` method', done => {
94 | const spy = jasmine.createSpy('spy').and.callThrough();
95 | Bus.listen('xyz', 't_detach')
96 | .pipe(takeUntil(die))
97 | .subscribe(() => {
98 | spy();
99 | done();
100 | });
101 | Bus.send('xyz', 't_detach', `qwerty`);
102 | Bus.send('xyz', 't_detach', `home`);
103 | Bus.send('xyz', 't_detach', `Bakery`);
104 | expect(spy.calls.count()).toEqual(3);
105 | });
106 | it('should complete the emission on calling `stop` method', done => {
107 | const spy = jasmine.createSpy('spy').and.callThrough();
108 | Bus.listen('xyz', 't_dynpos')
109 | .pipe(takeUntil(die))
110 | .subscribe(
111 | data => {
112 | spy();
113 | },
114 | null,
115 | () => {
116 | done();
117 | }
118 | );
119 | Bus.send('xyz', 't_dynpos', `qwerty`);
120 | Bus.send('xyz', 't_dynpos', `home`);
121 | Bus.stop();
122 | Bus.send('xyz', 't_dynpos', `Bakery`);
123 | expect(spy.calls.count()).toEqual(2);
124 | });
125 | });
126 | });
127 |
--------------------------------------------------------------------------------
/projects/toppy/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.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 | "es2018"
18 | ]
19 | },
20 | "angularCompilerOptions": {
21 | "annotateForClosureCompiler": true,
22 | "skipTemplateCodegen": true,
23 | "strictMetadataEmit": true,
24 | "fullTemplateTypeCheck": true,
25 | "strictInjectionParameters": true,
26 | "enableResourceInlining": true
27 | },
28 | "exclude": [
29 | "src/test.ts",
30 | "**/*.spec.ts"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/projects/toppy/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.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/toppy/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [true, "attribute", "lib", "camelCase"],
5 | "component-selector": [true, "element", "lib", "kebab-case"],
6 | "curly": [true, "ignore-same-line"]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/scripts/archive.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const version = process.argv[2];
3 | const archiveMetaFile = './docs/assets/archived-versions.json';
4 |
5 | async function archiveFiles() {
6 | try {
7 | await fs.copy('./dist/toppy-app', `./dist/${version}`);
8 | await fs.copy(`./dist/${version}`, `./dist/toppy-app/${version}`);
9 | let archivedData = await fs.readJson(archiveMetaFile);
10 | archivedData = archivedData || {};
11 | archivedData[version] = Date.now();
12 | await fs.writeJson(archiveMetaFile, archivedData);
13 | console.log(`successfully archived version ${version}!`);
14 | } catch (err) {
15 | console.error(err);
16 | }
17 | }
18 |
19 | archiveFiles();
20 |
--------------------------------------------------------------------------------
/scripts/build-md.js:
--------------------------------------------------------------------------------
1 | const execa = require('execa');
2 | const fs = require('fs-extra');
3 | const Listr = require('listr');
4 | const sane = require('sane');
5 | var unified = require('unified');
6 | var markdown = require('remark-parse');
7 | var html = require('remark-html');
8 | var bracketedSpans = require('remark-bracketed-spans');
9 | const replace = require('replace-in-file');
10 | const stringify = require('rehype-stringify');
11 | var highlight = require('rehype-highlight');
12 | const remarkAttr = require('remark-attr');
13 | const remark2rehype = require('remark-rehype');
14 | const slug = require('remark-slug');
15 | const headings = require('remark-autolink-headings');
16 | var raw = require('rehype-raw');
17 | var format = require('rehype-format');
18 | var watcher = sane('./docs/markdown', { glob: ['**/*.md'] });
19 |
20 | const tasks = new Listr([
21 | {
22 | title: 'fetch contents',
23 | task: ctx => {
24 | return fs.readFile('./docs/markdown/main.md', 'utf8').then(c => (ctx.contents = c));
25 | }
26 | },
27 | {
28 | title: 'converting markdown to html',
29 | task: ctx => {
30 | return unified()
31 | .use(markdown)
32 | .use(remarkAttr)
33 | .use(bracketedSpans)
34 | .use(slug)
35 | .use(headings, { behaviour: 'wrap' })
36 | .use(remark2rehype, { allowDangerousHTML: true })
37 | .use(raw)
38 | .use(format)
39 | .use(highlight)
40 | .use(stringify)
41 | .process(ctx.contents)
42 | .then(c => String(c))
43 | .then(c => (ctx.contents = c));
44 | }
45 | },
46 | {
47 | title: 'file contents changed',
48 | task: ctx => {
49 | return fs.outputFile('./docs/app/utils/content/content.component.html', ctx.contents);
50 | }
51 | },
52 | {
53 | title: 'replace braces',
54 | task: ctx => {
55 | return replace({
56 | files: './docs/app/utils/content/content.component.html',
57 | from: [/\{/g, /\}/g],
58 | to: ['{', '}']
59 | }).then(c => (ctx.contents = c));
60 | }
61 | },
62 | {
63 | title: 'replace links',
64 | task: ctx => {
65 | return replace({
66 | files: './docs/app/utils/content/content.component.html',
67 | from: [/(span-classtoppy-icon-icon-)(.+?)--span-/g],
68 | to: ['']
69 | }).then(c => (ctx.contents = c));
70 | }
71 | }
72 | ]);
73 |
74 | watcher.on('change', () => {
75 | tasks.run().catch(err => {
76 | console.error(err);
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/scripts/gh-pages.js:
--------------------------------------------------------------------------------
1 | const ghpages = require('gh-pages');
2 | ghpages.publish(
3 | './dist/toppy-app',
4 | {
5 | repo: 'https://' + process.env.GH_TOKEN + '@github.com/lokesh-coder/toppy.git',
6 | add: true
7 | },
8 | function(err) {
9 | if (err) {
10 | console.log('Error occured during gh pages push', err);
11 | } else {
12 | console.log('Pushed to ghpages!');
13 | }
14 | }
15 | );
16 |
--------------------------------------------------------------------------------
/scripts/version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "The version would be: $1"
3 | echo "export const TOPPY_VERSION='$1'" > ./docs/environments/version.ts
4 | echo "Version file updated!"
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "module": "es2015",
9 | "moduleResolution": "node",
10 | "emitDecoratorMetadata": true,
11 | "experimentalDecorators": true,
12 | "target": "es5",
13 | "typeRoots": ["node_modules/@types"],
14 | "lib": ["es2018", "dom"],
15 | "paths": {
16 | "toppy": ["projects/toppy/src/public_api.ts"],
17 | "toppy/*": ["projects/toppy/src/*"]
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warn"
16 | },
17 | "eofline": true,
18 | "forin": true,
19 | "import-blacklist": [
20 | true,
21 | "rxjs/Rx"
22 | ],
23 | "import-spacing": true,
24 | "indent": [
25 | true,
26 | "spaces"
27 | ],
28 | "interface-over-type-literal": true,
29 | "label-position": true,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-arg": true,
47 | "no-bitwise": true,
48 | "no-console": [
49 | true,
50 | "debug",
51 | "info",
52 | "time",
53 | "timeEnd",
54 | "trace"
55 | ],
56 | "no-construct": true,
57 | "no-debugger": true,
58 | "no-duplicate-super": true,
59 | "no-empty": false,
60 | "no-empty-interface": true,
61 | "no-eval": true,
62 | "no-inferrable-types": [
63 | true,
64 | "ignore-params"
65 | ],
66 | "no-misused-new": true,
67 | "no-non-null-assertion": true,
68 | "no-redundant-jsdoc": true,
69 | "no-shadowed-variable": true,
70 | "no-string-literal": false,
71 | "no-string-throw": true,
72 | "no-switch-case-fall-through": true,
73 | "no-trailing-whitespace": true,
74 | "no-unnecessary-initializer": true,
75 | "no-unused-expression": true,
76 | "no-use-before-declare": true,
77 | "no-var-keyword": true,
78 | "object-literal-sort-keys": false,
79 | "one-line": [
80 | true,
81 | "check-open-brace",
82 | "check-catch",
83 | "check-else",
84 | "check-whitespace"
85 | ],
86 | "prefer-const": true,
87 | "quotemark": [
88 | true,
89 | "single"
90 | ],
91 | "radix": true,
92 | "semicolon": [
93 | true,
94 | "always"
95 | ],
96 | "triple-equals": [
97 | true,
98 | "allow-null-check"
99 | ],
100 | "typedef-whitespace": [
101 | true,
102 | {
103 | "call-signature": "nospace",
104 | "index-signature": "nospace",
105 | "parameter": "nospace",
106 | "property-declaration": "nospace",
107 | "variable-declaration": "nospace"
108 | }
109 | ],
110 | "unified-signatures": true,
111 | "variable-name": false,
112 | "whitespace": [
113 | true,
114 | "check-branch",
115 | "check-decl",
116 | "check-operator",
117 | "check-separator",
118 | "check-type"
119 | ],
120 | "no-output-on-prefix": true,
121 | "use-input-property-decorator": true,
122 | "use-output-property-decorator": true,
123 | "use-host-property-decorator": true,
124 | "no-input-rename": true,
125 | "no-output-rename": true,
126 | "use-life-cycle-interface": true,
127 | "use-pipe-transform-interface": true,
128 | "component-class-suffix": true,
129 | "directive-class-suffix": true
130 | }
131 | }
132 |
--------------------------------------------------------------------------------