svelte-tel-input 1.3.2 → 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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # svelte-tel-input
2
2
 
3
+ ## 2.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: component export ([#147](https://github.com/gyurielf/svelte-tel-input/pull/147))
8
+
9
+ ## 2.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - breaking: switch from default to named export to export TelInput component. Use named import in the future. From now Svelte >= 3.58.0 is required. ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
14
+
15
+ ### Minor Changes
16
+
17
+ - feat: space config option added, it will enable or disable spaces in the input field. ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
18
+
19
+ - feat: autoPlaceholder feature added, it generates placeholder for each country. ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
20
+
21
+ ### Patch Changes
22
+
23
+ - chore: update deps, re-generate package-lock.json ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
24
+
25
+ - feat: added options panel to example page to be able to try out config opts. ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
26
+
3
27
  ## 1.3.2
4
28
 
5
29
  ### Patch Changes
package/README.md CHANGED
@@ -6,14 +6,9 @@
6
6
 
7
7
  > Lightweight svelte tel/phone input standardizer.
8
8
 
9
- The package is recently bumped to `1.0`. If you experience any problems, please open an issue, to be able to me to fix it.
9
+ <img src="https://raw.githubusercontent.com/gyurielf/svelte-tel-input/main/static/demo.gif" width="600px" align="center">
10
10
 
11
- ## Goals
12
-
13
- - Solve the problem that a users can enter the same phone number in different formats.
14
- - Storing a phone number in a standard format, that can be indexable and searchable in any database.
15
- - Should be accessible for the the browser. Eg. for a `<a href="tel+36201234567 />`.
16
- - The stored phone number format can be useable for any SMS gateway(e.g for 2FA) and if somebody can call the number from anywhere, it should work.
11
+ 🔥 Check it out live [here](https://svelte-tel-input.vercel.app/)
17
12
 
18
13
  ## Installation
19
14
 
@@ -27,9 +22,9 @@ npm install --save svelte-tel-input
27
22
 
28
23
  - Parse and validate phone number.You can store one exact format (`E164`), no matter how users type their phone numbers.
29
24
  - Format (specified to its country), to make it more readable.
30
- - Optionally it can set the user's current country automatically, via IP lookup.
31
- - Prevent non-digits typing into the input, except the `+` sign (and `space` optionally).
32
- - Handle copy-pasted phone numbers, it's sanitize non-digit characters except the `+` sign (and `space` optionally).
25
+ - Prevent non-digits typing into the input, except the leading `+` sign (and `space` optionally).
26
+ - Handle copy-pasted phone numbers, it's sanitize non-digit characters except the leading `+` sign (and `space` optionally).
27
+ - Automatic placeholder generation for the selected country.
33
28
 
34
29
  ## Usage
35
30
 
@@ -39,7 +34,7 @@ npm install --save svelte-tel-input
39
34
 
40
35
  ```html
41
36
  <script lang="ts">
42
- import TelInput, { normalizedCountries } from 'svelte-tel-input';
37
+ import { TelInput, normalizedCountries } from 'svelte-tel-input';
43
38
  import type { NormalizedTelNumber, CountryCode, E164Number } from 'svelte-tel-input/types';
44
39
 
45
40
  // Any Country Code Alpha-2 (ISO 3166)
@@ -107,17 +102,26 @@ npm install --save svelte-tel-input
107
102
 
108
103
  The default export of the library is the main TelInput component. It has the following props:
109
104
 
110
- | Props | Type | Default Value | Usage |
111
- | -------------- | --------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
112
- | country | `CountryCode \| null` | `null` | It's accept any Country Code Alpha-2 (ISO 3166). You can set manually (e.g: by the user via a select). The parser will inspect the entered phone number and if it detect a valid country calling code, then it's automatically set the country to according to the detected country calling code. E.g: `+36` -> `HU` |
113
- | disabled | `boolean` | `false` | It's block the parser and prevent entering input. You must handle its styling on your own. |
114
- | valid | `boolean` | `true` | Indicates whether the entered tel number validity. |
115
- | value | `E164Number \| null` | `null` | [E164](https://en.wikipedia.org/wiki/E.164) is the international format of phone.numbers. This is the main entry point to store and/or load an existent phone number. |
116
- | parsedTelInput | `NormalizedTelInput \|null` | `null` | All of the formatted results of the tel input. |
117
- | class | `string` | `` | You can pass down any classname to the component |
105
+ | Props | Type | Default Value | Usage |
106
+ | --------------- | --------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107
+ | country | `CountryCode \| null` | `null` | It's accept any Country Code Alpha-2 (ISO 3166). You can set manually (e.g: by the user via a select). The parser will inspect the entered phone number and if it detect a valid country calling code, then it's automatically set the country to according to the detected country calling code. E.g: `+36` -> `HU` |
108
+ | disabled | `boolean` | `false` | It's block the parser and prevent entering input. You must handle its styling on your own. |
109
+ | valid | `boolean` | `true` | Indicates whether the entered tel number validity. |
110
+ | value | `E164Number \| null` | `null` | [E164](https://en.wikipedia.org/wiki/E.164) is the international format of phone.numbers. This is the main entry point to store and/or load an existent phone number. |
111
+ | parsedTelInput | `NormalizedTelInput \|null` | `null` | All of the formatted results of the tel input. |
112
+ | class | `string` | `` | You can pass down any classname to the component |
113
+ | autoPlaceholder | `boolean` | `true` | Generates country specific placeholder for the selected country.something |
114
+ | allowSpaces | `boolean` | `true` | Allow or disallow spaces in the input field |
118
115
 
119
116
  <p align="right">(<a href="#readme-top">back to top</a>)</p>
120
117
 
118
+ ## Goals
119
+
120
+ - Solve the problem that a users can enter the same phone number in different formats.
121
+ - Storing a phone number in a standard format, that can be indexable and searchable in any database.
122
+ - Should be accessible for the the browser. Eg. for a `<a href="tel+36201234567 />`.
123
+ - The stored phone number format can be useable for any SMS gateway(e.g for 2FA) and if somebody can call the number from anywhere, it should work.
124
+
121
125
  ## Dependencies
122
126
 
123
127
  [svelte](https://svelte.dev/)
@@ -141,7 +145,8 @@ The default export of the library is the main TelInput component. It has the fol
141
145
  - [x] Integrate libphonenumber
142
146
  - [x] Implement parser
143
147
  - [x] Add basics docs and examples
144
- - [ ] Add advanced examples
148
+ - [x] Add advanced examples
149
+ - [x] Generate placeholders autimatically
145
150
  - [ ] Improve A11Y
146
151
 
147
152
  See the [open issues](https://github.com/gyurielf/svelte-tel-input/issues) for a list of proposed features (and known issues).
@@ -119,7 +119,7 @@ const onChange = (selectedCountry) => {
119
119
  <button
120
120
  value={country.iso2}
121
121
  type="button"
122
- class="inline-flex py-2 px-4 w-full text-sm hover:bg-gray-100 dark:hover:bg-gray-600
122
+ class="inline-flex py-2 px-4 w-full text-sm hover:bg-gray-100 dark:hover:bg-gray-600
123
123
  active:bg-gray-800 dark:active:bg-gray-800 overflow-hidden
124
124
  {isActive
125
125
  ? 'bg-gray-600 dark:text-white'
@@ -1,16 +1,32 @@
1
1
  <script>import { createEventDispatcher, onMount } from "svelte";
2
2
  import { parsePhoneNumberWithError, ParseError } from "libphonenumber-js/max";
3
3
  import { telInputAction } from "../../utils/directives/telInputAction";
4
- import { normalizeTelInput, getCountryForPartialE164Number } from "../../utils/helpers";
4
+ import {
5
+ normalizeTelInput,
6
+ getCountryForPartialE164Number,
7
+ generatePlaceholder
8
+ } from "../../utils/helpers";
5
9
  import { watcher } from "../../stores";
10
+ const defaultOptions = {
11
+ autoPlaceholder: true,
12
+ spaces: true
13
+ };
6
14
  const dispatch = createEventDispatcher();
7
15
  export let country;
8
16
  export let value;
9
17
  export let parsedTelInput = null;
10
18
  export let valid = true;
11
19
  export let disabled = false;
20
+ export let placeholder = null;
21
+ export let options = defaultOptions;
22
+ export let required = null;
12
23
  let inputValue = value;
13
24
  let prevCountry = country;
25
+ $:
26
+ combinedOptions = {
27
+ ...defaultOptions,
28
+ ...options
29
+ };
14
30
  const handleInputAction = (value2) => {
15
31
  if (disabled)
16
32
  return;
@@ -42,11 +58,16 @@ const handleParsePhoneNumber = (input, currCountry = null) => {
42
58
  throw err;
43
59
  }
44
60
  }
45
- if (parsedTelInput?.isValid && parsedTelInput?.formatOriginal) {
61
+ if (parsedTelInput?.isValid && combinedOptions.spaces && parsedTelInput?.formatOriginal) {
46
62
  if (inputValue === parsedTelInput?.formatOriginal) {
47
63
  inputValue = null;
48
64
  }
49
65
  inputValue = parsedTelInput?.formatOriginal;
66
+ } else if (parsedTelInput?.isValid && parsedTelInput?.nationalNumber) {
67
+ if (inputValue === parsedTelInput?.nationalNumber) {
68
+ inputValue = null;
69
+ }
70
+ inputValue = parsedTelInput?.nationalNumber;
50
71
  }
51
72
  value = parsedTelInput?.e164 ?? null;
52
73
  valid = parsedTelInput?.isValid ?? false;
@@ -90,9 +111,13 @@ const watchFunction = () => {
90
111
  const countryChangeWatch = watcher(null, watchFunction);
91
112
  $:
92
113
  $countryChangeWatch = country;
114
+ $:
115
+ getPlaceholder = combinedOptions.autoPlaceholder ? country ? generatePlaceholder(country) : null : placeholder;
93
116
  </script>
94
117
 
95
118
  <input
119
+ {required}
120
+ placeholder={getPlaceholder}
96
121
  {disabled}
97
122
  type="tel"
98
123
  value={inputValue}
@@ -107,5 +132,5 @@ $:
107
132
  on:keypress
108
133
  on:keyup
109
134
  on:paste
110
- use:telInputAction={handleInputAction}
135
+ use:telInputAction={{ handler: handleInputAction, spaces: combinedOptions.spaces }}
111
136
  />
@@ -1,5 +1,5 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import type { NormalizedTelNumber, CountryCode, E164Number } from '../../types';
2
+ import type { NormalizedTelNumber, CountryCode, E164Number, TelInputOptions } from '../../types';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  [x: string]: any;
@@ -8,6 +8,9 @@ declare const __propDef: {
8
8
  parsedTelInput?: Partial<NormalizedTelNumber> | null | undefined;
9
9
  valid?: boolean | undefined;
10
10
  disabled?: boolean | undefined;
11
+ placeholder?: string | null | undefined;
12
+ options?: TelInputOptions | undefined;
13
+ required?: boolean | null | undefined;
11
14
  };
12
15
  events: {
13
16
  beforeinput: InputEvent;
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { default } from './components/Input/TelInput.svelte';
1
+ export { default as TelInput } from './components/Input/TelInput.svelte';
2
2
  export { getCurrentCountry, isSelected, inputParser, inspectAllowedChars, normalizeTelInput, getCountryForPartialE164Number } from './utils/helpers';
3
3
  export { parsePhoneNumberWithError, ParseError } from 'libphonenumber-js/max';
4
4
  export { clickOutsideAction } from './utils/directives/clickOutsideAction';
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { default } from './components/Input/TelInput.svelte';
1
+ export { default as TelInput } from './components/Input/TelInput.svelte';
2
2
  export { getCurrentCountry, isSelected, inputParser, inspectAllowedChars, normalizeTelInput, getCountryForPartialE164Number } from './utils/helpers';
3
3
  export { parsePhoneNumberWithError, ParseError } from 'libphonenumber-js/max';
4
4
  export { clickOutsideAction } from './utils/directives/clickOutsideAction';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "svelte-tel-input",
3
3
  "description": "svelte-tel-input",
4
- "version": "1.3.2",
4
+ "version": "2.0.1",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/gyurielf/svelte-tel-input.git"
@@ -16,49 +16,49 @@
16
16
  "intl tel input"
17
17
  ],
18
18
  "engines": {
19
- "npm": ">= 7",
19
+ "npm": ">= 8",
20
20
  "yarn": ">=2",
21
21
  "node": ">= 16",
22
22
  "pnpm": ">= 7"
23
23
  },
24
24
  "dependencies": {
25
- "libphonenumber-js": "^1.10.21",
26
- "svelte": "^3.55.1"
25
+ "libphonenumber-js": "^1.10.28",
26
+ "svelte": "^3.58.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@changesets/cli": "^2.26.0",
29
+ "@changesets/cli": "^2.26.1",
30
30
  "@changesets/get-github-info": "^0.5.2",
31
31
  "@changesets/types": "^5.2.1",
32
32
  "@macfja/svelte-persistent-store": "^2.2.1",
33
- "@playwright/test": "^1.31.2",
34
- "@sveltejs/adapter-static": "^2.0.1",
35
- "@sveltejs/kit": "^1.11.0",
33
+ "@playwright/test": "^1.32.3",
34
+ "@sveltejs/adapter-static": "^2.0.2",
35
+ "@sveltejs/kit": "^1.15.7",
36
36
  "@sveltejs/package": "^1.0.2",
37
37
  "@testing-library/svelte": "^3.2.2",
38
38
  "@testing-library/user-event": "^14.4.3",
39
- "@typescript-eslint/eslint-plugin": "^5.54.1",
40
- "@typescript-eslint/parser": "^5.54.1",
41
- "autoprefixer": "^10.4.13",
42
- "cssnano": "^5.1.15",
39
+ "@typescript-eslint/eslint-plugin": "^5.59.0",
40
+ "@typescript-eslint/parser": "^5.59.0",
41
+ "autoprefixer": "^10.4.14",
42
+ "cssnano": "^6.0.0",
43
43
  "dotenv": "^16.0.3",
44
- "edit-package-json": "^0.8.9",
45
- "eslint": "^8.35.0",
46
- "eslint-config-prettier": "^8.7.0",
44
+ "edit-package-json": "^0.8.12",
45
+ "eslint": "^8.39.0",
46
+ "eslint-config-prettier": "^8.8.0",
47
47
  "eslint-plugin-svelte3": "^4.0.0",
48
48
  "husky": "^8.0.3",
49
- "jsdom": "^21.1.0",
49
+ "jsdom": "^21.1.1",
50
50
  "micromatch": "^4.0.5",
51
- "postcss": "^8.4.21",
52
- "prettier": "^2.8.4",
53
- "prettier-plugin-svelte": "^2.9.0",
51
+ "postcss": "^8.4.23",
52
+ "prettier": "^2.8.7",
53
+ "prettier-plugin-svelte": "^2.10.0",
54
54
  "schema-dts": "^1.1.2",
55
- "svelte-check": "^3.1.0",
56
- "svelte2tsx": "^0.6.3",
57
- "tailwindcss": "^3.2.7",
55
+ "svelte-check": "^3.2.0",
56
+ "svelte2tsx": "^0.6.11",
57
+ "tailwindcss": "^3.3.1",
58
58
  "tslib": "^2.5.0",
59
- "typescript": "^4.9.5",
60
- "vite": "^4.1.4",
61
- "vitest": "^0.29.2"
59
+ "typescript": "^5.0.4",
60
+ "vite": "^4.3.1",
61
+ "vitest": "^0.30.1"
62
62
  },
63
63
  "type": "module",
64
64
  "license": "MIT",
package/types/index.d.ts CHANGED
@@ -41,7 +41,7 @@ export interface NormalizedTelNumber {
41
41
  countryCallingCode: CountryCallingCode | null;
42
42
  formattedNumber: string | null;
43
43
  formatOriginal: string | null;
44
- nationalNumber: NationalNumber | null;
44
+ nationalNumber: string | null;
45
45
  formatInternational: string | null;
46
46
  formatNational: string | null;
47
47
  uri: string | null;
@@ -74,3 +74,25 @@ export type TelInputDispatchEvents = {
74
74
  valid: boolean;
75
75
  value: E164Number | null;
76
76
  };
77
+
78
+ export interface TelInputOptions {
79
+ /**
80
+ * It generates a placeholder into your input for the selected country. E.g. if the country is `US`, the placeholder will be `201 555 0123` by default.
81
+ * If you need other format, you can use tha `national` -> `(201) 555-0123` and `international` -> `+1 201 555 0123` mode.
82
+ * @default true
83
+ */
84
+
85
+ autoPlaceholder?: boolean;
86
+ /**
87
+ * Allow or disallow spaces in the input field
88
+ * @default true
89
+ */
90
+ spaces?: boolean;
91
+ /**
92
+ * "formatInternational": "+36 20 123 4567",
93
+ * "formatOriginal": "20 123 4567",
94
+ * "formatNational": "06 20 123 4567",
95
+ * @default 'original'
96
+ */
97
+ // format: 'original' | 'national' | 'international';
98
+ }
@@ -1,3 +1,6 @@
1
- export declare const telInputAction: (node: HTMLInputElement, handler: (val: string) => void) => {
1
+ export declare const telInputAction: (node: HTMLInputElement, { handler, spaces }: {
2
+ handler: (val: string) => void;
3
+ spaces: boolean;
4
+ }) => {
2
5
  destroy(): void;
3
6
  };
@@ -1,11 +1,11 @@
1
1
  import { inspectAllowedChars, inputParser } from '../..';
2
- export const telInputAction = (node, handler) => {
2
+ export const telInputAction = (node, { handler, spaces }) => {
3
3
  const onInput = (event) => {
4
4
  if (node && node.contains(event.target)) {
5
5
  const value = event.target.value;
6
6
  const formattedInput = inputParser(value, {
7
7
  parseCharacter: inspectAllowedChars,
8
- allowSpaces: true
8
+ allowSpaces: spaces
9
9
  });
10
10
  node.value = formattedInput;
11
11
  handler(formattedInput);
@@ -5,6 +5,7 @@ export declare const isNumber: (value: number) => boolean;
5
5
  export declare const normalizeTelInput: (input?: PhoneNumber) => {
6
6
  [k: string]: string | boolean | E164Number | import("libphonenumber-js/types").CountryCallingCode | import("libphonenumber-js/types").NationalNumber | null | undefined;
7
7
  };
8
+ export declare const generatePlaceholder: (country: CountryCode, format?: 'international' | 'national' | 'default') => string;
8
9
  export declare const isSelected: <T extends {
9
10
  id: string;
10
11
  }>(itemToSelect: string | T, selectedItem: string | T | null | undefined) => boolean;
package/utils/helpers.js CHANGED
@@ -1,4 +1,5 @@
1
- import { AsYouType, Metadata, getCountryCallingCode } from 'libphonenumber-js/max';
1
+ import { AsYouType, Metadata, getCountryCallingCode, getExampleNumber } from 'libphonenumber-js/max';
2
+ import examples from 'libphonenumber-js/mobile/examples';
2
3
  export const capitalize = (str) => {
3
4
  return (str && str[0].toUpperCase() + str.slice(1).toLowerCase()) || '';
4
5
  };
@@ -43,6 +44,26 @@ export const normalizeTelInput = (input) => {
43
44
  }).filter(([, value]) => value !== null));
44
45
  return filteredResult;
45
46
  };
47
+ export const generatePlaceholder = (country, format = 'default') => {
48
+ const examplePhoneNumber = getExampleNumber(country, examples);
49
+ if (examplePhoneNumber) {
50
+ const countryCallingCode = examplePhoneNumber.countryCallingCode;
51
+ switch (format) {
52
+ case 'international':
53
+ return examplePhoneNumber.formatInternational();
54
+ case 'national':
55
+ return examplePhoneNumber.formatNational();
56
+ default:
57
+ return examplePhoneNumber
58
+ .formatInternational()
59
+ .slice(countryCallingCode.length + 1)
60
+ .trim();
61
+ }
62
+ }
63
+ else {
64
+ throw new Error(`No country found with this country code: ${country}`);
65
+ }
66
+ };
46
67
  export const isSelected = (itemToSelect, selectedItem) => {
47
68
  if (!selectedItem || selectedItem === null) {
48
69
  return false;
@@ -199,7 +220,7 @@ export const isSupportedCountry = (country, metadata) => {
199
220
  * @returns {string}
200
221
  */
201
222
  export const allowedCharacters = (character, { spaces } = {
202
- spaces: false
223
+ spaces: true
203
224
  }) => {
204
225
  const DIGITS = {
205
226
  '0': '0',