ngx-mat-input-tel 21.4.2 → 21.4.3

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 (61) hide show
  1. package/.angulardoc.json +4 -0
  2. package/.editorconfig +13 -0
  3. package/.github/FUNDING.yml +13 -0
  4. package/.github/instructions/copilot-instructions.md +58 -0
  5. package/.github/workflows/ci.yml +27 -0
  6. package/.github/workflows/publish.yml +41 -0
  7. package/.github/workflows/test.yml +39 -0
  8. package/.husky/commit-msg +4 -0
  9. package/.husky/pre-commit +1 -0
  10. package/.prettierrc +15 -0
  11. package/angular.json +165 -0
  12. package/commitlint.config.ts +3 -0
  13. package/eslint.config.js +43 -0
  14. package/example-1.png +0 -0
  15. package/package.json +83 -55
  16. package/pnpm-workspace.yaml +18 -0
  17. package/projects/demo/eslint.config.js +3 -0
  18. package/projects/demo/karma.conf.js +31 -0
  19. package/projects/demo/src/app/app.html +123 -0
  20. package/projects/demo/src/app/app.scss +16 -0
  21. package/projects/demo/src/app/app.spec.ts +35 -0
  22. package/projects/demo/src/app/app.ts +100 -0
  23. package/projects/demo/src/app/dialog/dialog.html +12 -0
  24. package/projects/demo/src/app/dialog/dialog.ts +31 -0
  25. package/projects/demo/src/environments/environment.prod.ts +3 -0
  26. package/projects/demo/src/environments/environment.ts +3 -0
  27. package/projects/demo/src/favicon.ico +0 -0
  28. package/projects/demo/src/index.html +21 -0
  29. package/projects/demo/src/main.ts +16 -0
  30. package/projects/demo/src/styles.scss +32 -0
  31. package/projects/demo/tsconfig.app.json +9 -0
  32. package/projects/demo/tsconfig.spec.json +9 -0
  33. package/projects/ngx-mat-input-tel/eslint.config.js +3 -0
  34. package/projects/ngx-mat-input-tel/karma.conf.js +31 -0
  35. package/projects/ngx-mat-input-tel/ng-package.json +8 -0
  36. package/projects/ngx-mat-input-tel/package.json +46 -0
  37. package/projects/ngx-mat-input-tel/src/lib/assets/arrow_drop_down_grey600_18dp.png +0 -0
  38. package/projects/ngx-mat-input-tel/src/lib/assets/flags_sprite_2x.png +0 -0
  39. package/projects/ngx-mat-input-tel/src/lib/data/country-code.const.ts +792 -0
  40. package/projects/ngx-mat-input-tel/src/lib/model/country.model.ts +12 -0
  41. package/projects/ngx-mat-input-tel/src/lib/model/phone-number-format.model.ts +1 -0
  42. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel-dialog/ngx-mat-input-tel.dialog.html +82 -0
  43. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel-dialog/ngx-mat-input-tel.dialog.scss +91 -0
  44. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel-dialog/ngx-mat-input-tel.dialog.ts +128 -0
  45. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel-flag/ngx-mat-input-tel-flag.scss +319 -0
  46. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel-flag/ngx-mat-input-tel-flag.ts +72 -0
  47. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel.html +42 -0
  48. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel.scss +122 -0
  49. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel.spec.ts +318 -0
  50. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel.ts +625 -0
  51. package/projects/ngx-mat-input-tel/src/lib/ngx-mat-input-tel.validator.ts +35 -0
  52. package/projects/ngx-mat-input-tel/src/lib/remove-iso.pipe.ts +13 -0
  53. package/projects/ngx-mat-input-tel/src/public-api.ts +7 -0
  54. package/projects/ngx-mat-input-tel/src/test.ts +10 -0
  55. package/projects/ngx-mat-input-tel/tsconfig.lib.json +19 -0
  56. package/projects/ngx-mat-input-tel/tsconfig.lib.prod.json +9 -0
  57. package/projects/ngx-mat-input-tel/tsconfig.spec.json +8 -0
  58. package/tsconfig.json +28 -0
  59. package/fesm2022/ngx-mat-input-tel.mjs +0 -1603
  60. package/fesm2022/ngx-mat-input-tel.mjs.map +0 -1
  61. package/types/ngx-mat-input-tel.d.ts +0 -162
@@ -0,0 +1,123 @@
1
+ <div style="margin: 50px">
2
+ <h3 id="phoneInput">Test International Telephone Input Form</h3>
3
+ <br />
4
+
5
+ <form #f1="ngForm" [formGroup]="phoneForm" (ngSubmit)="onSubmit()">
6
+ <mat-form-field>
7
+ <ngx-mat-input-tel
8
+ [cssClass]="'custom'"
9
+ [preferredCountries]="['CA', 'US']"
10
+ defaultCountry="US"
11
+ enablePlaceholder
12
+ enableSearch
13
+ formControlName="phone"
14
+ describedBy="phoneInput"
15
+ required
16
+ #phone
17
+ maxLength="20"
18
+ ></ngx-mat-input-tel>
19
+ <mat-hint>e.g. {{ phone.$selectedCountry().placeholder }}</mat-hint>
20
+ @if (phoneForm.controls.phone.errors?.required) {
21
+ <mat-error> Required Field </mat-error>
22
+ } @else if (phoneForm.controls.phone.errors?.maxlength) {
23
+ <mat-error>
24
+ Length:{{ phoneForm.controls.phone.errors?.maxlength.actualLength }}/{{
25
+ phoneForm.controls.phone.errors?.maxlength.requiredLength
26
+ }}
27
+ </mat-error>
28
+ } @else if (f1.submitted && phoneForm.controls.phone.errors?.validatePhoneNumber) {
29
+ <mat-error> Invalid Number </mat-error>
30
+ }
31
+ </mat-form-field>
32
+
33
+ <div class="buttons-container">
34
+ <button mat-stroked-button>Submit</button>
35
+ <button type="reset" mat-stroked-button (click)="onReset()">Reset</button>
36
+ </div>
37
+ </form>
38
+
39
+ <br />
40
+ <div class="value-container">
41
+ <strong>Is form valid:</strong>
42
+ <code>{{ phoneForm.valid }}</code>
43
+ </div>
44
+ <div class="value-container">
45
+ <strong>Is input valid:</strong>
46
+ <code>{{ !phoneForm.controls.phone.invalid }}</code>
47
+ </div>
48
+ <div class="value-container">
49
+ <strong>Is input touched:</strong>
50
+ <code>{{ phoneForm.controls.phone.touched }}</code>
51
+ </div>
52
+ <div class="value-container">
53
+ <strong>Form value:</strong>
54
+ <pre><code>{{ phoneForm.value | json }}</code></pre>
55
+ </div>
56
+ <div class="value-container">
57
+ <strong>Form validation errors:</strong>
58
+ @for (control of phoneForm.controls | keyvalue; track control) {
59
+ <pre><code> {{ control.key }}: {{ control.value.errors | json }} </code></pre>
60
+ }
61
+ </div>
62
+
63
+ <mat-divider></mat-divider>
64
+
65
+ <form #f2="ngForm" [formGroup]="profileForm" class="second-form">
66
+ <h2>Required, PlaceHolder, Separated & OnlyCountries</h2>
67
+
68
+ <mat-form-field floatLabel="always" appearance="outline">
69
+ <mat-label>Phone</mat-label>
70
+ <ngx-mat-input-tel
71
+ [cssClass]="'custom'"
72
+ [preferredCountries]="['US', 'FR']"
73
+ [countriesName]="frCountriesName"
74
+ [onlyCountries]="$onlyCountries()"
75
+ [searchPlaceholder]="'Buscar...'"
76
+ [formControl]="profileForm.controls.phone"
77
+ resetOnChange
78
+ enablePlaceholder
79
+ enableSearch
80
+ #phone1
81
+ ></ngx-mat-input-tel>
82
+ <mat-hint>e.g. {{ phone1.$selectedCountry().placeholder }}</mat-hint>
83
+ @if (profileForm.controls.phone.errors?.required) {
84
+ <mat-error> Required Field </mat-error>
85
+ }
86
+ @if (profileForm.controls.phone.errors?.validatePhoneNumber) {
87
+ <mat-error> Invalid Number </mat-error>
88
+ }
89
+ @if (profileForm.controls.phone.errors?.invalidCountry) {
90
+ <mat-error> Country not allowed </mat-error>
91
+ }
92
+ </mat-form-field>
93
+ </form>
94
+
95
+ <div class="value-container">
96
+ <strong>Form value:</strong>
97
+ <pre><code>{{ f2.form.value | json }}</code></pre>
98
+ </div>
99
+
100
+ <mat-divider></mat-divider>
101
+
102
+ <form [formGroup]="profileForm" class="second-form">
103
+ <h2>Separated Dial Code</h2>
104
+
105
+ <mat-form-field floatLabel="always" appearance="outline" class="separated-flag">
106
+ <mat-label>Phone</mat-label>
107
+ <ngx-mat-input-tel
108
+ resetOnChange
109
+ placeholder="Your number"
110
+ enableSearch
111
+ separateDialCode
112
+ ></ngx-mat-input-tel>
113
+ </mat-form-field>
114
+ </form>
115
+
116
+ <mat-divider></mat-divider>
117
+
118
+ <div>
119
+ <h2>Inside a modal</h2>
120
+
121
+ <button mat-raised-button (click)="openDialog()">Open Dialog</button>
122
+ </div>
123
+ </div>
@@ -0,0 +1,16 @@
1
+ .second-form ngx-mat-input-tel {
2
+ --ngxMatInputTel-opacity: 1;
3
+ }
4
+
5
+ .buttons-container {
6
+ display: flex;
7
+ gap: 16px;
8
+ }
9
+
10
+ mat-divider {
11
+ margin-bottom: 16px;
12
+ }
13
+
14
+ .separated-flag {
15
+ margin-left: 128px;
16
+ }
@@ -0,0 +1,35 @@
1
+ import { CommonModule } from "@angular/common";
2
+ import { TestBed, waitForAsync } from "@angular/core/testing";
3
+ import { FormsModule, ReactiveFormsModule } from "@angular/forms";
4
+ import { MatButtonModule } from "@angular/material/button";
5
+ import { MatDividerModule } from "@angular/material/divider";
6
+ import { MatFormFieldModule } from "@angular/material/form-field";
7
+ import { MatInputModule } from "@angular/material/input";
8
+ import { MatMenuModule } from "@angular/material/menu";
9
+ import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
10
+ import { AppComponent } from "./app";
11
+
12
+ describe("AppComponent", () => {
13
+ beforeEach(waitForAsync(() => {
14
+ TestBed.configureTestingModule({
15
+ imports: [
16
+ FormsModule,
17
+ ReactiveFormsModule,
18
+ MatFormFieldModule,
19
+ MatInputModule,
20
+ MatButtonModule,
21
+ MatMenuModule,
22
+ MatDividerModule,
23
+ BrowserAnimationsModule,
24
+ CommonModule,
25
+ AppComponent,
26
+ ],
27
+ }).compileComponents();
28
+ }));
29
+
30
+ it("should create the app", () => {
31
+ const fixture = TestBed.createComponent(AppComponent);
32
+ const app = fixture.debugElementInstance;
33
+ expect(app).toBeTruthy();
34
+ });
35
+ });
@@ -0,0 +1,100 @@
1
+ import { JsonPipe, KeyValuePipe } from "@angular/common";
2
+ import { AfterViewInit, Component, inject, signal } from "@angular/core";
3
+ import {
4
+ FormControl,
5
+ FormGroup,
6
+ FormsModule,
7
+ ReactiveFormsModule,
8
+ Validators,
9
+ } from "@angular/forms";
10
+ import { MatButtonModule } from "@angular/material/button";
11
+ import { MatDialog } from "@angular/material/dialog";
12
+ import { MatDividerModule } from "@angular/material/divider";
13
+ import { MatFormFieldModule } from "@angular/material/form-field";
14
+ import { NgxMatInputTelComponent } from "../../../ngx-mat-input-tel/src/lib/ngx-mat-input-tel";
15
+ import { DialogComponent } from "./dialog/dialog";
16
+
17
+ interface PhoneForm {
18
+ phone: FormControl<string | null>;
19
+ }
20
+
21
+ interface ProfileForm {
22
+ phone: FormControl<string | null>;
23
+ }
24
+
25
+ @Component({
26
+ selector: "ngx-root",
27
+ templateUrl: "./app.html",
28
+ styleUrls: ["./app.scss"],
29
+ imports: [
30
+ // Forms
31
+ FormsModule,
32
+ ReactiveFormsModule,
33
+ MatFormFieldModule,
34
+
35
+ // Components
36
+ NgxMatInputTelComponent,
37
+
38
+ // Pipes
39
+ JsonPipe,
40
+ KeyValuePipe,
41
+
42
+ // Mat
43
+ MatButtonModule,
44
+ MatDividerModule,
45
+ ],
46
+ })
47
+ export class AppComponent implements AfterViewInit {
48
+ readonly #matDialog = inject(MatDialog);
49
+
50
+ phoneForm = new FormGroup<PhoneForm>({
51
+ phone: new FormControl(null, [Validators.required, Validators.maxLength(12)]),
52
+ });
53
+
54
+ profileForm = new FormGroup<ProfileForm>({
55
+ phone: new FormControl(null),
56
+ });
57
+
58
+ $onlyCountries = signal(["US", "DE"]);
59
+
60
+ frCountriesName: Record<string, string> = {
61
+ US: "États-Unis",
62
+ FR: "France",
63
+ DE: "Allemagne",
64
+ };
65
+
66
+ constructor() {
67
+ setTimeout(() => {
68
+ // Fake onlyCountries change - add FR
69
+ this.$onlyCountries.set(["US", "DE", "FR"]);
70
+ }, 1000);
71
+ }
72
+
73
+ onSubmit() {
74
+ this.phoneForm.markAllAsTouched();
75
+ }
76
+
77
+ onReset() {
78
+ this.phoneForm.reset();
79
+ }
80
+
81
+ ngAfterViewInit() {
82
+ this.phoneForm.valueChanges.subscribe((value) => {
83
+ // Only emitting correct number
84
+ console.log("phoneForm.valueChanges", value);
85
+ });
86
+
87
+ this.profileForm.valueChanges.subscribe((value) => {
88
+ // Only emitting correct number
89
+ console.log("phoneForm.valueChanges", value);
90
+ });
91
+ }
92
+
93
+ openDialog() {
94
+ const dialogRef = this.#matDialog.open(DialogComponent);
95
+
96
+ dialogRef.afterClosed().subscribe((result) => {
97
+ console.log("The dialog was closed", result);
98
+ });
99
+ }
100
+ }
@@ -0,0 +1,12 @@
1
+ <h2 mat-dialog-title>Inside a dialog</h2>
2
+
3
+ <mat-dialog-content [formGroup]="phoneForm">
4
+ <mat-form-field>
5
+ <mat-label>Phone Number</mat-label>
6
+ <ngx-mat-input-tel formControlName="phone" enableSearch></ngx-mat-input-tel>
7
+ </mat-form-field>
8
+ </mat-dialog-content>
9
+
10
+ <mat-dialog-actions>
11
+ <button matButton [mat-dialog-close]="phoneForm.getRawValue()" cdkFocusInitial>Close</button>
12
+ </mat-dialog-actions>
@@ -0,0 +1,31 @@
1
+ import { DialogModule } from "@angular/cdk/dialog";
2
+ import { ChangeDetectionStrategy, Component } from "@angular/core";
3
+ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from "@angular/forms";
4
+ import { MatButtonModule } from "@angular/material/button";
5
+ import { MatDialogModule } from "@angular/material/dialog";
6
+ import { MatFormFieldModule } from "@angular/material/form-field";
7
+ import { NgxMatInputTelComponent } from "projects/ngx-mat-input-tel/src/public-api";
8
+
9
+ @Component({
10
+ selector: "ngx-dialog",
11
+ imports: [
12
+ // Forms
13
+ ReactiveFormsModule,
14
+ MatFormFieldModule,
15
+
16
+ // Mat
17
+ DialogModule,
18
+ MatButtonModule,
19
+ MatDialogModule,
20
+
21
+ // Components
22
+ NgxMatInputTelComponent,
23
+ ],
24
+ templateUrl: "./dialog.html",
25
+ changeDetection: ChangeDetectionStrategy.OnPush,
26
+ })
27
+ export class DialogComponent {
28
+ phoneForm = new FormGroup({
29
+ phone: new FormControl(null, [Validators.required, Validators.maxLength(12)]),
30
+ });
31
+ }
@@ -0,0 +1,3 @@
1
+ export const environment = {
2
+ production: true,
3
+ };
@@ -0,0 +1,3 @@
1
+ export const environment = {
2
+ production: false,
3
+ };
Binary file
@@ -0,0 +1,21 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>ngxMatInputTelTester</title>
6
+ <base href="/" />
7
+
8
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
9
+ <link rel="icon" type="image/x-icon" href="favicon.ico" />
10
+
11
+ <link
12
+ rel="stylesheet"
13
+ href="http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300ita‌​lic,400italic,500,500italic,700,700italic,900italic,900&display=swap"
14
+ defer
15
+ />
16
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
17
+ </head>
18
+ <body class="mat-typography mat-app-background">
19
+ <ngx-root></ngx-root>
20
+ </body>
21
+ </html>
@@ -0,0 +1,16 @@
1
+ import { enableProdMode, provideZonelessChangeDetection } from "@angular/core";
2
+ import { bootstrapApplication } from "@angular/platform-browser";
3
+ import { provideAnimationsAsync } from "@angular/platform-browser/animations/async";
4
+ import { AppComponent } from "./app/app";
5
+ import { environment } from "./environments/environment";
6
+
7
+ if (environment.production) {
8
+ enableProdMode();
9
+ }
10
+
11
+ const bootstrap = () =>
12
+ bootstrapApplication(AppComponent, {
13
+ providers: [provideZonelessChangeDetection(), provideAnimationsAsync()],
14
+ });
15
+
16
+ bootstrap().catch((err) => console.error(err));
@@ -0,0 +1,32 @@
1
+ @use "@angular/material" as mat;
2
+
3
+ @include mat.elevation-classes();
4
+ @include mat.app-background();
5
+
6
+ $theme: mat.define-theme(
7
+ (
8
+ color: (
9
+ theme-type: light,
10
+ primary: mat.$violet-palette,
11
+ ),
12
+ typography: (
13
+ brand-family: "Roboto",
14
+ bold-weight: 900,
15
+ ),
16
+ density: (
17
+ scale: -1,
18
+ ),
19
+ )
20
+ );
21
+
22
+ html {
23
+ @include mat.all-component-themes($theme);
24
+
25
+ @include mat.elevation-classes();
26
+ @include mat.app-background();
27
+
28
+ // Somehow fix the menu not showing
29
+ .mat-mdc-menu-panel {
30
+ height: fit-content;
31
+ }
32
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../out-tsc/app",
5
+ "types": []
6
+ },
7
+ "files": ["src/main.ts"],
8
+ "include": ["src/**/*.d.ts"]
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../out-tsc/spec",
5
+ "types": ["jasmine", "node"]
6
+ },
7
+ "files": ["src/test.ts"],
8
+ "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
9
+ }
@@ -0,0 +1,3 @@
1
+ const baseConfig = require("../../eslint.config.js");
2
+
3
+ module.exports = [...baseConfig];
@@ -0,0 +1,31 @@
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
+ ],
14
+ client: {
15
+ clearContext: false, // leave Jasmine Spec Runner output visible in browser
16
+ },
17
+ coverageIstanbulReporter: {
18
+ dir: require("path").join(__dirname, "../../coverage/ngx-mat-input-tel"),
19
+ reports: ["html", "lcovonly"],
20
+ fixWebpackSourcePaths: true,
21
+ },
22
+ reporters: ["progress", "kjhtml"],
23
+ port: 9876,
24
+ colors: true,
25
+ logLevel: config.LOG_INFO,
26
+ autoWatch: true,
27
+ browsers: ["Chrome"],
28
+ singleRun: false,
29
+ restartOnFileChange: true,
30
+ });
31
+ };
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/ngx-mat-input-tel",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts",
6
+ "cssUrl": "inline"
7
+ }
8
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "ngx-mat-input-tel",
3
+ "version": "21.4.3",
4
+ "author": {
5
+ "name": "Raphaël Balet",
6
+ "email": "raphael.balet@outlook.com"
7
+ },
8
+ "maintainers": [
9
+ "raphael.balet@outlook.com"
10
+ ],
11
+ "peerDependencies": {
12
+ "@angular/common": ">=19.x",
13
+ "@angular/core": ">=19.x",
14
+ "@angular/forms": ">=19.x",
15
+ "@angular/platform-browser": ">=19.x",
16
+ "@angular/platform-browser-dynamic": ">=19.x",
17
+ "libphonenumber-js": "^1.12.31"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/rbalet/ngx-mat-input-tel"
22
+ },
23
+ "keywords": [
24
+ "angular",
25
+ "material",
26
+ "ngx-mat-intl-tel-input",
27
+ "intl-tel-input",
28
+ "ng-intl-tel-input",
29
+ "phone number",
30
+ "phone",
31
+ "validation",
32
+ "international",
33
+ "i18n",
34
+ "country",
35
+ "dial",
36
+ "code",
37
+ "telephone",
38
+ "mobile",
39
+ "input",
40
+ "flag"
41
+ ],
42
+ "license": "MIT",
43
+ "dependencies": {
44
+ "tslib": "^2.x"
45
+ }
46
+ }