ngx-print 21.2.0 → 22.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintrc.json +50 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  5. package/.github/dependabot.yml +17 -0
  6. package/.github/workflows/PullRequest.yml +32 -0
  7. package/.github/workflows/stale.yml +25 -0
  8. package/.prettierignore +42 -0
  9. package/.prettierrc.json +14 -0
  10. package/CHANGELOG.md +126 -0
  11. package/README.md +90 -52
  12. package/_config.yml +1 -0
  13. package/angular.json +132 -0
  14. package/eslint.config.js +32 -0
  15. package/ng-package.json +7 -0
  16. package/package.json +60 -43
  17. package/projects/demo/public/favicon.ico +0 -0
  18. package/projects/demo/src/app/app.config.ts +11 -0
  19. package/projects/demo/src/app/app.routes.ts +3 -0
  20. package/projects/demo/src/app/demo.component.html +83 -0
  21. package/projects/demo/src/app/demo.component.scss +54 -0
  22. package/projects/demo/src/app/demo.component.ts +73 -0
  23. package/projects/demo/src/index.html +13 -0
  24. package/projects/demo/src/main.ts +5 -0
  25. package/projects/demo/src/styles.scss +1 -0
  26. package/projects/demo/tsconfig.app.json +19 -0
  27. package/projects/demo/tsconfig.spec.json +15 -0
  28. package/src/lib/ngx-print.base.ts +381 -0
  29. package/src/lib/ngx-print.directive.spec.ts +232 -0
  30. package/src/lib/ngx-print.directive.ts +72 -0
  31. package/src/lib/ngx-print.module.ts +8 -0
  32. package/src/lib/ngx-print.service.spec.ts +276 -0
  33. package/src/lib/ngx-print.service.ts +50 -0
  34. package/src/lib/print-options.ts +16 -0
  35. package/src/public_api.ts +8 -0
  36. package/tsconfig.json +38 -0
  37. package/tsconfig.lib.json +19 -0
  38. package/tsconfig.spec.json +10 -0
  39. package/tslint.json +17 -0
  40. package/fesm2022/ngx-print.mjs +0 -543
  41. package/fesm2022/ngx-print.mjs.map +0 -1
  42. package/types/ngx-print.d.ts +0 -228
  43. package/types/ngx-print.d.ts.map +0 -1
package/angular.json ADDED
@@ -0,0 +1,132 @@
1
+ {
2
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+ "version": 1,
4
+ "newProjectRoot": "projects",
5
+ "projects": {
6
+ "ngx-print": {
7
+ "root": "",
8
+ "sourceRoot": "src",
9
+ "projectType": "library",
10
+ "prefix": "lib",
11
+ "architect": {
12
+ "build": {
13
+ "builder": "@angular/build:ng-packagr",
14
+ "options": {
15
+ "tsConfig": "tsconfig.lib.json",
16
+ "project": "ng-package.json"
17
+ },
18
+ "configurations": {
19
+ "development": {}
20
+ }
21
+ },
22
+ "test": {
23
+ "builder": "@angular/build:unit-test"
24
+ },
25
+ "lint": {
26
+ "builder": "@angular-eslint/builder:lint",
27
+ "options": {
28
+ "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
29
+ }
30
+ }
31
+ }
32
+ },
33
+ "demo": {
34
+ "projectType": "application",
35
+ "schematics": {
36
+ "@schematics/angular:component": {
37
+ "style": "scss"
38
+ }
39
+ },
40
+ "root": "projects/demo",
41
+ "sourceRoot": "projects/demo/src",
42
+ "prefix": "app",
43
+ "architect": {
44
+ "build": {
45
+ "builder": "@angular/build:application",
46
+ "options": {
47
+ "browser": "projects/demo/src/main.ts",
48
+ "tsConfig": "projects/demo/tsconfig.app.json",
49
+ "inlineStyleLanguage": "scss",
50
+ "assets": [
51
+ {
52
+ "glob": "**/*",
53
+ "input": "projects/demo/public"
54
+ }
55
+ ],
56
+ "styles": [
57
+ "projects/demo/src/styles.scss"
58
+ ]
59
+ },
60
+ "configurations": {
61
+ "production": {
62
+ "budgets": [
63
+ {
64
+ "type": "initial",
65
+ "maximumWarning": "500kB",
66
+ "maximumError": "1MB"
67
+ },
68
+ {
69
+ "type": "anyComponentStyle",
70
+ "maximumWarning": "4kB",
71
+ "maximumError": "8kB"
72
+ }
73
+ ],
74
+ "outputHashing": "all"
75
+ },
76
+ "development": {
77
+ "optimization": false,
78
+ "extractLicenses": false,
79
+ "sourceMap": true
80
+ }
81
+ },
82
+ "defaultConfiguration": "production"
83
+ },
84
+ "serve": {
85
+ "builder": "@angular/build:dev-server",
86
+ "configurations": {
87
+ "production": {
88
+ "buildTarget": "demo:build:production"
89
+ },
90
+ "development": {
91
+ "buildTarget": "demo:build:development"
92
+ }
93
+ },
94
+ "defaultConfiguration": "development"
95
+ },
96
+ "test": {
97
+ "builder": "@angular/build:unit-test"
98
+ }
99
+ }
100
+ }
101
+ },
102
+ "cli": {
103
+ "analytics": false,
104
+ "schematicCollections": ["angular-eslint"]
105
+ },
106
+ "schematics": {
107
+ "@schematics/angular:component": {
108
+ "type": "component"
109
+ },
110
+ "@schematics/angular:directive": {
111
+ "type": "directive"
112
+ },
113
+ "@schematics/angular:service": {
114
+ "type": "service"
115
+ },
116
+ "@schematics/angular:guard": {
117
+ "typeSeparator": "."
118
+ },
119
+ "@schematics/angular:interceptor": {
120
+ "typeSeparator": "."
121
+ },
122
+ "@schematics/angular:module": {
123
+ "typeSeparator": "."
124
+ },
125
+ "@schematics/angular:pipe": {
126
+ "typeSeparator": "."
127
+ },
128
+ "@schematics/angular:resolver": {
129
+ "typeSeparator": "."
130
+ }
131
+ }
132
+ }
@@ -0,0 +1,32 @@
1
+ // @ts-check
2
+ const eslint = require('@eslint/js');
3
+ const tseslint = require('typescript-eslint');
4
+ const angular = require('angular-eslint');
5
+
6
+ module.exports = tseslint.config(
7
+ {
8
+ files: ['**/*.ts'],
9
+ extends: [
10
+ eslint.configs.recommended,
11
+ ...tseslint.configs.recommended,
12
+ ...tseslint.configs.stylistic,
13
+ ...angular.configs.tsRecommended,
14
+ ],
15
+ processor: angular.processInlineTemplates,
16
+ rules: {
17
+ // our project thinks using renaming inputs is ok
18
+ '@angular-eslint/no-input-rename': 'off',
19
+ },
20
+ },
21
+ {
22
+ files: ['**/*.html'],
23
+ extends: [
24
+ ...angular.configs.templateRecommended,
25
+ ...angular.configs.templateAccessibility,
26
+ ],
27
+ rules: {
28
+ // our project thinks using negated async pipes is ok
29
+ '@angular-eslint/template/no-negated-async': 'off',
30
+ },
31
+ },
32
+ );
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "./node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "./dist/ngx-print",
4
+ "lib": {
5
+ "entryFile": "src/public_api.ts"
6
+ }
7
+ }
package/package.json CHANGED
@@ -1,43 +1,60 @@
1
- {
2
- "name": "ngx-print",
3
- "version": "21.2.0",
4
- "description": "Plug n' Play Angular (2++) directive to print your stuff",
5
- "author": "https://github.com/ngx-print/ngx-print/graphs/contributors",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/ngx-print/ngx-print.git"
9
- },
10
- "license": "MIT",
11
- "bugs": {
12
- "url": "https://github.com/ngx-print/ngx-print/issues"
13
- },
14
- "homepage": "https://github.com/ngx-print/ngx-print#readme",
15
- "keywords": [
16
- "print",
17
- "angular",
18
- "library",
19
- "ng-print",
20
- "ngx-print",
21
- "directive",
22
- "dependency",
23
- "angular-print"
24
- ],
25
- "peerDependencies": {
26
- "rxjs": "^7.4.0"
27
- },
28
- "module": "fesm2022/ngx-print.mjs",
29
- "typings": "types/ngx-print.d.ts",
30
- "exports": {
31
- "./package.json": {
32
- "default": "./package.json"
33
- },
34
- ".": {
35
- "types": "./types/ngx-print.d.ts",
36
- "default": "./fesm2022/ngx-print.mjs"
37
- }
38
- },
39
- "sideEffects": false,
40
- "dependencies": {
41
- "tslib": "^2.3.0"
42
- }
43
- }
1
+ {
2
+ "name": "ngx-print",
3
+ "version": "22.1.0",
4
+ "description": "Plug n' Play Angular directive to print your stuff",
5
+ "author": "https://github.com/ngx-print/ngx-print/graphs/contributors",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ngx-print/ngx-print.git"
9
+ },
10
+ "license": "MIT",
11
+ "bugs": {
12
+ "url": "https://github.com/ngx-print/ngx-print/issues"
13
+ },
14
+ "homepage": "https://github.com/ngx-print/ngx-print#readme",
15
+ "keywords": [
16
+ "print",
17
+ "angular",
18
+ "library",
19
+ "ng-print",
20
+ "ngx-print",
21
+ "directive",
22
+ "dependency",
23
+ "angular-print"
24
+ ],
25
+ "scripts": {
26
+ "ng": "ng",
27
+ "build": "ng build ngx-print",
28
+ "test": "ng test ngx-print --no-watch --coverage --no-progress",
29
+ "serve:demo": "ng serve demo",
30
+ "lint": "ng lint"
31
+ },
32
+ "devDependencies": {
33
+ "@angular/build": "^22.0.3",
34
+ "@angular/cli": "^22.0.3",
35
+ "@angular/common": "^22.0.2",
36
+ "@angular/compiler": "^22.0.2",
37
+ "@angular/compiler-cli": "^22.0.2",
38
+ "@angular/core": "^22.0.2",
39
+ "@angular/forms": "^22.0.2",
40
+ "@angular/localize": "^22.0.2",
41
+ "@angular/platform-browser": "^22.0.2",
42
+ "@angular/router": "^22.0.2",
43
+ "@eslint/js": "^10.0.1",
44
+ "@types/node": "^24.13.2",
45
+ "@vitest/coverage-v8": "^4.1.9",
46
+ "angular-eslint": "22.0.0",
47
+ "eslint": "^10.3.0",
48
+ "eslint-config-prettier": "^10.1.8",
49
+ "eslint-plugin-prettier": "^5.5.6",
50
+ "jsdom": "^29.1.1",
51
+ "ng-packagr": "^22.0.0",
52
+ "prettier": "^3.8.4",
53
+ "typescript": "~6.0.3",
54
+ "typescript-eslint": "8.62.0",
55
+ "vitest": "^4.0.8"
56
+ },
57
+ "peerDependencies": {
58
+ "rxjs": "^7.4.0"
59
+ }
60
+ }
Binary file
@@ -0,0 +1,11 @@
1
+ import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
2
+ import { provideRouter } from '@angular/router';
3
+
4
+ import { routes } from './app.routes';
5
+
6
+ export const appConfig: ApplicationConfig = {
7
+ providers: [
8
+ provideBrowserGlobalErrorListeners(),
9
+ provideRouter(routes)
10
+ ]
11
+ };
@@ -0,0 +1,3 @@
1
+ import { Routes } from '@angular/router';
2
+
3
+ export const routes: Routes = [];
@@ -0,0 +1,83 @@
1
+ <h1>Print Library Demo</h1>
2
+
3
+ <p>
4
+ Fill out the form and draw on the canvas below, then click print.
5
+ The library will capture the current state of all fields and the canvas.
6
+ </p>
7
+
8
+ <form class="option-form" [formGroup]="optionForm">
9
+ <fieldset>
10
+ <legend>Print options:</legend>
11
+ <div class="form-group">
12
+ @for (method of printMethods; track method) {
13
+ <div>
14
+ <label>
15
+ <input [formControlName]="'printMethod'"
16
+ [value]="method"
17
+ type="radio"
18
+ id="print-method-{{ $index }}"
19
+ name="printMethod"
20
+ />
21
+ {{ method }}
22
+ </label>
23
+ </div>
24
+ }
25
+ </div>
26
+
27
+ <div class="form-group">
28
+ <label for="fullName">printTitle</label>
29
+ <input id="fullName" type="text" formControlName="printTitle" />
30
+ </div>
31
+
32
+ <div class="form-group">
33
+ <label>Checkbox (Input)</label>
34
+ <div>
35
+ <input type="checkbox" id="agree" formControlName="useExistingCss" />
36
+ <label for="agree" style="display:inline;">useExistingCss</label>
37
+ </div>
38
+ </div>
39
+ </fieldset>
40
+ </form>
41
+
42
+ <button type="button" (click)="onPrint()">Print Section</button>
43
+
44
+ <!-- This is the section targeted by the ID -->
45
+ <div id="print-demo-section" class="print-container">
46
+ <h3>printable-section</h3>
47
+
48
+ <form [formGroup]="demoform">
49
+ <div class="form-group">
50
+ <label for="fullName">Full Name (Input)</label>
51
+ <input id="fullName" type="text" formControlName="name" placeholder="Enter your name" />
52
+ </div>
53
+
54
+ <div class="form-group">
55
+ <label for="role">Role (Select)</label>
56
+ <select id="role" formControlName="role">
57
+ <option value="developer">Developer</option>
58
+ <option value="designer">Designer</option>
59
+ <option value="manager">Manager</option>
60
+ </select>
61
+ </div>
62
+
63
+ <div class="form-group">
64
+ <label for="bio">Biography (Textarea)</label>
65
+ <textarea id="bio" formControlName="bio" rows="4"></textarea>
66
+ </div>
67
+
68
+ <div class="form-group">
69
+ <label>Checkbox (Input)</label>
70
+ <div>
71
+ <input type="checkbox" id="agree" formControlName="agree" />
72
+ <label for="agree" style="display:inline;">I agree to the terms</label>
73
+ </div>
74
+ </div>
75
+ </form>
76
+
77
+ <div class="form-group">
78
+ <label>Signature / Drawing (Canvas)</label>
79
+ <canvas #drawingCanvas width="400" height="150"></canvas>
80
+ </div>
81
+
82
+ <p>Swedish: Åå, Japanese: ひらがな, Chinese: 你好, Korean: 안녕하세요</p>
83
+ </div>
@@ -0,0 +1,54 @@
1
+ :host {
2
+ display: block;
3
+ padding: 2rem;
4
+ font-family: sans-serif;
5
+ }
6
+
7
+ .form-group {
8
+ margin-bottom: 1rem;
9
+ }
10
+
11
+ label {
12
+ display: block;
13
+ margin-bottom: 0.5rem;
14
+ font-weight: bold;
15
+ }
16
+
17
+ .option-form {
18
+ max-width: 600px;
19
+ margin-bottom: 2rem;
20
+ }
21
+
22
+ button {
23
+ padding: 0.75rem 1.5rem;
24
+ background: #007bff;
25
+ color: white;
26
+ border: none;
27
+ border-radius: 4px;
28
+ cursor: pointer;
29
+ font-size: 1rem;
30
+
31
+ &:hover {
32
+ background: #0056b3;
33
+ }
34
+ }
35
+
36
+ .print-container {
37
+ border: 2px dashed #ccc;
38
+ padding: 2rem;
39
+ margin: 1rem 0;
40
+ max-width: 600px;
41
+
42
+ input,
43
+ select,
44
+ textarea {
45
+ width: 100%;
46
+ padding: 0.5rem;
47
+ margin-bottom: 0.5rem;
48
+ }
49
+
50
+ canvas {
51
+ border: 1px solid #000;
52
+ background: #f0f0f0;
53
+ }
54
+ }
@@ -0,0 +1,73 @@
1
+ import { afterNextRender, Component, ElementRef, inject, viewChild } from '@angular/core';
2
+ import { NgxPrintService } from '../../../../src/lib/ngx-print.service';
3
+ import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
4
+ import { PrintOptions } from '../../../../src/public_api';
5
+
6
+ @Component({
7
+ selector: 'app-root',
8
+ imports: [ReactiveFormsModule],
9
+ templateUrl: './demo.component.html',
10
+ styleUrl: './demo.component.scss',
11
+ })
12
+ export class DemoComponent {
13
+ private _printService = inject(NgxPrintService);
14
+ private _fb = inject(FormBuilder);
15
+
16
+ protected readonly printMethods = ['iframe', 'window', 'tab'] as const;
17
+
18
+ canvasRef = viewChild.required<ElementRef<HTMLCanvasElement>>('drawingCanvas');
19
+
20
+ optionForm = this._fb.group({
21
+ printMethod: this._fb.nonNullable.control<typeof PrintOptions.prototype.printMethod>('iframe'),
22
+ printTitle: this._fb.nonNullable.control<string>('Demo Component Print'),
23
+ useExistingCss: this._fb.nonNullable.control<boolean>(true),
24
+ });
25
+
26
+ demoform = this._fb.group({
27
+ name: ['Angular Developer'],
28
+ role: ['developer'],
29
+ bio: ['This text will be preserved in the print view.'],
30
+ agree: [true],
31
+ });
32
+
33
+ constructor() {
34
+ // Draw on canvas once it is ready (SSR safe)
35
+ afterNextRender(() => {
36
+ this.initCanvas();
37
+ });
38
+ }
39
+
40
+ onPrint() {
41
+ this._printService.print({
42
+ printSectionId: 'print-demo-section',
43
+ printTitle: this.optionForm.controls.printTitle.value!,
44
+ printMethod: this.optionForm.controls.printMethod.value,
45
+ useExistingCss: this.optionForm.controls.useExistingCss.value,
46
+ });
47
+ }
48
+
49
+ private initCanvas() {
50
+ const canvas = this.canvasRef().nativeElement;
51
+ const ctx = canvas.getContext('2d');
52
+
53
+ if (ctx) {
54
+ // Draw a background and some shapes to prove canvas printing works
55
+ ctx.fillStyle = '#ffffff';
56
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
57
+
58
+ ctx.beginPath();
59
+ ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // Outer circle
60
+ ctx.moveTo(110, 75);
61
+ ctx.arc(75, 75, 35, 0, Math.PI, false); // Mouth (clockwise)
62
+ ctx.moveTo(65, 65);
63
+ ctx.arc(60, 65, 5, 0, Math.PI * 2, true); // Left eye
64
+ ctx.moveTo(95, 65);
65
+ ctx.arc(90, 65, 5, 0, Math.PI * 2, true); // Right eye
66
+ ctx.stroke();
67
+
68
+ ctx.font = '20px Arial';
69
+ ctx.fillStyle = 'blue';
70
+ ctx.fillText('Canvas Content', 150, 85);
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Demo</title>
6
+ <base href="/">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
9
+ </head>
10
+ <body>
11
+ <app-root></app-root>
12
+ </body>
13
+ </html>
@@ -0,0 +1,5 @@
1
+ import { bootstrapApplication } from '@angular/platform-browser';
2
+ import { appConfig } from './app/app.config';
3
+ import { DemoComponent } from './app/demo.component';
4
+
5
+ bootstrapApplication(DemoComponent, appConfig).catch(err => console.error(err));
@@ -0,0 +1 @@
1
+ /* You can add global styles to this file, and also import other style files */
@@ -0,0 +1,19 @@
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
+ "include": ["src/**/*.ts"],
10
+ "exclude": ["src/**/*.spec.ts"],
11
+ "angularCompilerOptions": {
12
+ "extendedDiagnostics": {
13
+ "checks": {
14
+ "nullishCoalescingNotNullable": "suppress",
15
+ "optionalChainNotNullable": "suppress"
16
+ }
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,15 @@
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
+ "vitest/globals"
9
+ ]
10
+ },
11
+ "include": [
12
+ "src/**/*.d.ts",
13
+ "src/**/*.spec.ts"
14
+ ]
15
+ }