svelte-tel-input 1.3.2 → 2.0.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.
- package/CHANGELOG.md +18 -0
- package/README.md +23 -22
- package/components/Input/AdvancedTelInput.svelte +1 -1
- package/components/Input/TelInput.svelte +28 -3
- package/components/Input/TelInput.svelte.d.ts +4 -1
- package/package.json +25 -25
- package/types/index.d.ts +23 -1
- package/utils/directives/telInputAction.d.ts +4 -1
- package/utils/directives/telInputAction.js +2 -2
- package/utils/helpers.d.ts +1 -0
- package/utils/helpers.js +23 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# svelte-tel-input
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 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))
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- 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))
|
|
12
|
+
|
|
13
|
+
- feat: autoPlaceholder feature added, it generates placeholder for each country. ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- chore: update deps, re-generate package-lock.json ([#143](https://github.com/gyurielf/svelte-tel-input/pull/143))
|
|
18
|
+
|
|
19
|
+
- 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))
|
|
20
|
+
|
|
3
21
|
## 1.3.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -6,15 +6,6 @@
|
|
|
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.
|
|
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.
|
|
17
|
-
|
|
18
9
|
## Installation
|
|
19
10
|
|
|
20
11
|
Svelte Tel Input is distributed via [npm](https://www.npmjs.com/package/svelte-tel-input).
|
|
@@ -27,9 +18,9 @@ npm install --save svelte-tel-input
|
|
|
27
18
|
|
|
28
19
|
- Parse and validate phone number.You can store one exact format (`E164`), no matter how users type their phone numbers.
|
|
29
20
|
- Format (specified to its country), to make it more readable.
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
21
|
+
- Prevent non-digits typing into the input, except the leading `+` sign (and `space` optionally).
|
|
22
|
+
- Handle copy-pasted phone numbers, it's sanitize non-digit characters except the leading `+` sign (and `space` optionally).
|
|
23
|
+
- Automatic placeholder generation for the selected country.
|
|
33
24
|
|
|
34
25
|
## Usage
|
|
35
26
|
|
|
@@ -39,7 +30,7 @@ npm install --save svelte-tel-input
|
|
|
39
30
|
|
|
40
31
|
```html
|
|
41
32
|
<script lang="ts">
|
|
42
|
-
import TelInput,
|
|
33
|
+
import { TelInput, normalizedCountries } from 'svelte-tel-input';
|
|
43
34
|
import type { NormalizedTelNumber, CountryCode, E164Number } from 'svelte-tel-input/types';
|
|
44
35
|
|
|
45
36
|
// Any Country Code Alpha-2 (ISO 3166)
|
|
@@ -107,17 +98,26 @@ npm install --save svelte-tel-input
|
|
|
107
98
|
|
|
108
99
|
The default export of the library is the main TelInput component. It has the following props:
|
|
109
100
|
|
|
110
|
-
| Props
|
|
111
|
-
|
|
|
112
|
-
| country
|
|
113
|
-
| disabled
|
|
114
|
-
| valid
|
|
115
|
-
| value
|
|
116
|
-
| parsedTelInput
|
|
117
|
-
| class
|
|
101
|
+
| Props | Type | Default Value | Usage |
|
|
102
|
+
| --------------- | --------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| 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` |
|
|
104
|
+
| disabled | `boolean` | `false` | It's block the parser and prevent entering input. You must handle its styling on your own. |
|
|
105
|
+
| valid | `boolean` | `true` | Indicates whether the entered tel number validity. |
|
|
106
|
+
| 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. |
|
|
107
|
+
| parsedTelInput | `NormalizedTelInput \|null` | `null` | All of the formatted results of the tel input. |
|
|
108
|
+
| class | `string` | `` | You can pass down any classname to the component |
|
|
109
|
+
| autoPlaceholder | `boolean` | `true` | Generates country specific placeholder for the selected country.something |
|
|
110
|
+
| allowSpaces | `boolean` | `true` | Allow or disallow spaces in the input field |
|
|
118
111
|
|
|
119
112
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
|
120
113
|
|
|
114
|
+
## Goals
|
|
115
|
+
|
|
116
|
+
- Solve the problem that a users can enter the same phone number in different formats.
|
|
117
|
+
- Storing a phone number in a standard format, that can be indexable and searchable in any database.
|
|
118
|
+
- Should be accessible for the the browser. Eg. for a `<a href="tel+36201234567 />`.
|
|
119
|
+
- 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.
|
|
120
|
+
|
|
121
121
|
## Dependencies
|
|
122
122
|
|
|
123
123
|
[svelte](https://svelte.dev/)
|
|
@@ -141,7 +141,8 @@ The default export of the library is the main TelInput component. It has the fol
|
|
|
141
141
|
- [x] Integrate libphonenumber
|
|
142
142
|
- [x] Implement parser
|
|
143
143
|
- [x] Add basics docs and examples
|
|
144
|
-
- [
|
|
144
|
+
- [x] Add advanced examples
|
|
145
|
+
- [x] Generate placeholders autimatically
|
|
145
146
|
- [ ] Improve A11Y
|
|
146
147
|
|
|
147
148
|
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 {
|
|
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-tel-input",
|
|
3
3
|
"description": "svelte-tel-input",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
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": ">=
|
|
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.
|
|
26
|
-
"svelte": "^3.
|
|
25
|
+
"libphonenumber-js": "^1.10.28",
|
|
26
|
+
"svelte": "^3.58.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@changesets/cli": "^2.26.
|
|
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.
|
|
34
|
-
"@sveltejs/adapter-static": "^2.0.
|
|
35
|
-
"@sveltejs/kit": "^1.
|
|
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.
|
|
40
|
-
"@typescript-eslint/parser": "^5.
|
|
41
|
-
"autoprefixer": "^10.4.
|
|
42
|
-
"cssnano": "^
|
|
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.
|
|
45
|
-
"eslint": "^8.
|
|
46
|
-
"eslint-config-prettier": "^8.
|
|
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.
|
|
49
|
+
"jsdom": "^21.1.1",
|
|
50
50
|
"micromatch": "^4.0.5",
|
|
51
|
-
"postcss": "^8.4.
|
|
52
|
-
"prettier": "^2.8.
|
|
53
|
-
"prettier-plugin-svelte": "^2.
|
|
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.
|
|
56
|
-
"svelte2tsx": "^0.6.
|
|
57
|
-
"tailwindcss": "^3.
|
|
55
|
+
"svelte-check": "^3.2.0",
|
|
56
|
+
"svelte2tsx": "^0.6.11",
|
|
57
|
+
"tailwindcss": "^3.3.1",
|
|
58
58
|
"tslib": "^2.5.0",
|
|
59
|
-
"typescript": "^
|
|
60
|
-
"vite": "^4.1
|
|
61
|
-
"vitest": "^0.
|
|
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:
|
|
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
|
|
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:
|
|
8
|
+
allowSpaces: spaces
|
|
9
9
|
});
|
|
10
10
|
node.value = formattedInput;
|
|
11
11
|
handler(formattedInput);
|
package/utils/helpers.d.ts
CHANGED
|
@@ -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:
|
|
223
|
+
spaces: true
|
|
203
224
|
}) => {
|
|
204
225
|
const DIGITS = {
|
|
205
226
|
'0': '0',
|