ngxsmk-tel-input 0.0.5 → 0.0.8
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.
- package/README.md +102 -165
- package/fesm2022/ngxsmk-tel-input.mjs +385 -0
- package/fesm2022/ngxsmk-tel-input.mjs.map +1 -0
- package/{projects/ngxsmk-tel-input/dist/lib → lib}/ngxsmk-tel-input.component.d.ts +31 -16
- package/lib/ngxsmk-tel-input.service.d.ts +12 -0
- package/package.json +33 -68
- package/.editorconfig +0 -17
- package/.vscode/extensions.json +0 -4
- package/.vscode/launch.json +0 -20
- package/.vscode/tasks.json +0 -42
- package/angular.json +0 -40
- package/projects/ngxsmk-tel-input/README.md +0 -63
- package/projects/ngxsmk-tel-input/dist/README.md +0 -63
- package/projects/ngxsmk-tel-input/dist/fesm2022/ngxsmk-tel-input.mjs +0 -377
- package/projects/ngxsmk-tel-input/dist/fesm2022/ngxsmk-tel-input.mjs.map +0 -1
- package/projects/ngxsmk-tel-input/dist/lib/ngxsmk-tel-input.service.d.ts +0 -56
- package/projects/ngxsmk-tel-input/ng-package.json +0 -5
- package/projects/ngxsmk-tel-input/package.json +0 -22
- package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.component.spec.ts +0 -23
- package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.component.ts +0 -279
- package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.service.spec.ts +0 -16
- package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.service.ts +0 -116
- package/projects/ngxsmk-tel-input/src/public-api.ts +0 -6
- package/projects/ngxsmk-tel-input/tsconfig.lib.json +0 -13
- package/projects/ngxsmk-tel-input/tsconfig.lib.prod.json +0 -9
- package/projects/ngxsmk-tel-input/tsconfig.spec.json +0 -13
- package/tsconfig.json +0 -30
- package/{projects/ngxsmk-tel-input/dist/index.d.ts → index.d.ts} +0 -0
- package/{projects/ngxsmk-tel-input/dist/public-api.d.ts → public-api.d.ts} +1 -1
package/README.md
CHANGED
|
@@ -1,45 +1,37 @@
|
|
|
1
1
|
# ngxsmk-tel-input
|
|
2
2
|
|
|
3
|
-
An Angular **telephone input**
|
|
4
|
-
Wraps [`intl-tel-input`](https://github.com/jackocnr/intl-tel-input) for UI and uses [`libphonenumber-js`](https://github.com/catamphetamine/libphonenumber-js) for parsing & validation. Implements `ControlValueAccessor` so it plugs right into Angular Forms.
|
|
3
|
+
An Angular **telephone input** with country dropdown, flags, formatting and validation.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Features
|
|
11
|
-
|
|
12
|
-
* ✅ Country dropdown with flags
|
|
13
|
-
* ✅ E.164 output (configurable for national numbers)
|
|
14
|
-
* ✅ Works with Reactive/Template-driven Forms (`ControlValueAccessor`)
|
|
15
|
-
* ✅ Built-in validation (uses `libphonenumber-js`)
|
|
16
|
-
* ✅ SSR-friendly (lazy `intl-tel-input` import)
|
|
17
|
-
* ✅ Tiny API surface, easy to theme
|
|
5
|
+
* UI: [`intl-tel-input`](https://github.com/jackocnr/intl-tel-input)
|
|
6
|
+
* Parsing/validation: [`libphonenumber-js`](https://github.com/catamphetamine/libphonenumber-js)
|
|
7
|
+
* Forms: Implements **ControlValueAccessor** (Reactive & Template‑driven)
|
|
8
|
+
* Output: Emits **E.164** (e.g. `+14155550123`) when valid
|
|
18
9
|
|
|
19
10
|
---
|
|
20
11
|
|
|
21
12
|
## Requirements
|
|
22
13
|
|
|
23
|
-
* Angular **17
|
|
24
|
-
* Node **18
|
|
14
|
+
* Angular **17 – 19**
|
|
15
|
+
* Node **18** or **20**
|
|
16
|
+
|
|
17
|
+
> Peer deps: `@angular/* >=17 <20`
|
|
25
18
|
|
|
26
19
|
---
|
|
27
20
|
|
|
28
21
|
## Install
|
|
29
22
|
|
|
30
23
|
```bash
|
|
31
|
-
# your app
|
|
32
24
|
npm i ngxsmk-tel-input intl-tel-input libphonenumber-js
|
|
33
25
|
```
|
|
34
26
|
|
|
35
|
-
### Add styles &
|
|
27
|
+
### Add styles & flags (in your **app**, not the library)
|
|
36
28
|
|
|
37
|
-
`intl-tel-input`
|
|
29
|
+
Add `intl-tel-input` CSS and copy flag images via `angular.json`:
|
|
38
30
|
|
|
39
31
|
```jsonc
|
|
40
32
|
{
|
|
41
33
|
"projects": {
|
|
42
|
-
"your-app": {
|
|
34
|
+
"<your-app-name>": {
|
|
43
35
|
"architect": {
|
|
44
36
|
"build": {
|
|
45
37
|
"options": {
|
|
@@ -47,11 +39,7 @@ npm i ngxsmk-tel-input intl-tel-input libphonenumber-js
|
|
|
47
39
|
"node_modules/intl-tel-input/build/css/intlTelInput.css"
|
|
48
40
|
],
|
|
49
41
|
"assets": [
|
|
50
|
-
{
|
|
51
|
-
"glob": "**/*",
|
|
52
|
-
"input": "node_modules/intl-tel-input/build/img",
|
|
53
|
-
"output": "assets/intl-tel-input/img"
|
|
54
|
-
}
|
|
42
|
+
{ "glob": "**/*", "input": "node_modules/intl-tel-input/build/img", "output": "assets/intl-tel-input/img" }
|
|
55
43
|
]
|
|
56
44
|
}
|
|
57
45
|
}
|
|
@@ -61,34 +49,43 @@ npm i ngxsmk-tel-input intl-tel-input libphonenumber-js
|
|
|
61
49
|
}
|
|
62
50
|
```
|
|
63
51
|
|
|
64
|
-
|
|
52
|
+
Optional flag URL override (put in your app’s global styles):
|
|
53
|
+
|
|
54
|
+
```css
|
|
55
|
+
.iti__flag { background-image: url("/assets/intl-tel-input/img/flags.png"); }
|
|
56
|
+
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
|
57
|
+
.iti__flag { background-image: url("/assets/intl-tel-input/img/flags@2x.png"); }
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Restart the dev server after changes.
|
|
65
62
|
|
|
66
63
|
---
|
|
67
64
|
|
|
68
|
-
## Quick
|
|
65
|
+
## Quick Start (Reactive Forms)
|
|
69
66
|
|
|
70
67
|
```ts
|
|
71
68
|
// app.component.ts
|
|
72
69
|
import { Component } from '@angular/core';
|
|
73
70
|
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
74
|
-
import {
|
|
71
|
+
import { NgxsmkTelInputComponent } from 'ngxsmk-tel-input';
|
|
75
72
|
|
|
76
73
|
@Component({
|
|
77
74
|
selector: 'app-root',
|
|
78
75
|
standalone: true,
|
|
79
|
-
imports: [ReactiveFormsModule,
|
|
76
|
+
imports: [ReactiveFormsModule, NgxsmkTelInputComponent],
|
|
80
77
|
template: `
|
|
81
|
-
<form [formGroup]="fg"
|
|
82
|
-
<label for="phone">Phone</label>
|
|
78
|
+
<form [formGroup]="fg" style="max-width:420px;display:grid;gap:12px">
|
|
83
79
|
<ngxsmk-tel-input
|
|
84
|
-
id="phone"
|
|
85
80
|
formControlName="phone"
|
|
81
|
+
label="Phone"
|
|
82
|
+
hint="Include area code"
|
|
86
83
|
[initialCountry]="'US'"
|
|
87
84
|
[preferredCountries]="['US','GB','AU']"
|
|
88
85
|
(countryChange)="onCountry($event)">
|
|
89
86
|
</ngxsmk-tel-input>
|
|
90
87
|
|
|
91
|
-
<p *ngIf="fg.get('phone')?.hasError('phoneInvalid') && fg.get('phone')?.touched">
|
|
88
|
+
<p class="err" *ngIf="fg.get('phone')?.hasError('phoneInvalid') && fg.get('phone')?.touched">
|
|
92
89
|
Please enter a valid phone number.
|
|
93
90
|
</p>
|
|
94
91
|
|
|
@@ -97,26 +94,26 @@ import { TelInputComponent } from 'ngxsmk-tel-input';
|
|
|
97
94
|
`
|
|
98
95
|
})
|
|
99
96
|
export class AppComponent {
|
|
100
|
-
fg = this.fb.group({
|
|
101
|
-
|
|
102
|
-
});
|
|
103
|
-
constructor(private fb: FormBuilder) {}
|
|
104
|
-
onCountry(e: { iso2: any }) { console.log('Country changed:', e.iso2); }
|
|
97
|
+
fg = this.fb.group({ phone: ['', Validators.required] });
|
|
98
|
+
constructor(private readonly fb: FormBuilder) {}
|
|
99
|
+
onCountry(e: { iso2: string }) { console.log('country:', e.iso2); }
|
|
105
100
|
}
|
|
106
101
|
```
|
|
107
102
|
|
|
108
|
-
**
|
|
103
|
+
**Value semantics**
|
|
104
|
+
|
|
105
|
+
* Valid → control value is **E.164** string (e.g. `+14155550123`)
|
|
106
|
+
* Empty/invalid → value is **`null`**; validator sets `{ phoneInvalid: true }`
|
|
109
107
|
|
|
110
108
|
---
|
|
111
109
|
|
|
112
|
-
## Template
|
|
110
|
+
## Template‑driven
|
|
113
111
|
|
|
114
112
|
```html
|
|
115
113
|
<form #f="ngForm">
|
|
116
114
|
<ngxsmk-tel-input name="phone" [(ngModel)]="phone"></ngxsmk-tel-input>
|
|
117
115
|
</form>
|
|
118
|
-
|
|
119
|
-
<!-- phone is a string (E.164) or null -->
|
|
116
|
+
<!-- phone is an E.164 string or null -->
|
|
120
117
|
```
|
|
121
118
|
|
|
122
119
|
---
|
|
@@ -125,171 +122,111 @@ export class AppComponent {
|
|
|
125
122
|
|
|
126
123
|
### Inputs
|
|
127
124
|
|
|
128
|
-
| Name
|
|
129
|
-
|
|
|
130
|
-
| `initialCountry`
|
|
131
|
-
| `preferredCountries`
|
|
132
|
-
| `onlyCountries`
|
|
133
|
-
| `nationalMode`
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
|
|
138
|
-
|
|
125
|
+
| Name | Type | Default | Description |
|
|
126
|
+
| ---------------------- | -------------------------------------- | ---------------------- | ------------------------------------------------------------ |
|
|
127
|
+
| `initialCountry` | `CountryCode \| 'auto'` | `'US'` | Starting country (`'auto'` uses a stubbed US by default). |
|
|
128
|
+
| `preferredCountries` | `CountryCode[]` | `['US','GB']` | Pinned at the top. |
|
|
129
|
+
| `onlyCountries` | `CountryCode[]` | — | Limit selectable countries. |
|
|
130
|
+
| `nationalMode` | `boolean` | `false` | Display national format in the box; value still emits E.164. |
|
|
131
|
+
| `separateDialCode` | `boolean` | `false` | Show dial code separately. |
|
|
132
|
+
| `allowDropdown` | `boolean` | `true` | Enable/disable dropdown. |
|
|
133
|
+
| `placeholder` | `string` | `'Enter phone number'` | Native placeholder. |
|
|
134
|
+
| `autocomplete` | `string` | `'tel'` | Native autocomplete. |
|
|
135
|
+
| `disabled` | `boolean` | `false` | Disable input. |
|
|
136
|
+
| `label` | `string` | — | Label text. |
|
|
137
|
+
| `hint` | `string` | — | Helper text. |
|
|
138
|
+
| `errorText` | `string` | — | Custom error text. |
|
|
139
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Sizing preset. |
|
|
140
|
+
| `variant` | `'outline' \| 'filled' \| 'underline'` | `'outline'` | Visual style. |
|
|
141
|
+
| `showClear` | `boolean` | `true` | Show clear (×) button. |
|
|
142
|
+
| `autoFocus` | `boolean` | `false` | Focus on init. |
|
|
143
|
+
| `selectOnFocus` | `boolean` | `false` | Select all text on focus. |
|
|
144
|
+
| `formatOnBlur` | `boolean` | `true` | Pretty‑print on blur (national if `nationalMode`). |
|
|
145
|
+
| `showErrorWhenTouched` | `boolean` | `true` | Only show error style after blur. |
|
|
146
|
+
| `dropdownAttachToBody` | `boolean` | `true` | Append dropdown to `<body>` to avoid clipping. |
|
|
147
|
+
| `dropdownZIndex` | `number` | `2000` | Z‑index for dropdown panel. |
|
|
148
|
+
|
|
149
|
+
> `CountryCode` is the ISO‑2 code from `libphonenumber-js` (e.g., `US`, `GB`).
|
|
139
150
|
|
|
140
151
|
### Outputs
|
|
141
152
|
|
|
142
|
-
| Event
|
|
143
|
-
|
|
|
144
|
-
| `countryChange`
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
* **When valid:** emits **E.164** string (e.g., `+33123456789`) unless `nationalMode` is `true`.
|
|
149
|
-
* **When empty or invalid:** emits `null`.
|
|
150
|
-
* **Validation:** adds `phoneInvalid` error key when the input cannot be parsed as a valid number for the selected country.
|
|
153
|
+
| Event | Payload | Description |
|
|
154
|
+
| ---------------- | ---------------------------------------------------------- | ---------------------------------- |
|
|
155
|
+
| `countryChange` | `{ iso2: CountryCode }` | When the selected country changes. |
|
|
156
|
+
| `validityChange` | `boolean` | Emits when validity toggles. |
|
|
157
|
+
| `inputChange` | `{ raw: string; e164: string \| null; iso2: CountryCode }` | Emitted on each input. |
|
|
151
158
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
## Validation examples
|
|
155
|
-
|
|
156
|
-
```html
|
|
157
|
-
<ngxsmk-tel-input formControlName="phone"></ngxsmk-tel-input>
|
|
158
|
-
|
|
159
|
-
<div class="error" *ngIf="fg.get('phone')?.hasError('required')">
|
|
160
|
-
Phone is required
|
|
161
|
-
</div>
|
|
162
|
-
<div class="error" *ngIf="fg.get('phone')?.hasError('phoneInvalid')">
|
|
163
|
-
Please enter a valid phone number
|
|
164
|
-
</div>
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
---
|
|
168
|
-
|
|
169
|
-
## Accessibility
|
|
159
|
+
### Public methods
|
|
170
160
|
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* Consider additional ARIA attributes if you customize the template.
|
|
161
|
+
* `focus(): void`
|
|
162
|
+
* `selectCountry(iso2: CountryCode): void`
|
|
174
163
|
|
|
175
164
|
---
|
|
176
165
|
|
|
177
166
|
## Theming
|
|
178
167
|
|
|
179
|
-
The component
|
|
180
|
-
You can style it or the `intl-tel-input` container globally:
|
|
168
|
+
The component exposes CSS variables for easy theming. Example:
|
|
181
169
|
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
170
|
+
```html
|
|
171
|
+
<ngxsmk-tel-input style="
|
|
172
|
+
--tel-border:#cbd5e1;
|
|
173
|
+
--tel-ring:#22c55e;
|
|
174
|
+
--tel-radius:14px;
|
|
175
|
+
--tel-dd-item-hover: rgba(34,197,94,.12);
|
|
176
|
+
--tel-dd-z: 3000;
|
|
177
|
+
"></ngxsmk-tel-input>
|
|
191
178
|
```
|
|
192
179
|
|
|
193
|
-
|
|
180
|
+
Key tokens:
|
|
194
181
|
|
|
195
|
-
|
|
182
|
+
* Input: `--tel-bg`, `--tel-fg`, `--tel-border`, `--tel-border-hover`, `--tel-ring`, `--tel-placeholder`, `--tel-error`, `--tel-radius`, `--tel-focus-shadow`
|
|
183
|
+
* Dropdown: `--tel-dd-bg`, `--tel-dd-border`, `--tel-dd-shadow`, `--tel-dd-radius`, `--tel-dd-item-hover`, `--tel-dd-search-bg`, `--tel-dd-z`
|
|
196
184
|
|
|
197
|
-
|
|
198
|
-
No special setup required for Angular Universal. If you still see SSR errors, ensure you’re not referencing `window` in your own wrappers.
|
|
185
|
+
Dark mode: wrap in a `.dark` container – tokens adapt.
|
|
199
186
|
|
|
200
187
|
---
|
|
201
188
|
|
|
202
|
-
##
|
|
203
|
-
|
|
204
|
-
* **No flags / broken images**
|
|
205
|
-
Ensure `angular.json` asset mapping is present and that the output path matches your app’s `/assets` directory.
|
|
206
|
-
|
|
207
|
-
* **Styles not applied**
|
|
208
|
-
Add `"node_modules/intl-tel-input/build/css/intlTelInput.css"` to the `styles` array in `angular.json`.
|
|
189
|
+
## SSR
|
|
209
190
|
|
|
210
|
-
* **
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
* **Always invalid**
|
|
214
|
-
Some numbers are only valid with the correct country selected. Try typing with the `+` international prefix or set `initialCountry` appropriately.
|
|
191
|
+
* `intl-tel-input` is lazy‑loaded **only in the browser** using `isPlatformBrowser` guards.
|
|
192
|
+
* No direct `window`/`document` usage on the server path.
|
|
215
193
|
|
|
216
194
|
---
|
|
217
195
|
|
|
218
|
-
##
|
|
219
|
-
|
|
220
|
-
```html
|
|
221
|
-
<ngxsmk-tel-input formControlName="phone" [nationalMode]="true" [initialCountry]="'GB'"></ngxsmk-tel-input>
|
|
222
|
-
<!-- Value will be a national format string like '020 7946 0958' with validation tied to the selected country -->
|
|
223
|
-
```
|
|
196
|
+
## Troubleshooting
|
|
224
197
|
|
|
225
|
-
|
|
198
|
+
* **Unstyled UI / bullets** → Add CSS + assets in `angular.json`, restart dev server.
|
|
199
|
+
* **Flags missing** → Verify the images were copied to `/assets/intl-tel-input/img` or add the CSS override.
|
|
200
|
+
* **`TS2307: Cannot find module 'ngxsmk-tel-input'`** → Build the lib first; or add a `paths` alias to your app’s `tsconfig` if consuming locally.
|
|
201
|
+
* **Peer dependency conflict** → App Angular version must satisfy `>=17 <20`.
|
|
226
202
|
|
|
227
203
|
---
|
|
228
204
|
|
|
229
|
-
##
|
|
230
|
-
|
|
231
|
-
This repo is structured as an Angular workspace with a library:
|
|
205
|
+
## Local dev & publish
|
|
232
206
|
|
|
233
207
|
```bash
|
|
234
208
|
# Build the library
|
|
235
209
|
ng build ngxsmk-tel-input
|
|
236
210
|
|
|
237
|
-
#
|
|
238
|
-
|
|
239
|
-
#
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## Publish
|
|
211
|
+
# Test via tarball in another app
|
|
212
|
+
cd dist/ngxsmk-tel-input && npm pack
|
|
213
|
+
# in your app
|
|
214
|
+
npm i ../path-to/dist/ngxsmk-tel-input/ngxsmk-tel-input-<version>.tgz
|
|
245
215
|
|
|
246
|
-
|
|
247
|
-
#
|
|
216
|
+
# Publish (from the built dist folder)
|
|
217
|
+
# bump version in projects/ngxsmk-tel-input/package.json
|
|
248
218
|
ng build ngxsmk-tel-input
|
|
249
219
|
cd dist/ngxsmk-tel-input
|
|
250
220
|
npm publish --access public
|
|
251
221
|
```
|
|
252
222
|
|
|
253
|
-
> Ensure `peerDependencies` in the library’s `package.json` reflect your Angular support range.
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## Contributing
|
|
258
|
-
|
|
259
|
-
PRs welcome! Please:
|
|
260
|
-
|
|
261
|
-
1. Run `npm ci` and `ng build`.
|
|
262
|
-
2. Add/adjust unit or e2e tests if you change behavior.
|
|
263
|
-
3. Update this README for any API changes.
|
|
264
|
-
|
|
265
223
|
---
|
|
266
224
|
|
|
267
225
|
## License
|
|
268
226
|
|
|
269
227
|
[MIT](./LICENSE)
|
|
270
228
|
|
|
271
|
-
---
|
|
272
|
-
|
|
273
229
|
## Credits
|
|
274
230
|
|
|
275
|
-
* UI
|
|
276
|
-
* Parsing/validation
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
### Appendix: `angular.json` snippet (copy-paste)
|
|
281
|
-
|
|
282
|
-
```jsonc
|
|
283
|
-
{
|
|
284
|
-
"styles": [
|
|
285
|
-
"node_modules/intl-tel-input/build/css/intlTelInput.css"
|
|
286
|
-
],
|
|
287
|
-
"assets": [
|
|
288
|
-
{
|
|
289
|
-
"glob": "**/*",
|
|
290
|
-
"input": "node_modules/intl-tel-input/build/img",
|
|
291
|
-
"output": "assets/intl-tel-input/img"
|
|
292
|
-
}
|
|
293
|
-
]
|
|
294
|
-
}
|
|
295
|
-
```
|
|
231
|
+
* UI: `intl-tel-input`
|
|
232
|
+
* Parsing/validation: `libphonenumber-js`
|