├── .editorconfig
├── .eslintrc.json
├── .github
└── workflows
│ └── nodejs.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── projects
└── angular-busy2
│ ├── .eslintrc.json
│ ├── LICENSE
│ ├── README.md
│ ├── ng-package.json
│ ├── package.json
│ ├── src
│ ├── lib
│ │ ├── cgBusy.component.css
│ │ ├── cgBusy.component.html
│ │ ├── cgBusy.component.ts
│ │ ├── cgBusy.directive.ts
│ │ ├── cgBusy.interface.ts
│ │ ├── cgBusy.module.ts
│ │ ├── cgBusy.service.ts
│ │ └── cgBusyDefaults.service.ts
│ └── public_api.ts
│ ├── tsconfig.lib.json
│ ├── tsconfig.lib.lint.json
│ ├── tsconfig.lib.prod.json
│ └── tsconfig.spec.json
├── src
├── app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.ts
│ └── app.config.ts
├── assets
│ ├── favicon.ico
│ └── finalfantasy.gif
├── index.html
├── main.ts
├── styles.css
└── theme.scss
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.lint.json
└── tsconfig.spec.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://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 | [*.ts]
12 | quote_type = single
13 | ij_typescript_use_double_quotes = false
14 |
15 | [*.md]
16 | max_line_length = off
17 | trim_trailing_whitespace = false
18 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "ignorePatterns": [
4 | "projects/**/*"
5 | ],
6 | "overrides": [
7 | {
8 | "files": [
9 | "*.ts"
10 | ],
11 | "parserOptions": {
12 | "project": [
13 | "tsconfig.lint.json",
14 | "tsconfig.spec.json"
15 | ]
16 | },
17 | "plugins": [
18 | "@typescript-eslint"
19 | ],
20 | "extends": [
21 | "plugin:@angular-eslint/recommended",
22 | "plugin:@angular-eslint/template/process-inline-templates"
23 | ],
24 | "rules": {
25 | "@angular-eslint/component-selector": [
26 | "error",
27 | {
28 | "prefix": "app",
29 | "style": "kebab-case",
30 | "type": "element"
31 | }
32 | ],
33 | "@angular-eslint/directive-selector": [
34 | "error",
35 | {
36 | "prefix": "app",
37 | "style": "camelCase",
38 | "type": "attribute"
39 | }
40 | ]
41 | }
42 | },
43 | {
44 | "files": [
45 | "*.html"
46 | ],
47 | "extends": [
48 | "plugin:@angular-eslint/template/recommended"
49 | ],
50 | "rules": {}
51 | }
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | strategy:
11 | matrix:
12 | node-version: [22.x]
13 |
14 | steps:
15 | - uses: actions/checkout@v1
16 | - name: Use Node.js ${{ matrix.node-version }}
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: ${{ matrix.node-version }}
20 | - name: npm install, build, and deploy
21 | run: |
22 | npm ci --legacy-peer-deps
23 | npm run deploy
24 | env:
25 | CI: true
26 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
2 |
3 | # Compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | /bazel-out
8 |
9 | # Node
10 | /node_modules
11 | npm-debug.log
12 | yarn-error.log
13 |
14 | # IDEs and editors
15 | .idea/
16 | .project
17 | .classpath
18 | .c9/
19 | *.launch
20 | .settings/
21 | *.sublime-workspace
22 |
23 | # Visual Studio Code
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 | .history/*
30 |
31 | # Miscellaneous
32 | /.angular/cache
33 | .sass-cache/
34 | /connect.lock
35 | /coverage
36 | /libpeerconnection.log
37 | testem.log
38 | /typings
39 |
40 | # System files
41 | .DS_Store
42 | Thumbs.db
43 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at tiberiuzuld@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Tiberiu Zuld
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-busy2 [Live Demo](https://tiberiuzuld.github.io/angular-busy)
2 |
3 | [](https://badge.fury.io/js/angular-busy2)
4 | 
5 | [](https://www.npmjs.com/package/angular-busy2)
6 | [](https://www.paypal.me/tiberiuzuld)
7 |
8 | > Show busy/loading indicators on Observable, Subscription, Promise, Boolean, Number
9 |
10 | ### For [AngularJS 1 branch 1.x](https://github.com/tiberiuzuld/angular-busy/tree/1.x)
11 |
12 | ## Getting Started
13 |
14 | Install with npm.
15 |
16 | ```bash
17 | npm install angular-busy2 --save
18 | ```
19 |
20 | Add `CgBusyModule` as a module dependency for your module.
21 |
22 | You have to import it with `forRoot` in any module where you want to provide `CgBusyDefaults`.
23 |
24 | Usually you do that in your root module (`app.module`).
25 |
26 | If you never import it with `forRoot` `CgBusyDefaults` will always be `undefined`.
27 |
28 | `forRoot` takes optional `CgBusyOptions` as parameter.
29 |
30 | For every omitted option in the supplied `CgBusyOptions` the libraries default value will be used.
31 |
32 | ```typescript
33 | import { CgBusyModule } from 'angular-busy2';
34 |
35 | @NgModule({
36 | imports: [
37 | CgBusyModule.forRoot({
38 | backdrop: true
39 | }) //import it with .forRoot in your root module. provide some optional Options.
40 | ]
41 | })
42 | ```
43 |
44 | In every shared module/sub module you should import `CgBusyModule` without `forRoot` unless you want to provide a
45 | different instance of `CgBusyDefaults`
46 |
47 | ### Standalone import directive
48 |
49 | ```typescript
50 | import { CgBusyDirective } from 'angular-busy2';
51 |
52 | @Component({
53 | standalone: true,
54 | imports: [CgBusyDirective],
55 | // ...
56 | })
57 |
58 | // main.ts if you bootstrap application
59 | bootstrapApplication(AppComponent, {
60 | providers: [
61 | importProvidersFrom(CgBusyModule.forRoot())
62 | // ...
63 | ]
64 | }).catch(err => console.log(err));
65 | ```
66 |
67 | ## Options
68 |
69 | The `[cgBusy]` directive expects any Observable, Subscription, Promise, Boolean, Number and optional `[cgBusyConfig]`
70 | configuration object.
71 |
72 | In other words. You may do this:
73 |
74 | ```html
75 |
76 |
77 | ```
78 |
79 | or this:
80 |
81 | ```html
82 |
83 |
85 | ```
86 |
87 | * `promise` - Required. The promise/Observables (or array of promises/Observables) that will cause the busy indicator to
88 | show. Also supports boolean and numbers (truthy values will show loading...)
89 | * `message` - Optional. Defaults to 'Please Wait...'. The message to show in the indicator. This value may be updated
90 | while the promise is active. The indicator will reflect the updated values as they're changed.
91 | * `backdrop` - Optional. Boolean, default is true. If true a faded backdrop will be shown behind the progress indicator.
92 | * `templateRef` - Optional. If provided, the given template will be shown in place of the default progress indicator
93 | template.
94 | * `delay` - Optional. The amount of time to wait until showing the indicator. Defaults to 0. Specified in milliseconds.
95 | * `minDuration` - Optional. The amount of time to keep the indicator showing even if the promise was resolved quicker.
96 | Defaults to 0. Specified in milliseconds.
97 | * `wrapperClass` - Optional. The name(s) of the CSS classes to be applied to the wrapper element of the busy
98 | sign/animation. Defaults to `undefined`. Typically only useful if you wish to apply different positioning to the
99 | animation.
100 |
101 | ## Overriding Defaults
102 |
103 | The default values for `message`, `backdrop`, `templateRef`, `delay`, and `minDuration` may all be overridden by
104 | overriding the `CgBusyDefaults`, like so:
105 |
106 | ```typescript
107 | import { CgBusyDefaults } from 'angular-busy2';
108 |
109 | class AppComponent {
110 | @ViewChild('customTemplate')
111 | private customTemplateTpl: TemplateRef;
112 |
113 | constructor(private busyDefaults: CgBusyDefaults) {
114 | this.busyDefaults.delay = 5000;
115 | }
116 |
117 | ngOnInit() {
118 | this.busyDefaults.templateRef = this.customTemplateTpl;
119 | }
120 | }
121 | ```
122 |
123 | ```html
124 |
125 |
126 |
129 |
130 | ```
131 |
132 | Only the values you'd like overridden need to be specified.
133 |
134 | > Fork from original angular-busy (cgBusy) https://github.com/cgross/angular-busy
135 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "angular-busy2-app": {
7 | "projectType": "application",
8 | "schematics": {
9 | "@schematics/angular:application": {
10 | "strict": true
11 | }
12 | },
13 | "root": "",
14 | "sourceRoot": "src",
15 | "prefix": "cg",
16 | "architect": {
17 | "build": {
18 | "builder": "@angular-devkit/build-angular:application",
19 | "options": {
20 | "outputPath": "dist/demo",
21 | "index": "src/index.html",
22 | "polyfills": [
23 | "zone.js"
24 | ],
25 | "tsConfig": "tsconfig.app.json",
26 | "assets": [
27 | "src/assets"
28 | ],
29 | "styles": [
30 | "src/styles.css",
31 | "src/theme.scss"
32 | ],
33 | "scripts": [],
34 | "browser": "src/main.ts"
35 | },
36 | "configurations": {
37 | "production": {
38 | "baseHref": "/angular-busy/",
39 | "budgets": [
40 | {
41 | "type": "anyComponentStyle",
42 | "maximumWarning": "4kb",
43 | "maximumError": "8kb"
44 | }
45 | ],
46 | "outputHashing": "all"
47 | },
48 | "development": {
49 | "optimization": false,
50 | "extractLicenses": false,
51 | "sourceMap": true
52 | }
53 | },
54 | "defaultConfiguration": "production"
55 | },
56 | "serve": {
57 | "builder": "@angular-devkit/build-angular:dev-server",
58 | "configurations": {
59 | "production": {
60 | "buildTarget": "angular-busy2-app:build:production"
61 | },
62 | "development": {
63 | "buildTarget": "angular-busy2-app:build:development"
64 | }
65 | },
66 | "defaultConfiguration": "development"
67 | },
68 | "extract-i18n": {
69 | "builder": "@angular-devkit/build-angular:extract-i18n"
70 | },
71 | "test": {
72 | "builder": "@angular-devkit/build-angular:karma",
73 | "options": {
74 | "polyfills": [
75 | "zone.js",
76 | "zone.js/testing"
77 | ],
78 | "tsConfig": "tsconfig.spec.json",
79 | "assets": [
80 | "src/assets"
81 | ],
82 | "styles": [
83 | "src/styles.css"
84 | ],
85 | "scripts": []
86 | }
87 | },
88 | "lint": {
89 | "builder": "@angular-eslint/builder:lint",
90 | "options": {
91 | "lintFilePatterns": [
92 | "src/**/*.ts",
93 | "src/**/*.html"
94 | ]
95 | }
96 | },
97 | "deploy": {
98 | "builder": "angular-cli-ghpages:deploy",
99 | "options": {
100 | "buildTarget": "angular-busy2-app:build:production",
101 | "repo": "https://GH_TOKEN@github.com/tiberiuzuld/angular-busy.git",
102 | "name": "Tiberiu Zuld",
103 | "email": "tiberiuzuld@gmail.com"
104 | }
105 | }
106 | }
107 | },
108 | "angular-busy2": {
109 | "projectType": "library",
110 | "root": "projects/angular-busy2",
111 | "sourceRoot": "projects/angular-busy2/src",
112 | "prefix": "lib",
113 | "architect": {
114 | "build": {
115 | "builder": "@angular-devkit/build-angular:ng-packagr",
116 | "options": {
117 | "project": "projects/angular-busy2/ng-package.json"
118 | },
119 | "configurations": {
120 | "production": {
121 | "tsConfig": "projects/angular-busy2/tsconfig.lib.prod.json"
122 | },
123 | "development": {
124 | "tsConfig": "projects/angular-busy2/tsconfig.lib.json"
125 | }
126 | },
127 | "defaultConfiguration": "production"
128 | },
129 | "test": {
130 | "builder": "@angular-devkit/build-angular:karma",
131 | "options": {
132 | "tsConfig": "projects/angular-busy2/tsconfig.spec.json",
133 | "polyfills": [
134 | "zone.js",
135 | "zone.js/testing"
136 | ]
137 | }
138 | },
139 | "lint": {
140 | "builder": "@angular-eslint/builder:lint",
141 | "options": {
142 | "lintFilePatterns": [
143 | "projects/angular-busy2/**/*.ts",
144 | "projects/angular-busy2/**/*.html"
145 | ]
146 | }
147 | }
148 | }
149 | }
150 | },
151 | "cli": {
152 | "analytics": "1f4c9dbf-755c-4ca9-a896-da7d97faf505",
153 | "schematicCollections": [
154 | "@angular-eslint/schematics"
155 | ]
156 | },
157 | "schematics": {
158 | "@angular-eslint/schematics:application": {
159 | "setParserOptionsProject": true
160 | },
161 | "@angular-eslint/schematics:library": {
162 | "setParserOptionsProject": true
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-busy2",
3 | "version": "21.0.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "ng": "ng",
7 | "start": "ng serve",
8 | "build": "ng build",
9 | "test": "ng test",
10 | "lint": "ng lint",
11 | "build-demo": "ng build",
12 | "build-npm": "ng build angular-busy2",
13 | "watch": "ng build --watch --configuration development",
14 | "deploy": "npm run build-npm && ng deploy"
15 | },
16 | "sideEffects": false,
17 | "homepage": "https://tiberiuzuld.github.io/angular-busy/",
18 | "bugs": {
19 | "url": "https://github.com/tiberiuzuld/angular-busy/issues"
20 | },
21 | "repository": {
22 | "type": "git",
23 | "url": "git+https://github.com/tiberiuzuld/angular-busy.git"
24 | },
25 | "description": "Angular Busy 2",
26 | "keywords": [
27 | "angular",
28 | "angularjs",
29 | "typescript",
30 | "busy",
31 | "loading",
32 | "angular-busy2",
33 | "angular-busy"
34 | ],
35 | "authors": [
36 | "Tiberiu Zuld"
37 | ],
38 | "dependencies": {
39 | "@angular/animations": "19.0.3",
40 | "@angular/cdk": "19.0.2",
41 | "@angular/common": "19.0.3",
42 | "@angular/compiler": "19.0.3",
43 | "@angular/core": "19.0.3",
44 | "@angular/forms": "19.0.3",
45 | "@angular/material": "19.0.2",
46 | "@angular/platform-browser": "19.0.3",
47 | "@angular/platform-browser-dynamic": "19.0.3",
48 | "@angular/router": "19.0.3",
49 | "rxjs": "7.8.1",
50 | "tslib": "2.8.1",
51 | "zone.js": "0.15.0"
52 | },
53 | "devDependencies": {
54 | "@angular-devkit/build-angular": "19.0.3",
55 | "@angular-eslint/builder": "19.0.0",
56 | "@angular-eslint/eslint-plugin": "19.0.0",
57 | "@angular-eslint/eslint-plugin-template": "19.0.0",
58 | "@angular-eslint/schematics": "19.0.0",
59 | "@angular-eslint/template-parser": "19.0.0",
60 | "@angular/cli": "19.0.3",
61 | "@angular/compiler-cli": "19.0.3",
62 | "@types/jasmine": "5.1.5",
63 | "@types/node": "22.10.1",
64 | "angular-cli-ghpages": "2.0.3",
65 | "eslint": "9.16.0",
66 | "jasmine-core": "5.5.0",
67 | "karma": "6.4.4",
68 | "karma-chrome-launcher": "3.2.0",
69 | "karma-coverage": "2.2.1",
70 | "karma-jasmine": "5.1.0",
71 | "karma-jasmine-html-reporter": "2.1.0",
72 | "ng-packagr": "19.0.1",
73 | "typescript": "5.6.3",
74 | "typescript-eslint": "8.17.0"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/projects/angular-busy2/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../.eslintrc.json",
3 | "ignorePatterns": [
4 | "!**/*"
5 | ],
6 | "overrides": [
7 | {
8 | "files": [
9 | "*.ts"
10 | ],
11 | "parserOptions": {
12 | "project": [
13 | "projects/angular-busy2/tsconfig.lib.lint.json",
14 | "projects/angular-busy2/tsconfig.spec.json"
15 | ]
16 | },
17 | "rules": {
18 | "@angular-eslint/directive-selector": [
19 | "error",
20 | {
21 | "type": "attribute",
22 | "prefix": "cg",
23 | "style": "camelCase"
24 | }
25 | ],
26 | "@angular-eslint/component-selector": [
27 | "error",
28 | {
29 | "type": "element",
30 | "prefix": "cg",
31 | "style": "kebab-case"
32 | }
33 | ]
34 | }
35 | },
36 | {
37 | "files": [
38 | "*.html"
39 | ],
40 | "rules": {}
41 | }
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/projects/angular-busy2/LICENSE:
--------------------------------------------------------------------------------
1 | ../../LICENSE
--------------------------------------------------------------------------------
/projects/angular-busy2/README.md:
--------------------------------------------------------------------------------
1 | ../../README.md
--------------------------------------------------------------------------------
/projects/angular-busy2/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/angular-busy2",
4 | "lib": {
5 | "entryFile": "src/public_api.ts"
6 | }
7 | }
--------------------------------------------------------------------------------
/projects/angular-busy2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-busy2",
3 | "version": "21.0.0",
4 | "license": "MIT",
5 | "homepage": "https://tiberiuzuld.github.io/angular-busy/",
6 | "bugs": {
7 | "url": "https://github.com/tiberiuzuld/angular-busy/issues"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/tiberiuzuld/angular-busy.git"
12 | },
13 | "description": "Angular Busy 2",
14 | "keywords": [
15 | "angular",
16 | "angularjs",
17 | "typescript",
18 | "busy",
19 | "loading",
20 | "angular-busy2",
21 | "angular-busy"
22 | ],
23 | "authors": [
24 | "Tiberiu Zuld"
25 | ],
26 | "sideEffects": false,
27 | "peerDependencies": {
28 | "@angular/common": "^19.0.0",
29 | "@angular/core": "^19.0.0"
30 | },
31 | "dependencies": {
32 | "tslib": "^2.4.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.component.css:
--------------------------------------------------------------------------------
1 | .cg-busy, .cg-busy .cg-busy-template, .cg-busy .cg-busy-backdrop {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | right: 0;
6 | bottom: 0;
7 | width: 100%;
8 | height: 100%
9 | }
10 |
11 | .cg-busy {
12 | z-index: 1001;
13 | text-align: center;
14 | }
15 |
16 | .cg-busy-animation.ng-hide-add,
17 | .cg-busy-animation.ng-hide-remove {
18 | transition: all .3s ease;
19 | display: block !important;
20 | }
21 |
22 | .cg-busy-animation.ng-hide-remove {
23 | opacity: 0;
24 | transform: translate(0px, -40px);
25 | }
26 |
27 | .cg-busy-animation.ng-hide-remove.ng-hide-remove-active {
28 | opacity: 1;
29 | transform: translate(0px, 0px);
30 | }
31 |
32 | .cg-busy-animation.ng-hide-add {
33 | opacity: 1;
34 | transform: translate(0px, 0px);
35 | }
36 |
37 | .cg-busy-animation.ng-hide-add.ng-hide-add-active {
38 | opacity: 0;
39 | transform: translate(0px, -40px);
40 | }
41 |
42 | .cg-busy-backdrop {
43 | background-color: white;
44 | opacity: .7;
45 | }
46 |
47 | .cg-busy-backdrop-animation.ng-hide-add,
48 | .cg-busy-backdrop-animation.ng-hide-remove {
49 | transition: opacity .3s ease;
50 | display: block !important;
51 | }
52 |
53 | .cg-busy-backdrop-animation.ng-hide {
54 | opacity: 0;
55 | }
56 |
57 | /* All styles below are for the default template. */
58 |
59 | .cg-busy-default-sign {
60 | display: inline-block;
61 | position: relative;
62 | z-index: 1002;
63 | padding-bottom: 6px;
64 | color: #333333;
65 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
66 | background-color: #e9eeee;
67 | border: 1px solid #dddddd;
68 | border-top-width: 0;
69 | border-radius: 7px;
70 | border-top-left-radius: 0;
71 | border-top-right-radius: 0;
72 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05);
73 | }
74 |
75 | .cg-busy-default-text {
76 | margin: 13px 12px 6px 49px;
77 | font-size: 16px;
78 | color: #555;
79 | text-align: left;
80 | max-width: 400px;
81 | }
82 |
83 | .cg-busy-default-spinner {
84 | position: absolute;
85 | width: 25px;
86 | height: 25px;
87 | display: inline-block;
88 | top: 12px;
89 | left: 14px;
90 | }
91 |
92 | .cg-busy-default-spinner div {
93 | width: 12%;
94 | height: 26%;
95 | background: #000;
96 | position: absolute;
97 | left: 44.5%;
98 | top: 37%;
99 | opacity: 0;
100 | animation: cg-busy-spinner-anim 1s linear infinite;
101 | border-radius: 50px;
102 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
103 | }
104 |
105 | .cg-busy-default-spinner div.bar1 {
106 | transform: rotate(0deg) translate(0, -142%);
107 | animation-delay: 0s;
108 | }
109 |
110 | .cg-busy-default-spinner div.bar2 {
111 | transform: rotate(30deg) translate(0, -142%);
112 | animation-delay: -0.9167s;
113 | }
114 |
115 | .cg-busy-default-spinner div.bar3 {
116 | transform: rotate(60deg) translate(0, -142%);
117 | animation-delay: -0.833s;
118 | }
119 |
120 | .cg-busy-default-spinner div.bar4 {
121 | transform: rotate(90deg) translate(0, -142%);
122 | animation-delay: -0.75s;
123 | }
124 |
125 | .cg-busy-default-spinner div.bar5 {
126 | transform: rotate(120deg) translate(0, -142%);
127 | animation-delay: -0.667s;
128 | }
129 |
130 | .cg-busy-default-spinner div.bar6 {
131 | transform: rotate(150deg) translate(0, -142%);
132 | animation-delay: -0.5833s;
133 | }
134 |
135 | .cg-busy-default-spinner div.bar7 {
136 | transform: rotate(180deg) translate(0, -142%);
137 | animation-delay: -0.5s;
138 | }
139 |
140 | .cg-busy-default-spinner div.bar8 {
141 | transform: rotate(210deg) translate(0, -142%);
142 | animation-delay: -0.41667s;
143 | }
144 |
145 | .cg-busy-default-spinner div.bar9 {
146 | transform: rotate(240deg) translate(0, -142%);
147 | animation-delay: -0.333s;
148 | }
149 |
150 | .cg-busy-default-spinner div.bar10 {
151 | transform: rotate(270deg) translate(0, -142%);
152 | animation-delay: -0.25s;
153 | }
154 |
155 | .cg-busy-default-spinner div.bar11 {
156 | transform: rotate(300deg) translate(0, -142%);
157 | animation-delay: -0.1667s;
158 | }
159 |
160 | .cg-busy-default-spinner div.bar12 {
161 | transform: rotate(330deg) translate(0, -142%);
162 | animation-delay: -0.0833s;
163 | }
164 |
165 | @keyframes cg-busy-spinner-anim {
166 | from {
167 | opacity: 1;
168 | }
169 | to {
170 | opacity: 0.25;
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.component.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.component.ts:
--------------------------------------------------------------------------------
1 | import {NgTemplateOutlet} from '@angular/common';
2 | import {Component, Input, ViewEncapsulation} from '@angular/core';
3 | import type {CgBusyOptions} from './cgBusy.interface';
4 | import {CgBusyService} from './cgBusy.service';
5 |
6 | @Component({
7 | templateUrl: './cgBusy.component.html',
8 | styleUrls: ['./cgBusy.component.css'],
9 | selector: 'cg-busy',
10 | encapsulation: ViewEncapsulation.None,
11 | imports: [NgTemplateOutlet]
12 | })
13 | export class CgBusyComponent {
14 | @Input() options: CgBusyOptions;
15 | @Input() tracker: CgBusyService;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.directive.ts:
--------------------------------------------------------------------------------
1 | import {ComponentRef, Directive, ElementRef, Input, OnChanges, OnDestroy, Renderer2, SimpleChanges, ViewContainerRef} from '@angular/core';
2 | import {Observable, Subscription} from 'rxjs';
3 | import {CgBusyComponent} from './cgBusy.component';
4 | import type {CgBusyOptions} from './cgBusy.interface';
5 | import {CgBusyService} from './cgBusy.service';
6 | import {CgBusyDefaults} from './cgBusyDefaults.service';
7 |
8 | @Directive({selector: '[cgBusy]', standalone: true, exportAs: 'cgBusy'})
9 | export class CgBusyDirective implements OnChanges, OnDestroy {
10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
11 | @Input() cgBusy: boolean | number | Promise | Subscription | Observable | (Promise | Subscription | Observable)[];
12 | @Input() cgBusyConfig: CgBusyOptions;
13 | tracker: CgBusyService;
14 | fakePromise: Promise;
15 | fakePromiseResolve: () => void;
16 | $options: CgBusyOptions;
17 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
18 | $promise: (Promise | Subscription | Observable)[];
19 | componentRef: ComponentRef;
20 |
21 | constructor(private viewContainer: ViewContainerRef, private defaultOptions: CgBusyDefaults,
22 | private renderer: Renderer2, private el: ElementRef) {
23 | this.$options = {...this.defaultOptions};
24 | this.$promise = [];
25 | this.renderer.setStyle(this.el.nativeElement.parentNode, 'position', 'relative');
26 | this.componentRef = this.viewContainer.createComponent(CgBusyComponent);
27 | this.tracker = new CgBusyService();
28 | this.tracker.detectChanges = () => this.componentRef.changeDetectorRef.detectChanges();
29 | this.componentRef.instance.tracker = this.tracker;
30 | this.componentRef.instance.options = this.$options;
31 | }
32 |
33 | ngOnChanges(changes: SimpleChanges): void {
34 | if (changes.cgBusyConfig) {
35 | this.$options = {
36 | ...this.defaultOptions,
37 | ...this.$options,
38 | ...this.cgBusyConfig
39 | };
40 | this.componentRef.instance.options = this.$options;
41 | }
42 | if (changes.cgBusy) {
43 | if (this.fakePromise) {
44 | this.fakePromiseResolve();
45 | this.fakePromise = undefined;
46 | this.fakePromiseResolve = undefined;
47 | }
48 |
49 | if (Number.isFinite(this.cgBusy) || this.cgBusy === true || this.cgBusy === false) {
50 | this.fakePromise = new Promise((resolve) => {
51 | this.fakePromiseResolve = resolve;
52 | if (!this.cgBusy) {
53 | resolve();
54 | }
55 | });
56 | this.$promise = [this.fakePromise];
57 | } else if (Array.isArray(this.cgBusy)) {
58 | this.$promise = this.cgBusy;
59 | } else {
60 | // @ts-ignore
61 | this.$promise = [this.cgBusy];
62 | }
63 | }
64 | this.tracker.reset({
65 | promises: this.$promise,
66 | delay: this.$options.delay || 0,
67 | minDuration: this.$options.minDuration || 0
68 | });
69 | }
70 |
71 | ngOnDestroy(): void {
72 | this.tracker.destroy();
73 | delete this.tracker;
74 | this.componentRef.destroy();
75 | delete this.componentRef;
76 | this.$promise = [];
77 | this.fakePromise = undefined;
78 | this.fakePromiseResolve = undefined;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.interface.ts:
--------------------------------------------------------------------------------
1 | import {TemplateRef} from '@angular/core';
2 |
3 | export interface CgBusyOptions {
4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
5 | templateRef?: TemplateRef;
6 | message?: string;
7 | wrapperClass?: string;
8 | backdrop?: boolean;
9 | delay?: number;
10 | minDuration?: number;
11 | }
12 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.module.ts:
--------------------------------------------------------------------------------
1 | import { ModuleWithProviders, NgModule } from '@angular/core';
2 | import { CgBusyDirective } from './cgBusy.directive';
3 | import { CgBusyOptions } from './cgBusy.interface';
4 | import { BUSY_OPTIONS, CgBusyDefaults } from './cgBusyDefaults.service';
5 |
6 | export function cgBusyDefaultsFactory(busyOptions?: CgBusyOptions): CgBusyDefaults {
7 | return new CgBusyDefaults(busyOptions);
8 | }
9 |
10 | @NgModule({
11 | imports: [CgBusyDirective],
12 | exports: [CgBusyDirective]
13 | })
14 | export class CgBusyModule {
15 | static forRoot(busyOptions?: CgBusyOptions): ModuleWithProviders {
16 | return {
17 | ngModule: CgBusyModule,
18 | providers: [
19 | {
20 | provide: CgBusyDefaults,
21 | useFactory: cgBusyDefaultsFactory,
22 | deps: [BUSY_OPTIONS]
23 | },
24 | {
25 | provide: BUSY_OPTIONS,
26 | useValue: busyOptions
27 | }
28 | ]
29 | };
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusy.service.ts:
--------------------------------------------------------------------------------
1 | import {finalize, Observable, Subscription} from 'rxjs';
2 |
3 | export interface TrackerOptions {
4 | minDuration: number;
5 | delay: number;
6 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
7 | promises: any[];
8 | }
9 |
10 | export class CgBusyService {
11 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
12 | promises: any[];
13 | subscriptions: Subscription[];
14 | delayPromise: number;
15 | durationPromise: number;
16 | minDuration: number;
17 | detectChanges: () => void | null;
18 |
19 | constructor() {
20 | this.promises = [];
21 | this.subscriptions = [];
22 | }
23 |
24 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
25 | static isPromise(promiseThing: PromiseLike): boolean {
26 | return promiseThing && (promiseThing instanceof Promise || promiseThing instanceof Observable || promiseThing instanceof Subscription);
27 | }
28 |
29 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
30 | callThen(promiseThing: any, callback: () => void): void {
31 | if (promiseThing.finally) {
32 | promiseThing.finally(callback);
33 | } else if (promiseThing.then) {
34 | promiseThing.then(callback, callback);
35 | } else if (promiseThing instanceof Observable) {
36 | promiseThing.pipe(finalize(callback));
37 | } else if (promiseThing instanceof Subscription) {
38 | promiseThing.add(callback);
39 | } else {
40 | throw new Error('cgBusy expects a Promise ,an Observable, a Subscription, a number or a boolean');
41 | }
42 | }
43 |
44 | reset(options: TrackerOptions): void {
45 | this.minDuration = options.minDuration;
46 |
47 | this.promises = [];
48 | options.promises.forEach((p) => {
49 | if (!p || p.$cgBusyFulfilled) {
50 | return;
51 | }
52 | this.addPromiseLikeThing(p);
53 | });
54 |
55 | if (this.promises.length === 0) {
56 | // if we have no promises then don't do the delay or duration stuff
57 | return;
58 | }
59 |
60 | if (options.delay) {
61 | this.delayPromise = window.setTimeout(() => {
62 | this.delayPromise = null;
63 | if (this.detectChanges) {
64 | this.detectChanges();
65 | }
66 | this.createMinDuration(options);
67 | }, options.delay);
68 | } else {
69 | this.createMinDuration(options);
70 | }
71 | }
72 |
73 | createMinDuration(options: TrackerOptions): void {
74 | if (options.minDuration) {
75 | this.durationPromise = window.setTimeout(() => {
76 | this.durationPromise = null;
77 | if (this.detectChanges) {
78 | this.detectChanges();
79 | }
80 | }, options.minDuration);
81 | }
82 | }
83 |
84 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
85 | addPromiseLikeThing(promise: any): void {
86 |
87 | if (!CgBusyService.isPromise(promise)) {
88 | throw new Error('cgBusy expects a Promise ,an Observable, a Subscription, a number or a boolean');
89 | }
90 |
91 | if (this.promises.indexOf(promise) !== -1) {
92 | return;
93 | }
94 | this.promises.push(promise);
95 |
96 | this.callThen(promise, () => {
97 | promise.$cgBusyFulfilled = true;
98 | if (this.promises.indexOf(promise) === -1) {
99 | return;
100 | }
101 | this.promises.splice(this.promises.indexOf(promise), 1);
102 | if (this.delayPromise && this.promises.length === 0) {
103 | clearTimeout(this.delayPromise);
104 | this.delayPromise = null;
105 | }
106 | if (this.detectChanges) {
107 | this.detectChanges();
108 | }
109 | });
110 | }
111 |
112 | active(): boolean {
113 | return !this.delayPromise && (!!this.durationPromise || this.promises.length > 0);
114 | }
115 |
116 | destroy(): void {
117 | if (this.delayPromise) {
118 | clearTimeout(this.delayPromise);
119 | this.delayPromise = null;
120 | }
121 | if (this.durationPromise) {
122 | clearTimeout(this.durationPromise);
123 | this.durationPromise = null;
124 | }
125 | this.promises = [];
126 | this.detectChanges = null;
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/lib/cgBusyDefaults.service.ts:
--------------------------------------------------------------------------------
1 | import {Inject, Injectable, InjectionToken, TemplateRef} from '@angular/core';
2 | import type {CgBusyOptions} from './cgBusy.interface';
3 |
4 | export const BUSY_OPTIONS = new InjectionToken('BUSY_OPTIONS');
5 |
6 | @Injectable()
7 | export class CgBusyDefaults implements CgBusyOptions {
8 | delay: number;
9 | minDuration: number;
10 | backdrop: boolean;
11 | message: string;
12 | wrapperClass: string;
13 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
14 | templateRef: TemplateRef;
15 |
16 | constructor(@Inject(BUSY_OPTIONS) busyOptions?: CgBusyOptions) {
17 |
18 | if (!busyOptions) {
19 | busyOptions = {};
20 | }
21 |
22 | this.delay = busyOptions.delay || 0;
23 | this.minDuration = busyOptions.minDuration || 0;
24 | this.backdrop = busyOptions.backdrop !== undefined ? busyOptions.backdrop : true;
25 | this.message = busyOptions.message || 'Please Wait...';
26 | this.wrapperClass = busyOptions.wrapperClass || '';
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/projects/angular-busy2/src/public_api.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Public API Surface of angular-busy2
3 | */
4 |
5 | export type {CgBusyOptions} from './lib/cgBusy.interface';
6 | export {CgBusyModule} from './lib/cgBusy.module';
7 | export {CgBusyDefaults} from './lib/cgBusyDefaults.service';
8 | export {CgBusyDirective} from './lib/cgBusy.directive';
9 |
--------------------------------------------------------------------------------
/projects/angular-busy2/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "../../tsconfig.json",
5 | "compilerOptions": {
6 | "outDir": "../../out-tsc/lib",
7 | "declarationMap": true,
8 | "module": "ES2022",
9 | "moduleResolution": "bundler",
10 | "declaration": true,
11 | "sourceMap": true,
12 | "inlineSources": true,
13 | "emitDecoratorMetadata": true,
14 | "experimentalDecorators": true,
15 | "importHelpers": true,
16 | "types": []
17 | },
18 | "exclude": [
19 | "**/*.spec.ts"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/projects/angular-busy2/tsconfig.lib.lint.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "./tsconfig.lib.json",
5 | "include": [
6 | // adjust "includes" to what makes sense for you and your project
7 | "src/**/*.ts"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/projects/angular-busy2/tsconfig.lib.prod.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "./tsconfig.lib.json",
5 | "compilerOptions": {
6 | "declarationMap": false
7 | },
8 | "angularCompilerOptions": {
9 | "compilationMode": "partial"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/projects/angular-busy2/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "../../tsconfig.json",
5 | "compilerOptions": {
6 | "outDir": "../../out-tsc/spec",
7 | "types": [
8 | "jasmine"
9 | ]
10 | },
11 | "include": [
12 | "**/*.spec.ts",
13 | "**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | mat-grid-list {
2 | min-width: 400px;
3 | }
4 |
5 | .custom-template {
6 | background: url('../assets/finalfantasy.gif') no-repeat 50% 20px;
7 | width: 100%;
8 | height: 100%;
9 | position: absolute;
10 | }
11 |
12 | .custom-message {
13 | text-align: center;
14 | font-size: 26px;
15 | position: absolute;
16 | top: 100px;
17 | width: 100%;
18 | text-shadow: 1px 1px 2px white, -1px -1px 2px white, -4px 4px 4px white, -4px 4px 4px white;
19 | }
20 |
21 | .mat-select {
22 | margin-top: 25px;
23 | }
24 |
25 | .flex {
26 | flex: 1 auto;
27 | }
28 |
29 | .layout-column {
30 | display: flex;
31 | flex-direction: column;
32 | }
33 |
34 | .layout-row {
35 | display: flex;
36 | flex-direction: row;
37 | }
38 |
39 | @media (min-width: 1280px) {
40 | .layout-gt-md-row {
41 | display: flex;
42 | flex-direction: row;
43 | }
44 | }
45 |
46 | .layout-align-space-between {
47 | justify-content: space-between;
48 | }
49 |
50 | .layout-align-end-center {
51 | align-items: center;
52 | justify-content: flex-end;
53 | }
54 |
55 | :host {
56 | padding: 8px;
57 | width: 100%;
58 | height: 100%;
59 | display: flex;
60 | flex-direction: column;
61 | box-sizing: border-box;
62 | }
63 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
angular-busy2
4 |
Show busy/loading indicators on any Observable, Subscription, Promise, Boolean, Number
5 |
6 |
7 |
37 |
38 |
39 |
41 |
42 | #
43 |
44 |
45 | First Name
46 |
47 |
48 | Last Name
49 |
50 |
51 | Username
52 |
53 |
54 | 1
55 |
56 |
57 | Mark
58 |
59 |
60 | Otto
61 |
62 |
63 | @mdo
64 |
65 |
66 | 2
67 |
68 |
69 | Mark
70 |
71 |
72 | Otto
73 |
74 |
75 | @TwBootstrap
76 |
77 |
78 | 3
79 |
80 |
81 | Jacob
82 |
83 |
84 | Thornton
85 |
86 |
87 | @fat
88 |
89 |
90 | 4
91 |
92 |
93 | Larry
94 |
95 |
96 | the Bird
97 |
98 |
99 | @twitter
100 |
101 |
102 |
103 |
104 |
105 |
106 |
109 |
110 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {HttpClient} from '@angular/common/http';
2 | import {ChangeDetectionStrategy, Component, OnInit} from '@angular/core';
3 | import {FormsModule} from '@angular/forms';
4 | import {MatButtonModule} from '@angular/material/button';
5 | import {MatCheckboxModule} from '@angular/material/checkbox';
6 | import {MatGridListModule} from '@angular/material/grid-list';
7 | import {MatInputModule} from '@angular/material/input';
8 | import {MatSelectModule} from '@angular/material/select';
9 | import {CgBusyDirective} from 'angular-busy2';
10 | import {Observable, Subscription} from 'rxjs';
11 |
12 | @Component({
13 | selector: 'app-cg-busy',
14 | templateUrl: './app.component.html',
15 | styleUrl: './app.component.css',
16 | changeDetection: ChangeDetectionStrategy.OnPush,
17 | imports: [
18 | FormsModule,
19 | MatButtonModule,
20 | MatCheckboxModule,
21 | MatGridListModule,
22 | MatInputModule,
23 | MatSelectModule,
24 | CgBusyDirective
25 | ]
26 | })
27 | export class AppComponent implements OnInit {
28 | delay: number;
29 | minDuration: number;
30 | message: string;
31 | backdrop: boolean;
32 | showCustomTemplate: boolean;
33 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
34 | promise: any;
35 | templateUrl: string;
36 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
37 | promiseTypes: {id: number, label: string, value: any}[];
38 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
39 | promiseType: {id: number, label: string, value: any};
40 |
41 | constructor(private http: HttpClient) {
42 | this.showCustomTemplate = false;
43 | }
44 |
45 | ngOnInit(): void {
46 | this.delay = 0;
47 | this.minDuration = 0;
48 | this.message = 'Please Wait...';
49 | this.backdrop = true;
50 | this.promise = null;
51 | this.templateUrl = '';
52 |
53 | this.promiseTypes = [
54 | {id: 0, label: 'Promise', value: this.getHttp.bind(this)},
55 | {id: 1, label: 'Observable', value: this.getHttpObserver.bind(this)},
56 | {id: 1, label: 'Subscription', value: this.getHttpSubscription.bind(this)},
57 | {id: 2, label: 'Number', value: 1},
58 | {id: 3, label: 'Number `falsy`', value: 0},
59 | {id: 4, label: 'Boolean', value: true},
60 | {id: 5, label: 'Boolean false', value: false}
61 | ];
62 |
63 | this.promiseType = this.promiseTypes[0];
64 | }
65 |
66 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
67 | getHttp(): Promise {
68 | return this.http.get('https://httpbin.org/delay/3').toPromise();
69 | }
70 |
71 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
72 | getHttpObserver(): Observable {
73 | return this.http.get('https://httpbin.org/delay/3');
74 | }
75 |
76 | getHttpSubscription(): Subscription {
77 | return this.http.get('https://httpbin.org/delay/3').subscribe(() => {
78 | });
79 | }
80 |
81 | demo(): void {
82 | if (typeof this.promiseType.value === 'function') {
83 | this.promise = this.promiseType.value();
84 | } else {
85 | this.promise = this.promiseType.value;
86 | }
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/app/app.config.ts:
--------------------------------------------------------------------------------
1 | import {provideHttpClient} from '@angular/common/http';
2 | import {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core';
3 | import {provideAnimationsAsync} from '@angular/platform-browser/animations/async';
4 | import {CgBusyModule} from 'angular-busy2';
5 |
6 | export const appConfig: ApplicationConfig = {
7 | providers: [
8 | provideZoneChangeDetection({ eventCoalescing: true }),
9 | provideAnimationsAsync(),
10 | provideHttpClient(),
11 | importProvidersFrom(CgBusyModule.forRoot())
12 | ]
13 | };
14 |
--------------------------------------------------------------------------------
/src/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiberiuzuld/angular-busy/728a33a4885b3b501d43ca99c2549c18b185abd3/src/assets/favicon.ico
--------------------------------------------------------------------------------
/src/assets/finalfantasy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tiberiuzuld/angular-busy/728a33a4885b3b501d43ca99c2549c18b185abd3/src/assets/finalfantasy.gif
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular Busy 2
6 |
7 |
8 |
9 |
13 |
14 |
15 |
20 | Loading...
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import {bootstrapApplication} from '@angular/platform-browser';
2 | import {AppComponent} from './app/app.component';
3 | import {appConfig} from './app/app.config';
4 |
5 | bootstrapApplication(AppComponent, appConfig).catch(err => console.log(err));
6 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | html, body {
4 | height: 100vh;
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | body {
10 | display: flex;
11 | flex-direction: column;
12 | margin: 0;
13 | font-family: Roboto, 'Helvetica Neue', sans-serif;
14 | }
15 |
16 | /* Left will inherit from right (so we don't need to duplicate code) */
17 | .github-fork-ribbon {
18 | /* The right and left classes determine the side we attach our banner to */
19 | position: absolute;
20 |
21 | /* Add a bit of padding to give some substance outside the "stitching" */
22 | padding: 2px 0;
23 |
24 | /* Set the base colour */
25 | background-color: #a00;
26 |
27 | /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */
28 | background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.15)));
29 | background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
30 | background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
31 | background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
32 | background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
33 | background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
34 |
35 | /* Add a drop shadow */
36 | -webkit-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
37 | -moz-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
38 | box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
39 |
40 | z-index: 9999;
41 | pointer-events: auto;
42 | }
43 |
44 | .github-fork-ribbon a,
45 | .github-fork-ribbon a:hover {
46 | /* Set the font */
47 | font: 700 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
48 | color: #fff;
49 |
50 | /* Set the text properties */
51 | text-decoration: none;
52 | text-shadow: 0 -1px rgba(0, 0, 0, 0.5);
53 | text-align: center;
54 |
55 | /* Set the geometry. If you fiddle with these you'll also need
56 | to tweak the top and right values in .github-fork-ribbon. */
57 | width: 200px;
58 | line-height: 20px;
59 |
60 | /* Set the layout properties */
61 | display: inline-block;
62 | padding: 2px 0;
63 |
64 | /* Add "stitching" effect */
65 | border-width: 1px 0;
66 | border-style: dotted;
67 | border-color: #fff;
68 | border-color: rgba(255, 255, 255, 0.7);
69 | }
70 |
71 | .github-fork-ribbon-wrapper {
72 | width: 150px;
73 | height: 150px;
74 | position: absolute;
75 | overflow: hidden;
76 | top: 0;
77 | z-index: 9999;
78 | pointer-events: none;
79 | }
80 |
81 | .github-fork-ribbon-wrapper.fixed {
82 | position: fixed;
83 | }
84 |
85 | .github-fork-ribbon-wrapper.left {
86 | left: 0;
87 | }
88 |
89 | .github-fork-ribbon-wrapper.right {
90 | right: 0;
91 | }
92 |
93 | .github-fork-ribbon-wrapper.left-bottom {
94 | position: fixed;
95 | top: inherit;
96 | bottom: 0;
97 | left: 0;
98 | }
99 |
100 | .github-fork-ribbon-wrapper.right-bottom {
101 | position: fixed;
102 | top: inherit;
103 | bottom: 0;
104 | right: 0;
105 | }
106 |
107 | .github-fork-ribbon-wrapper.right .github-fork-ribbon {
108 | top: 42px;
109 | right: -43px;
110 |
111 | -webkit-transform: rotate(45deg);
112 | -moz-transform: rotate(45deg);
113 | -ms-transform: rotate(45deg);
114 | -o-transform: rotate(45deg);
115 | transform: rotate(45deg);
116 | }
117 |
118 | .github-fork-ribbon-wrapper.left .github-fork-ribbon {
119 | top: 42px;
120 | left: -43px;
121 |
122 | -webkit-transform: rotate(-45deg);
123 | -moz-transform: rotate(-45deg);
124 | -ms-transform: rotate(-45deg);
125 | -o-transform: rotate(-45deg);
126 | transform: rotate(-45deg);
127 | }
128 |
129 | .github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon {
130 | top: 80px;
131 | left: -43px;
132 |
133 | -webkit-transform: rotate(45deg);
134 | -moz-transform: rotate(45deg);
135 | -ms-transform: rotate(45deg);
136 | -o-transform: rotate(45deg);
137 | transform: rotate(45deg);
138 | }
139 |
140 | .github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon {
141 | top: 80px;
142 | right: -43px;
143 |
144 | -webkit-transform: rotate(-45deg);
145 | -moz-transform: rotate(-45deg);
146 | -ms-transform: rotate(-45deg);
147 | -o-transform: rotate(-45deg);
148 | transform: rotate(-45deg);
149 | }
150 |
--------------------------------------------------------------------------------
/src/theme.scss:
--------------------------------------------------------------------------------
1 | @use '@angular/material' as mat;
2 | // Plus imports for other components in your app.
3 |
4 | // Define the theme object.
5 | $busy-app-theme: mat.define-theme(
6 | (
7 | color: (
8 | theme-type: light,
9 | primary: mat.$blue-palette
10 | ),
11 | density: (
12 | scale: 0
13 | )
14 | )
15 | );
16 |
17 | // Include the base styles for Angular Material core. We include this here so that you only
18 | // have to load a single css file for Angular Material in your app.
19 | @include mat.all-component-typographies();
20 | @include mat.elevation-classes();
21 | @include mat.app-background();
22 |
23 | // Include theme styles for core and each component used in your app.
24 | // Alternatively, you can import and @include the theme mixins for each component
25 | // that you are using.
26 | :root {
27 | @include mat.all-component-themes($busy-app-theme);
28 | }
29 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "./tsconfig.json",
5 | "compilerOptions": {
6 | "outDir": "./out-tsc/app",
7 | "types": []
8 | },
9 | "files": [
10 | "src/main.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "compileOnSave": false,
5 | "compilerOptions": {
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "noImplicitReturns": true,
9 | "noFallthroughCasesInSwitch": true,
10 | "isolatedModules": true,
11 | "esModuleInterop": true,
12 | "sourceMap": true,
13 | "declaration": false,
14 | "emitDecoratorMetadata": true,
15 | "experimentalDecorators": true,
16 | "moduleResolution": "bundler",
17 | "importHelpers": true,
18 | "target": "ES2022",
19 | "module": "ES2022",
20 | "paths": {
21 | "angular-busy2": [
22 | "./dist/angular-busy2",
23 | "./projects/angular-busy2/src/public_api.ts"
24 | ]
25 | }
26 | },
27 | "angularCompilerOptions": {
28 | "strictInjectionParameters": true,
29 | "strictInputAccessModifiers": true,
30 | "strictTemplates": true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tsconfig.lint.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "./tsconfig.app.json",
5 | "include": [
6 | // adjust "includes" to what makes sense for you and your project
7 | "src/**/*.ts"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3 | {
4 | "extends": "./tsconfig.json",
5 | "compilerOptions": {
6 | "outDir": "./out-tsc/spec",
7 | "types": [
8 | "jasmine"
9 | ]
10 | },
11 | "include": [
12 | "src/**/*.spec.ts",
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------