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.
Files changed (29) hide show
  1. package/README.md +102 -165
  2. package/fesm2022/ngxsmk-tel-input.mjs +385 -0
  3. package/fesm2022/ngxsmk-tel-input.mjs.map +1 -0
  4. package/{projects/ngxsmk-tel-input/dist/lib → lib}/ngxsmk-tel-input.component.d.ts +31 -16
  5. package/lib/ngxsmk-tel-input.service.d.ts +12 -0
  6. package/package.json +33 -68
  7. package/.editorconfig +0 -17
  8. package/.vscode/extensions.json +0 -4
  9. package/.vscode/launch.json +0 -20
  10. package/.vscode/tasks.json +0 -42
  11. package/angular.json +0 -40
  12. package/projects/ngxsmk-tel-input/README.md +0 -63
  13. package/projects/ngxsmk-tel-input/dist/README.md +0 -63
  14. package/projects/ngxsmk-tel-input/dist/fesm2022/ngxsmk-tel-input.mjs +0 -377
  15. package/projects/ngxsmk-tel-input/dist/fesm2022/ngxsmk-tel-input.mjs.map +0 -1
  16. package/projects/ngxsmk-tel-input/dist/lib/ngxsmk-tel-input.service.d.ts +0 -56
  17. package/projects/ngxsmk-tel-input/ng-package.json +0 -5
  18. package/projects/ngxsmk-tel-input/package.json +0 -22
  19. package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.component.spec.ts +0 -23
  20. package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.component.ts +0 -279
  21. package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.service.spec.ts +0 -16
  22. package/projects/ngxsmk-tel-input/src/lib/ngxsmk-tel-input.service.ts +0 -116
  23. package/projects/ngxsmk-tel-input/src/public-api.ts +0 -6
  24. package/projects/ngxsmk-tel-input/tsconfig.lib.json +0 -13
  25. package/projects/ngxsmk-tel-input/tsconfig.lib.prod.json +0 -9
  26. package/projects/ngxsmk-tel-input/tsconfig.spec.json +0 -13
  27. package/tsconfig.json +0 -30
  28. package/{projects/ngxsmk-tel-input/dist/index.d.ts → index.d.ts} +0 -0
  29. 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** component with country dropdown, flag icons, and robust validation/formatting.
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
- > Emits E.164 numbers by default (e.g., `+14155550123`). SSR-safe via lazy imports.
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+** / **20+**
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 & assets
27
+ ### Add styles & flags (in your **app**, not the library)
36
28
 
37
- `intl-tel-input` ships its own CSS and flag images. Add them to your app’s `angular.json`:
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
- > If you use a custom builder, copy the flags folder to `/assets/intl-tel-input/img`.
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 start (Reactive Forms)
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 { TelInputComponent } from 'ngxsmk-tel-input';
71
+ import { NgxsmkTelInputComponent } from 'ngxsmk-tel-input';
75
72
 
76
73
  @Component({
77
74
  selector: 'app-root',
78
75
  standalone: true,
79
- imports: [ReactiveFormsModule, TelInputComponent],
76
+ imports: [ReactiveFormsModule, NgxsmkTelInputComponent],
80
77
  template: `
81
- <form [formGroup]="fg" class="space-y-3">
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
- phone: ['', Validators.required] // control value will be E.164 string or null
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
- **Result:** `form.get('phone')?.value` → `'+14155550123'` (E.164) when valid, or `null` while empty/invalid.
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-driven usage
110
+ ## Templatedriven
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 | Type | Default | Description |
129
- | -------------------- | ----------------------- | ---------------------- | --------------------------------------------------- |
130
- | `initialCountry` | `CountryCode \| 'auto'` | `'auto'` | Starting country. `'auto'` uses the plugin default. |
131
- | `preferredCountries` | `CountryCode[]` | `['US','GB']` | Pinned countries at the top. |
132
- | `onlyCountries` | `CountryCode[]` | `undefined` | Restrict selectable countries. |
133
- | `nationalMode` | `boolean` | `false` | If `true`, emits national numbers; otherwise E.164. |
134
- | `placeholder` | `string` | `'Enter phone number'` | Input placeholder. |
135
- | `autocomplete` | `string` | `'tel'` | Native autocomplete attribute. |
136
- | `disabled` | `boolean` | `false` | Disables the input. |
137
-
138
- > `CountryCode` is the ISO-2 uppercase code from `libphonenumber-js` (e.g., `US`, `GB`, `AU`).
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 | Payload | Description |
143
- | --------------- | ----------------------- | ---------------------------------------- |
144
- | `countryChange` | `{ iso2: CountryCode }` | Fires when the selected country changes. |
145
-
146
- ### Value semantics
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
- * Pair with a `<label for="phone">` or wrap the input and label together.
172
- * The country dropdown is keyboard navigable (via `intl-tel-input`).
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 applies a minimal class to the input: `.ngxsmk-tel-input`.
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
- ```css
183
- .ngxsmk-tel-input {
184
- width: 100%;
185
- padding: 0.5rem 0.75rem;
186
- }
187
-
188
- .iti {
189
- width: 100%; /* make dropdown stretch */
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
- ## SSR notes
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
- This library lazily imports `intl-tel-input` **only in the browser**.
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
- ## Troubleshooting
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
- * **Form value doesn’t update**
211
- Use Angular Forms APIs (Reactive or Template-driven). For Reactive Forms, confirm the control is bound via `formControlName` and that `ReactiveFormsModule` is imported.
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
- ## Example: national mode
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
- > When using `nationalMode=true`, you’ll typically store the country code alongside the value, using `(countryChange)`.
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
- ## Development
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
- # (Optional) create a demo app and try it locally
238
- ng g application demo
239
- # import TelInputComponent in your demo app and test
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
- ```bash
247
- # Bump version, then:
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 powered by [`intl-tel-input`](https://github.com/jackocnr/intl-tel-input)
276
- * Parsing/validation by [`libphonenumber-js`](https://github.com/catamphetamine/libphonenumber-js)
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`