ngx-dial-input 2.0.0 → 2.0.1

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 (39) hide show
  1. package/README.md +9 -12
  2. package/data/countries.d.ts +2 -0
  3. package/data/countries.model.d.ts +9 -0
  4. package/esm2020/data/countries.mjs +1218 -0
  5. package/esm2020/data/countries.model.mjs +2 -0
  6. package/esm2020/lib/phone-input.component.mjs +292 -0
  7. package/esm2020/lib/phone-input.module.mjs +24 -0
  8. package/esm2020/ngx-dial-input.mjs +5 -0
  9. package/esm2020/public-api.mjs +6 -0
  10. package/fesm2015/ngx-dial-input.mjs +1542 -0
  11. package/fesm2015/ngx-dial-input.mjs.map +1 -0
  12. package/fesm2020/ngx-dial-input.mjs +1541 -0
  13. package/fesm2020/ngx-dial-input.mjs.map +1 -0
  14. package/index.d.ts +5 -0
  15. package/lib/phone-input.component.d.ts +37 -0
  16. package/lib/phone-input.module.d.ts +9 -0
  17. package/ngx-dial-input-2.0.1.tgz +0 -0
  18. package/package.json +32 -49
  19. package/{projects/phone-input/src/public-api.ts → public-api.d.ts} +0 -3
  20. package/.editorconfig +0 -16
  21. package/.vscode/extensions.json +0 -4
  22. package/.vscode/launch.json +0 -20
  23. package/.vscode/tasks.json +0 -42
  24. package/angular.json +0 -41
  25. package/country-phone-input-0.0.0.tgz +0 -0
  26. package/projects/phone-input/README.md +0 -24
  27. package/projects/phone-input/ng-package.json +0 -7
  28. package/projects/phone-input/package.json +0 -12
  29. package/projects/phone-input/src/data/countries.model.ts +0 -9
  30. package/projects/phone-input/src/data/countries.ts +0 -1219
  31. package/projects/phone-input/src/lib/phone-input.component.css +0 -0
  32. package/projects/phone-input/src/lib/phone-input.component.html +0 -0
  33. package/projects/phone-input/src/lib/phone-input.component.ts +0 -338
  34. package/projects/phone-input/src/lib/phone-input.module.ts +0 -15
  35. package/projects/phone-input/src/lib/phone-input.service.spec.ts +0 -16
  36. package/projects/phone-input/tsconfig.lib.json +0 -15
  37. package/projects/phone-input/tsconfig.lib.prod.json +0 -10
  38. package/projects/phone-input/tsconfig.spec.json +0 -14
  39. package/tsconfig.json +0 -33
@@ -1,338 +0,0 @@
1
- import {
2
- Component,
3
- Input,
4
- Output,
5
- EventEmitter,
6
- ElementRef,
7
- HostListener,
8
- forwardRef
9
- } from '@angular/core';
10
- import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
11
- import { countries } from '../data/countries';
12
- import {
13
- trigger,
14
- state,
15
- style,
16
- transition,
17
- animate
18
- } from '@angular/animations';
19
-
20
-
21
-
22
- @Component({
23
- selector: 'phone-input',
24
- animations: [
25
- trigger('dropdownAnimation', [
26
- state('open', style({
27
- opacity: 1,
28
- transform: 'scaleY(1)',
29
- height: '*',
30
- padding: '*'
31
- })),
32
- state('closed', style({
33
- opacity: 0,
34
- transform: 'scaleY(0)',
35
- height: '0px',
36
- padding: '0px'
37
- })),
38
- transition('closed => open', [
39
- animate('200ms ease-out')
40
- ]),
41
- transition('open => closed', [
42
- animate('150ms ease-in')
43
- ])
44
- ])
45
- ],
46
- template: `<div class="phone-input-wrapper">
47
- <div class="input-container">
48
- <!-- Country Selector (20%) -->
49
- <div class="country-select" (click)="toggleDropdown()" (blur)="toggleDropdown()">
50
- <img [src]="selectedCountry.flag" width="20" />
51
- <span>{{selectedCountry.dialCode}}</span>
52
- <span class="arrow-down">▾</span>
53
- </div>
54
-
55
- <!-- Phone Input (80%) -->
56
- <input
57
- type="tel"
58
- pattern="[0-9]*"
59
- inputmode="numeric"
60
- class="phone-input"
61
- [placeholder]="placeholder"
62
- [(ngModel)]="phoneNumber"
63
- [ngClass]="{ 'error-border': isInvalid }"
64
- (input)="onPhoneInput()"
65
- (keypress)="allowOnlyNumbers($event)"
66
- />
67
- </div>
68
-
69
- <!-- Dropdown Content (full width below) -->
70
- <div
71
- class="dropdown-content"
72
- [@dropdownAnimation]="dropdownOpen ? 'open' : 'closed'"
73
- *ngIf="dropdownOpen || animating"
74
- (@dropdownAnimation.done)="onAnimationDone($event)" >
75
- <input
76
- *ngIf="searchEnabled"
77
- type="text"
78
- class="search-box"
79
- placeholder="Search Country"
80
- [(ngModel)]="searchTerm"
81
- (input)="onSearchChange()"
82
- />
83
- <div class="country-list">
84
- <div
85
- class="country-option"
86
- *ngFor="let country of countriesList"
87
- (click)="selectCountry(country)"
88
- >
89
- <img [src]="country.flag" width="20" />
90
- <span class="country-name">{{ country.name }} ({{ country.native }})</span>
91
- <span class="dial-code">{{ country.dialCode }}</span>
92
- </div>
93
- </div>
94
- </div>
95
- </div>
96
-
97
- `,
98
- styles: [`
99
- .phone-input-wrapper {
100
- position: relative;
101
- font-family: Arial, sans-serif;
102
- }
103
-
104
- .input-container {
105
- display: flex;
106
- width: 100%;
107
- padding-bottom: 3px;
108
- }
109
-
110
- /* Country Select (20%) */
111
- .country-select {
112
- width: 24%;
113
- display: flex;
114
- align-items: center;
115
- justify-content: space-between;
116
- border: 1px solid #ccc;
117
- border-right: none;
118
- border-radius: 4px 0 0 4px;
119
- padding: 8px 8px;
120
- cursor: pointer;
121
- background-color: #f8f8f8;
122
- }
123
-
124
- .country-select img {
125
- margin-right: 5px;
126
- }
127
-
128
- .arrow-down {
129
- font-size: 13px;
130
- color: #666;
131
- }
132
- .arrow-down:after {
133
- display: none;
134
- }
135
- /* Phone Input (80%) */
136
- .phone-input {
137
- width: 80%;
138
- padding: 8px 12px;
139
- border: 1px solid #ccc;
140
- border-radius: 0 4px 4px 0;
141
- outline: none;
142
- }
143
-
144
- /* Dropdown Content */
145
- .dropdown-content {
146
- position: absolute;
147
- top: 100%;
148
- left: 0;
149
- width: 100%;
150
- background: white;
151
- border: 1px solid #ccc;
152
- border-radius: 0 0 4px 4px;
153
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
154
- z-index: 1000;
155
- margin-top: -1px;
156
- }
157
-
158
- .search-box {
159
- width: 100%;
160
- padding: 8px 12px;
161
- border: none;
162
- border-bottom: 1px solid #eee;
163
- outline: none;
164
- }
165
-
166
- .country-list {
167
- max-height: 200px;
168
- overflow-y: auto;
169
- }
170
-
171
- .country-option {
172
- display: flex;
173
- align-items: center;
174
- padding: 8px 12px;
175
- cursor: pointer;
176
- }
177
-
178
- .country-option:hover {
179
- background-color: #f5f5f5;
180
- }
181
-
182
- .country-option img {
183
- margin-right: 5px;
184
- }
185
-
186
- .country-name {
187
- flex-grow: 1;
188
- }
189
-
190
- .dial-code {
191
- color: #666;
192
- font-size: 0.9em;
193
- }
194
-
195
- /* Error State */
196
- input.error-border {
197
- border-color: red;
198
- }
199
-
200
- `],
201
- providers: [{
202
- provide: NG_VALUE_ACCESSOR,
203
- useExisting: forwardRef(() => PhoneInputComponent),
204
- multi: true
205
- }]
206
- })
207
- export class PhoneInputComponent implements ControlValueAccessor {
208
- countriesList = countries;
209
- searchTerm = '';
210
- @Input() defaultCountry: string = '';
211
- @Input() placeholder: string = '';
212
- @Input() searchEnabled: boolean = true;
213
- @Input() numberFormat: 'international' | 'national' = 'international';
214
- @Input() setFirstCountry: string = '';
215
- @Output() phoneChange = new EventEmitter<any>();
216
-
217
- phoneNumber: string = '';
218
- isInvalid: boolean = false;
219
- dropdownOpen: boolean = false;
220
- animating: boolean = false;
221
-
222
- selectedCountry = countries[0];
223
-
224
- constructor(private eRef: ElementRef) {}
225
-
226
- private onChange: any = () => {};
227
- private onTouched: any = () => {};
228
-
229
-
230
- ngOnInit() {
231
- if (this.defaultCountry) {
232
- const match = countries.find(c => c.iso2 === this.defaultCountry.toLowerCase());
233
- if (match) this.selectedCountry = match;
234
- }
235
- }
236
- @HostListener('document:click', ['$event'])
237
- handleClickOutside(event: MouseEvent) {
238
- if (!this.eRef.nativeElement.contains(event.target)) {
239
- this.dropdownOpen = false;
240
- }
241
- }
242
-
243
- onAnimationDone(event: any) {
244
- if (!this.dropdownOpen) {
245
- this.animating = false;
246
- }
247
- }
248
-
249
- toggleDropdown() {
250
- this.dropdownOpen = !this.dropdownOpen;
251
- this.animating = true;
252
- }
253
-
254
- onClickOutside(event: MouseEvent) {
255
- if (!this.eRef.nativeElement.contains(event.target)) {
256
- this.dropdownOpen = false;
257
- }
258
- }
259
-
260
- onSearchChange() {
261
- const term = this.searchTerm.toLowerCase();
262
- this.countriesList = countries.filter(c =>
263
- c.name.toLowerCase().includes(term)
264
- );
265
- }
266
-
267
- selectCountry(country: any) {
268
- this.selectedCountry = country;
269
- this.searchTerm = '';
270
- this.countriesList = countries;
271
- this.dropdownOpen = false;
272
- this.emitPhoneChange();
273
- }
274
-
275
- onPhoneInput() {
276
- this.emitPhoneChange();
277
- }
278
-
279
- private emitPhoneChange() {
280
- const digitsOnly = this.phoneNumber.replace(/\D/g, '');
281
- const length = digitsOnly.length;
282
-
283
- const expectedLength = this.selectedCountry?.phoneLength;
284
-
285
- if (expectedLength) {
286
- this.isInvalid = length !== expectedLength;
287
- } else {
288
- // fallback validation
289
- this.isInvalid = length < 7 || length > 12;
290
- }
291
-
292
- const fullPhone = this.selectedCountry.dialCode + this.phoneNumber;
293
-
294
- const structuredValue = {
295
- e164Number: fullPhone,
296
- nationalNumber: this.phoneNumber,
297
- dialCode: this.selectedCountry.dialCode,
298
- countryCode: this.selectedCountry.iso2,
299
- isValid: !this.isInvalid,
300
- };
301
-
302
- this.onChange(structuredValue);
303
- this.phoneChange.emit(structuredValue);
304
- }
305
-
306
- writeValue(value: any): void {
307
- if (value && value.dialCode && value.countryCode) {
308
- const match = countries.find(c =>
309
- c.dialCode === value.dialCode && c.iso2 === value.countryCode
310
- );
311
- if (match) {
312
- this.selectedCountry = match;
313
- } else {
314
- this.selectedCountry = countries[0];
315
- }
316
- this.phoneNumber = value.nationalNumber || '';
317
- } else {
318
- this.selectedCountry = countries[0];
319
- this.phoneNumber = '';
320
- }
321
- }
322
- registerOnChange(fn: any): void {
323
- this.onChange = fn;
324
- }
325
-
326
- registerOnTouched(fn: any): void {
327
- this.onTouched = fn;
328
- }
329
- allowOnlyNumbers(event: KeyboardEvent) {
330
- const charCode = event.charCode;
331
-
332
- // Allow only digits (0–9)
333
- if (charCode < 48 || charCode > 57) {
334
- event.preventDefault();
335
- }
336
- }
337
-
338
- }
@@ -1,15 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { PhoneInputComponent } from './phone-input.component';
4
- import { FormsModule } from '@angular/forms';
5
-
6
- @NgModule({
7
- declarations: [PhoneInputComponent],
8
- imports: [
9
- CommonModule,
10
- FormsModule
11
- ],
12
- exports: [PhoneInputComponent]
13
- })
14
- export class PhoneInputModule { }
15
-
@@ -1,16 +0,0 @@
1
- import { TestBed } from '@angular/core/testing';
2
-
3
- import { PhoneInputService } from './phone-input.service';
4
-
5
- describe('PhoneInputService', () => {
6
- let service: PhoneInputService;
7
-
8
- beforeEach(() => {
9
- TestBed.configureTestingModule({});
10
- service = TestBed.inject(PhoneInputService);
11
- });
12
-
13
- it('should be created', () => {
14
- expect(service).toBeTruthy();
15
- });
16
- });
@@ -1,15 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../out-tsc/lib",
5
- "rootDir": "src",
6
- "declaration": true,
7
- "declarationMap": true,
8
- "inlineSources": true,
9
- "types": [],
10
- "composite": false
11
- },
12
- "exclude": [
13
- "**/*.spec.ts"
14
- ]
15
- }
@@ -1,10 +0,0 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
- {
3
- "extends": "./tsconfig.lib.json",
4
- "compilerOptions": {
5
- "declarationMap": false
6
- },
7
- "angularCompilerOptions": {
8
- "compilationMode": "partial"
9
- }
10
- }
@@ -1,14 +0,0 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
- {
3
- "extends": "../../tsconfig.json",
4
- "compilerOptions": {
5
- "outDir": "../../out-tsc/spec",
6
- "types": [
7
- "jasmine"
8
- ]
9
- },
10
- "include": [
11
- "**/*.spec.ts",
12
- "**/*.d.ts"
13
- ]
14
- }
package/tsconfig.json DELETED
@@ -1,33 +0,0 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
- {
3
- "compileOnSave": false,
4
- "compilerOptions": {
5
- "baseUrl": "./",
6
- "outDir": "./dist/out-tsc",
7
- "forceConsistentCasingInFileNames": true,
8
- "strict": true,
9
- "noImplicitOverride": true,
10
- "noPropertyAccessFromIndexSignature": true,
11
- "noImplicitReturns": true,
12
- "noFallthroughCasesInSwitch": true,
13
- "skipLibCheck": true,
14
- "esModuleInterop": true,
15
- "sourceMap": true,
16
- "declaration": false,
17
- "experimentalDecorators": true,
18
- "moduleResolution": "node",
19
- "importHelpers": true,
20
- "module": "es2020",
21
- "target": "es2015",
22
- "useDefineForClassFields": false,
23
- "lib": ["es2020", "dom"]
24
- },
25
- "angularCompilerOptions": {
26
- "enableI18nLegacyMessageIdFormat": false,
27
- "strictInjectionParameters": true,
28
- "strictInputAccessModifiers": true,
29
- "strictTemplates": true,
30
- "compilationMode": "partial"
31
-
32
- }
33
- }