svelte-tel-input 0.7.0 → 0.8.0

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 (41) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +8 -0
  3. package/assets/allCountry.js +2 -0
  4. package/assets/flags_responsive.png +0 -0
  5. package/components/Input/TelInput.svelte +18 -9
  6. package/components/Input/TelInput.svelte.d.ts +4 -5
  7. package/components/Select/Select.svelte +65 -8
  8. package/components/Select/Select.svelte.d.ts +16 -11
  9. package/components/Select/SelectListItem.svelte +1 -0
  10. package/components/utils/ExamplePayload.svelte +31 -0
  11. package/components/utils/ExamplePayload.svelte.d.ts +17 -0
  12. package/package.json +19 -24
  13. package/stores/exampleStore.d.ts +2 -0
  14. package/stores/exampleStore.js +2 -0
  15. package/stores/index.d.ts +4 -3
  16. package/stores/index.js +12 -2
  17. package/styles/flags.css +741 -0
  18. package/types/DynamicSvelteComponent.type.d.ts +1 -1
  19. package/types/index.d.ts +16 -1
  20. package/types/interfaces/Country.interface.d.ts +2 -0
  21. package/types/interfaces/Phone.interface.d.ts +4 -0
  22. package/utils/api.d.ts +7 -7
  23. package/utils/api.js +1 -1
  24. package/utils/helpers.d.ts +7 -1
  25. package/utils/helpers.js +31 -3
  26. package/assets/countries_deprecated.d.ts +0 -1
  27. package/assets/countries_deprecated.js +0 -602
  28. package/components/Select/TelRegionSelect/TelRegionSelect.svelte +0 -12
  29. package/components/Select/TelRegionSelect/TelRegionSelect.svelte.d.ts +0 -18
  30. package/components/Select/TelRegionSelect/TelRegionSelectOption.svelte +0 -4
  31. package/components/Select/TelRegionSelect/TelRegionSelectOption.svelte.d.ts +0 -18
  32. package/components/Select/TelTypeSelect/TelTypeSelect.svelte +0 -15
  33. package/components/Select/TelTypeSelect/TelTypeSelect.svelte.d.ts +0 -20
  34. package/components/Select/TelTypeSelect/TelTypeSelectOption.svelte +0 -4
  35. package/components/Select/TelTypeSelect/TelTypeSelectOption.svelte.d.ts +0 -18
  36. package/index.d.ts +0 -8
  37. package/index.js +0 -8
  38. package/types/Select.type.d.ts +0 -2
  39. package/types/Select.type.js +0 -1
  40. package/views/Usage.svelte +0 -55
  41. package/views/Usage.svelte.d.ts +0 -17
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # svelte-tel-input
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat: example improvements, extend functionality ([#70](https://github.com/gyurielf/svelte-tel-input/pull/70))
8
+
3
9
  ## 0.7.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  Lightweight phone input standardization.
8
8
 
9
+ ---
10
+
9
11
  ## Installation
10
12
 
11
13
  Svelte Tel Input is distributed via [npm](https://www.npmjs.com/package/svelte-tel-input).
@@ -22,6 +24,12 @@ npm install --save svelte-tel-input
22
24
 
23
25
  [libphonenumber-js](https://gitlab.com/catamphetamine/libphonenumber-js)
24
26
 
27
+ ## Features
28
+
29
+ - Automatically set the user's current country using an IP lookup. #TODO should be optional (IP (by default)|browserLang|off)
30
+
31
+ ---
32
+
25
33
  ## Changelog
26
34
 
27
35
  | Package | Changelog |
@@ -296,6 +296,8 @@ const allCountries = [
296
296
  ];
297
297
  export const normalizedCountries = allCountries.map((country) => {
298
298
  return {
299
+ id: country[1].toUpperCase(),
300
+ label: `${country[0]} +${country[2]}`,
299
301
  name: country[0],
300
302
  iso2: country[1].toUpperCase(),
301
303
  dialCode: country[2],
Binary file
@@ -1,32 +1,41 @@
1
- <script>import { enteredTelInputStore } from '../../stores';
1
+ <script>import { watcher } from '../../stores';
2
2
  import { PhoneNumberParseError } from '../../types';
3
+ import { normalizePhoneInput } from '../../utils/helpers';
3
4
  import { parsePhoneNumberWithError, ParseError } from 'libphonenumber-js';
4
5
  export let defaultCountry = null;
5
- export let phoneInput = null;
6
+ export let rawPhoneInput = null;
6
7
  export let parsedPhoneInput = null;
7
- export let error = null;
8
8
  export let disabled = false;
9
9
  export let id = null;
10
10
  export let name = null;
11
11
  const handleInput = (event) => {
12
12
  const inputVal = event.target.value;
13
- phoneInput = inputVal;
14
- $enteredTelInputStore = inputVal;
13
+ rawPhoneInput = inputVal;
14
+ handleParsePhoneNumber(defaultCountry, inputVal);
15
+ };
16
+ const handleParsePhoneNumber = (country, input) => {
15
17
  try {
16
- parsedPhoneInput = parsePhoneNumberWithError(inputVal, defaultCountry || undefined);
17
- error = null;
18
+ parsedPhoneInput = normalizePhoneInput(parsePhoneNumberWithError(input, country || undefined));
18
19
  }
19
20
  catch (err) {
20
21
  if (err instanceof ParseError) {
21
22
  // Not a phone number, non-existent country, etc.
22
- parsedPhoneInput = null;
23
- error = PhoneNumberParseError[err.message];
23
+ parsedPhoneInput = {
24
+ isValid: false,
25
+ error: PhoneNumberParseError[err.message]
26
+ };
24
27
  }
25
28
  else {
26
29
  throw err;
27
30
  }
28
31
  }
29
32
  };
33
+ const watchFunction = () => {
34
+ if (rawPhoneInput !== null)
35
+ handleParsePhoneNumber(defaultCountry, rawPhoneInput);
36
+ };
37
+ const countryChangeWatch = watcher(null, watchFunction);
38
+ $: $countryChangeWatch = defaultCountry;
30
39
  </script>
31
40
 
32
41
  <input {id} {name} class={$$props.class} {disabled} type="tel" on:input={handleInput} />
@@ -1,13 +1,12 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { PhoneNumberParseError } from '../../types';
3
- import { type CountryCode, type PhoneNumber } from 'libphonenumber-js';
2
+ import type { NormalizedPhoneNumber } from '../../types/interfaces/Phone.interface';
3
+ import { type CountryCode } from 'libphonenumber-js';
4
4
  declare const __propDef: {
5
5
  props: {
6
6
  [x: string]: any;
7
7
  defaultCountry?: CountryCode | null | undefined;
8
- phoneInput?: string | null | undefined;
9
- parsedPhoneInput?: PhoneNumber | null | undefined;
10
- error?: PhoneNumberParseError | null | undefined;
8
+ rawPhoneInput?: string | null | undefined;
9
+ parsedPhoneInput?: NormalizedPhoneNumber | null | undefined;
11
10
  disabled?: boolean | undefined;
12
11
  id?: string | null | undefined;
13
12
  name?: string | null | undefined;
@@ -1,12 +1,23 @@
1
1
  <script>import { clickOutsideAction } from '../../utils/directives/clickOutsideAction';
2
+ import { isSelected } from '../../utils/helpers';
3
+ import { createEventDispatcher } from 'svelte';
2
4
  export let selectOptions = {
3
5
  searchInput: false,
4
- flags: true
6
+ flags: false
5
7
  };
8
+ export let disabled = false;
6
9
  export let items;
10
+ export let selected = null;
7
11
  export let clickOutside = true;
8
12
  let isOpen = false;
9
- let enteredSearch;
13
+ let closeOnClick = true;
14
+ export let searchText = '';
15
+ $: filteredItems =
16
+ searchText && searchText.length > 0
17
+ ? items
18
+ .filter((el) => el.label.toLowerCase().indexOf(searchText.toLowerCase()) >= 0)
19
+ .sort((a, b) => (a.label < b.label ? -1 : 1))
20
+ : items;
10
21
  const toggleSelect = (e) => {
11
22
  e?.preventDefault();
12
23
  isOpen = !isOpen;
@@ -14,6 +25,7 @@ const toggleSelect = (e) => {
14
25
  const closeSelect = (e) => {
15
26
  e?.preventDefault();
16
27
  isOpen = false;
28
+ searchText = '';
17
29
  };
18
30
  const handleClickOutside = (e) => {
19
31
  e?.preventDefault();
@@ -21,25 +33,70 @@ const handleClickOutside = (e) => {
21
33
  closeSelect(e);
22
34
  }
23
35
  };
36
+ const selectClick = () => {
37
+ if (closeOnClick)
38
+ closeSelect();
39
+ };
40
+ const handleSelect = (val) => {
41
+ if (disabled)
42
+ return;
43
+ if (typeof selected === 'object' && typeof val === 'object' && selected?.id && val?.id) {
44
+ if (typeof selected === 'object' && typeof val === 'object' && selected.id !== val.id) {
45
+ selected = val;
46
+ onChange(val);
47
+ selectClick();
48
+ }
49
+ else {
50
+ dispatch('same', { option: val });
51
+ selectClick();
52
+ }
53
+ }
54
+ else if (((selected === undefined || selected === null) && typeof val === 'object') ||
55
+ (typeof selected === typeof val && selected !== val)) {
56
+ selected = val;
57
+ onChange(val);
58
+ selectClick();
59
+ }
60
+ else {
61
+ dispatch('same', { option: val });
62
+ selectClick();
63
+ }
64
+ };
65
+ const dispatch = createEventDispatcher();
66
+ const onChange = (selectedType) => {
67
+ dispatch('change', { option: selectedType });
68
+ };
24
69
  </script>
25
70
 
26
71
  <div class="select cursor-pointer" use:clickOutsideAction={handleClickOutside}>
27
- <div on:click={() => toggleSelect()}>CHOOSE</div>
72
+ {#if selected && selected !== null}
73
+ <div on:click={() => toggleSelect()}>{selected.label}</div>
74
+ {:else}
75
+ <div on:click={() => toggleSelect()}>CHOOSE</div>
76
+ {/if}
77
+
28
78
  {#if isOpen}
29
79
  <ul class="border border-gray-900 max-h-40 w-fit overflow-y-scroll">
30
80
  {#if !selectOptions.searchInput}
31
81
  <input
32
82
  type="text"
33
83
  class="px-4 py-1 text-gray-900 focus:outline-none w-full"
34
- bind:value={enteredSearch}
84
+ bind:value={searchText}
35
85
  />
36
86
  {/if}
37
- {#each items as item}
38
- <li class="p-2 bg-gray-600 hover:bg-opacity-30">
39
- <span class="mr-3">{item.name}</span> +{item.dialCode}
87
+ {#each filteredItems as item (item.id)}
88
+ <li
89
+ class="p-2 {isSelected(item, selected)
90
+ ? 'bg-red-400'
91
+ : 'bg-gray-600 hover:bg-opacity-30'}"
92
+ on:click={() => {
93
+ handleSelect(item);
94
+ }}
95
+ >
96
+ <span class="mr-3">{item.label}</span>
40
97
  </li>
41
98
  {:else}
42
- <div>List is on the way..</div>
99
+ <div>List of items is on the way..</div>
43
100
  {/each}
44
101
  </ul>
45
102
  {/if}
@@ -1,22 +1,27 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import type { Country } from '../../types/interfaces/Country.interface';
3
- declare const __propDef: {
4
- props: {
2
+ import type { TelSelectObject, Country } from '../../types';
3
+ declare class __sveltets_Render<T extends Country | TelSelectObject> {
4
+ props(): {
5
5
  selectOptions?: {
6
6
  searchInput: boolean;
7
7
  flags: boolean;
8
8
  } | undefined;
9
- items: Country[];
9
+ disabled?: boolean | undefined;
10
+ items: T[];
11
+ selected?: T | null | undefined;
10
12
  clickOutside?: boolean | undefined;
13
+ searchText?: string | undefined;
11
14
  };
12
- events: {
15
+ events(): {
16
+ change: CustomEvent<any>;
17
+ } & {
13
18
  [evt: string]: CustomEvent<any>;
14
19
  };
15
- slots: {};
16
- };
17
- export declare type SelectProps = typeof __propDef.props;
18
- export declare type SelectEvents = typeof __propDef.events;
19
- export declare type SelectSlots = typeof __propDef.slots;
20
- export default class Select extends SvelteComponentTyped<SelectProps, SelectEvents, SelectSlots> {
20
+ slots(): {};
21
+ }
22
+ export declare type SelectProps<T extends Country | TelSelectObject> = ReturnType<__sveltets_Render<T>['props']>;
23
+ export declare type SelectEvents<T extends Country | TelSelectObject> = ReturnType<__sveltets_Render<T>['events']>;
24
+ export declare type SelectSlots<T extends Country | TelSelectObject> = ReturnType<__sveltets_Render<T>['slots']>;
25
+ export default class Select<T extends Country | TelSelectObject> extends SvelteComponentTyped<SelectProps<T>, SelectEvents<T>, SelectSlots<T>> {
21
26
  }
22
27
  export {};
@@ -1,6 +1,7 @@
1
1
  <script>import { createEventDispatcher } from 'svelte';
2
2
  const dispatch = createEventDispatcher();
3
3
  const setSelected = (e) => {
4
+ e?.preventDefault();
4
5
  dispatch('selectedItem');
5
6
  };
6
7
  </script>
@@ -0,0 +1,31 @@
1
+ <script>import { jsonPrettyParser } from '../../utils/helpers';
2
+ export let exampleData;
3
+ $: exampleDataEntries = (exampleData && Object.entries(exampleData)) || [];
4
+ </script>
5
+
6
+ <div class="validation-table grid grid-cols-2 mt-5 border rounded-sm border-gray-100 p-3 font-mono">
7
+ <div class="grid grid-cols-2">
8
+ <div>
9
+ <h3 class="text-lg font-semibold">Key</h3>
10
+ {#each exampleDataEntries as [key, _]}
11
+ <div>{key}</div>
12
+ {/each}
13
+ </div>
14
+ <div>
15
+ <h3 class="text-lg font-semibold">Value</h3>
16
+ {#each exampleDataEntries as [_, value]}
17
+ <div>{value}</div>
18
+ {/each}
19
+ </div>
20
+ </div>
21
+ <div class="grid">
22
+ <h3 class="text-lg font-semibold">Payload</h3>
23
+ {#key exampleData}
24
+ <pre
25
+ lang="no-highlight"
26
+ class="whitespace-pre-wrap "
27
+ use:jsonPrettyParser={exampleData}
28
+ />
29
+ {/key}
30
+ </div>
31
+ </div>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { NormalizedPhoneNumber } from '../../types/interfaces/Phone.interface';
3
+ declare const __propDef: {
4
+ props: {
5
+ exampleData: NormalizedPhoneNumber;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type ExamplePayloadProps = typeof __propDef.props;
13
+ export declare type ExamplePayloadEvents = typeof __propDef.events;
14
+ export declare type ExamplePayloadSlots = typeof __propDef.slots;
15
+ export default class ExamplePayload extends SvelteComponentTyped<ExamplePayloadProps, ExamplePayloadEvents, ExamplePayloadSlots> {
16
+ }
17
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "svelte-tel-input",
3
3
  "description": "svelte-tel-input",
4
- "version": "0.7.0",
4
+ "version": "0.8.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/gyurielf/svelte-tel-input.git"
@@ -21,32 +21,32 @@
21
21
  "node": ">= 16"
22
22
  },
23
23
  "dependencies": {
24
- "libphonenumber-js": "^1.10.9"
24
+ "libphonenumber-js": "^1.10.11"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@babel/core": "^7.18.9",
28
28
  "@babel/preset-env": "^7.18.9",
29
- "@changesets/cli": "^2.24.0",
29
+ "@changesets/cli": "^2.24.1",
30
30
  "@changesets/get-github-info": "^0.5.1",
31
31
  "@changesets/types": "^5.1.0",
32
32
  "@sveltejs/adapter-static": "^1.0.0-next.38",
33
- "@sveltejs/kit": "^1.0.0-next.388",
33
+ "@sveltejs/kit": "^1.0.0-next.398",
34
34
  "@testing-library/jest-dom": "^5.16.4",
35
35
  "@testing-library/svelte": "^3.1.3",
36
- "@types/jest": "^28.1.4",
37
- "@typescript-eslint/eslint-plugin": "^5.30.7",
38
- "@typescript-eslint/parser": "^5.30.7",
39
- "autoprefixer": "^10.4.7",
40
- "babel-jest": "^28.1.2",
36
+ "@types/jest": "^28.1.6",
37
+ "@typescript-eslint/eslint-plugin": "^5.31.0",
38
+ "@typescript-eslint/parser": "^5.31.0",
39
+ "autoprefixer": "^10.4.8",
40
+ "babel-jest": "^28.1.3",
41
41
  "babel-loader": "^8.2.5",
42
42
  "cssnano": "^5.1.12",
43
43
  "dotenv": "^16.0.1",
44
44
  "eslint": "^8.20.0",
45
45
  "eslint-config-prettier": "^8.5.0",
46
- "eslint-plugin-jest": "^26.5.3",
46
+ "eslint-plugin-jest": "^26.7.0",
47
47
  "eslint-plugin-svelte3": "^4.0.0",
48
48
  "husky": "^8.0.1",
49
- "jest": "^28.1.2",
49
+ "jest": "^28.1.3",
50
50
  "jest-matchmedia-mock": "^1.1.0",
51
51
  "micromatch": "^4.0.5",
52
52
  "postcss": "^8.4.14",
@@ -59,10 +59,10 @@
59
59
  "svelte-jester": "^2.3.2",
60
60
  "svelte-loader": "^3.1.3",
61
61
  "svelte-preprocess": "^4.10.7",
62
- "svelte2tsx": "^0.5.12",
63
- "tailwindcss": "^3.1.6",
64
- "ts-jest": "^28.0.5",
65
- "tsconfig-paths-webpack-plugin": "^3.5.2",
62
+ "svelte2tsx": "^0.5.13",
63
+ "tailwindcss": "^3.1.7",
64
+ "ts-jest": "^28.0.7",
65
+ "tsconfig-paths-webpack-plugin": "^4.0.0",
66
66
  "tslib": "^2.4.0",
67
67
  "typescript": "^4.7.4"
68
68
  },
@@ -139,7 +139,7 @@
139
139
  "exports": {
140
140
  "./package.json": "./package.json",
141
141
  "./assets/allCountry": "./assets/allCountry.js",
142
- "./assets/countries_deprecated": "./assets/countries_deprecated.js",
142
+ "./assets/flags_responsive.png": "./assets/flags_responsive.png",
143
143
  "./assets": "./assets/index.js",
144
144
  "./assets/regions": "./assets/regions.js",
145
145
  "./assets/telTypes": "./assets/telTypes.js",
@@ -147,14 +147,10 @@
147
147
  "./components/Select/Select.svelte": "./components/Select/Select.svelte",
148
148
  "./components/Select/SelectListItem.svelte": "./components/Select/SelectListItem.svelte",
149
149
  "./components/Select/TelCountrySelect/TelCountrySelect.svelte": "./components/Select/TelCountrySelect/TelCountrySelect.svelte",
150
- "./components/Select/TelRegionSelect/TelRegionSelect.svelte": "./components/Select/TelRegionSelect/TelRegionSelect.svelte",
151
- "./components/Select/TelRegionSelect/TelRegionSelectOption.svelte": "./components/Select/TelRegionSelect/TelRegionSelectOption.svelte",
152
- "./components/Select/TelTypeSelect/TelTypeSelect.svelte": "./components/Select/TelTypeSelect/TelTypeSelect.svelte",
153
- "./components/Select/TelTypeSelect/TelTypeSelectOption.svelte": "./components/Select/TelTypeSelect/TelTypeSelectOption.svelte",
154
- ".": "./index.js",
150
+ "./stores/exampleStore": "./stores/exampleStore.js",
155
151
  "./stores": "./stores/index.js",
152
+ "./styles/flags.css": "./styles/flags.css",
156
153
  "./types/DynamicSvelteComponent.type": "./types/DynamicSvelteComponent.type.js",
157
- "./types/Select.type": "./types/Select.type.js",
158
154
  "./types/enums/PhoneNumberParseError.enum": "./types/enums/PhoneNumberParseError.enum.js",
159
155
  "./types/enums/PhoneType.enum": "./types/enums/PhoneType.enum.js",
160
156
  "./types/enums": "./types/enums/index.js",
@@ -167,7 +163,6 @@
167
163
  "./utils/directives/clickOutsideAction": "./utils/directives/clickOutsideAction.js",
168
164
  "./utils/helpers": "./utils/helpers.js",
169
165
  "./utils/simulator": "./utils/simulator.js",
170
- "./utils/typeCheck": "./utils/typeCheck.js",
171
- "./views/Usage.svelte": "./views/Usage.svelte"
166
+ "./utils/typeCheck": "./utils/typeCheck.js"
172
167
  }
173
168
  }
@@ -0,0 +1,2 @@
1
+ import type { NormalizedPhoneNumber } from '../types/interfaces/Phone.interface';
2
+ export declare const exampleDataStore: import("svelte/store").Writable<NormalizedPhoneNumber>;
@@ -0,0 +1,2 @@
1
+ import { writable } from 'svelte/store';
2
+ export const exampleDataStore = writable();
package/stores/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { Writable } from 'svelte/store';
2
- import type { SelectType } from '../types';
3
2
  export declare const booleanStore: (initial: boolean) => {
4
3
  isOpen: Writable<boolean>;
5
4
  open: () => void;
@@ -11,7 +10,9 @@ export declare const statefulSwap: (initialState: boolean | null) => {
11
10
  transitionTo: (newState: boolean | null) => void;
12
11
  onOutro: () => void;
13
12
  };
13
+ export declare const watcher: (initialValue: string | null, watchFunction: (oldVal: string | null, newVal: string | null) => void) => {
14
+ subscribe: (this: void, run: import("svelte/store").Subscriber<string | null>, invalidate?: ((value?: string | null | undefined) => void) | undefined) => import("svelte/store").Unsubscriber;
15
+ set: (value: string | null) => void;
16
+ };
14
17
  export declare const selectedCountryStore: Writable<string>;
15
- export declare const selectedRegionStore: Writable<string>;
16
- export declare const selectedTelTypeStore: Writable<SelectType>;
17
18
  export declare const enteredTelInputStore: Writable<string>;
package/stores/index.js CHANGED
@@ -29,9 +29,19 @@ export const statefulSwap = (initialState) => {
29
29
  onOutro
30
30
  };
31
31
  };
32
+ export const watcher = (initialValue, watchFunction) => {
33
+ const { subscribe, update } = writable(initialValue);
34
+ return {
35
+ subscribe,
36
+ set: (value) => {
37
+ update((oldvalue) => {
38
+ watchFunction(oldvalue, value);
39
+ return value;
40
+ });
41
+ }
42
+ };
43
+ };
32
44
  // SELECTS
33
45
  export const selectedCountryStore = writable();
34
- export const selectedRegionStore = writable();
35
- export const selectedTelTypeStore = writable();
36
46
  // INPUT
37
47
  export const enteredTelInputStore = writable();