@xsolla/xui-input-phone 0.150.0 → 0.152.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/README.md +155 -169
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,212 +1,198 @@
|
|
|
1
|
-
#
|
|
1
|
+
# InputPhone
|
|
2
2
|
|
|
3
|
-
A cross-platform
|
|
3
|
+
A cross-platform phone-number input with an integrated, searchable country selector (flags and dial codes); ships with a `usePhoneNumber` hook for formatting and country detection.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @xsolla/xui-input-phone
|
|
9
|
-
# or
|
|
10
|
-
yarn add @xsolla/xui-input-phone
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
### Basic Phone Input
|
|
11
|
+
## Imports
|
|
16
12
|
|
|
17
13
|
```tsx
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
import {
|
|
15
|
+
InputPhone,
|
|
16
|
+
usePhoneNumber,
|
|
17
|
+
allCountries,
|
|
18
|
+
defaultCountries,
|
|
19
|
+
getCountryByCode,
|
|
20
|
+
getCountryByDialCode,
|
|
21
|
+
getFlag,
|
|
22
|
+
} from '@xsolla/xui-input-phone';
|
|
23
|
+
import type {
|
|
24
|
+
InputPhoneProps,
|
|
25
|
+
Country,
|
|
26
|
+
UsePhoneNumberOptions,
|
|
27
|
+
UsePhoneNumberReturn,
|
|
28
|
+
} from '@xsolla/xui-input-phone';
|
|
32
29
|
```
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
## Quick start
|
|
35
32
|
|
|
36
33
|
```tsx
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<InputPhone
|
|
46
|
-
value={phone}
|
|
47
|
-
onChange={(e) => setPhone(e.target.value)}
|
|
48
|
-
selectedCountry={country}
|
|
49
|
-
onCountryChange={setCountry}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
34
|
+
const [phone, setPhone] = useState('');
|
|
35
|
+
|
|
36
|
+
<InputPhone
|
|
37
|
+
value={phone}
|
|
38
|
+
onChangeText={setPhone}
|
|
39
|
+
placeholder="+1 (000) 000-0000"
|
|
40
|
+
/>;
|
|
53
41
|
```
|
|
54
42
|
|
|
55
|
-
|
|
43
|
+
## API Reference
|
|
56
44
|
|
|
57
|
-
|
|
58
|
-
import * as React from 'react';
|
|
59
|
-
import { InputPhone } from '@xsolla/xui-input-phone';
|
|
60
|
-
|
|
61
|
-
export default function ValidatedPhoneInput() {
|
|
62
|
-
const [phone, setPhone] = React.useState('');
|
|
63
|
-
const isValid = phone.length >= 10;
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<InputPhone
|
|
67
|
-
value={phone}
|
|
68
|
-
onChange={(e) => setPhone(e.target.value)}
|
|
69
|
-
checked={isValid}
|
|
70
|
-
extraClear={true}
|
|
71
|
-
onRemove={() => setPhone('')}
|
|
72
|
-
/>
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
```
|
|
45
|
+
### `<InputPhone>`
|
|
76
46
|
|
|
77
|
-
|
|
47
|
+
| Prop | Type | Default | Description |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `value` | `string` | — | Controlled value. |
|
|
50
|
+
| `placeholder` | `string` | — | Placeholder shown when empty. |
|
|
51
|
+
| `onChange` | `(e: ChangeEvent<HTMLInputElement>) => void` | — | Native change handler. |
|
|
52
|
+
| `onChangeText` | `(text: string) => void` | — | Simplified change handler. |
|
|
53
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Control size. |
|
|
54
|
+
| `name` | `string` | — | Form field name. |
|
|
55
|
+
| `disabled` | `boolean` | `false` | Disable the control. |
|
|
56
|
+
| `error` | `boolean` | `false` | Apply error styling. |
|
|
57
|
+
| `errorMessage` | `string` | — | Error message; also marks the control invalid. |
|
|
58
|
+
| `countries` | `Country[]` | `allCountries` | Countries available in the dropdown. |
|
|
59
|
+
| `selectedCountry` | `Country` | — | Currently selected country. |
|
|
60
|
+
| `onCountryChange` | `(country: Country) => void` | — | Fired when the country changes. |
|
|
61
|
+
| `extraClear` | `boolean` | `false` | Show a clear button when the input has a value. |
|
|
62
|
+
| `onRemove` | `() => void` | — | Fired when the clear button is pressed. |
|
|
63
|
+
| `checked` | `boolean` | `false` | Show a success indicator (suppressed when `errorMessage` is set). |
|
|
64
|
+
| `checkedIcon` | `ReactNode` | `<CheckCr />` | Override the checked icon. |
|
|
65
|
+
| `id` | `string` | `auto` | HTML id. |
|
|
66
|
+
| `aria-label` | `string` | — | Accessible label when no visible label is present. |
|
|
67
|
+
| `testID` | `string` | — | Test identifier. |
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
import { InputPhone } from '@xsolla/xui-input-phone';
|
|
69
|
+
`InputPhone` also accepts the standard `InputHTMLAttributes` (excluding `size` and `onChange`).
|
|
81
70
|
|
|
82
|
-
|
|
83
|
-
value={phoneNumber} // Phone number value
|
|
84
|
-
onChange={handleChange} // Change event handler
|
|
85
|
-
selectedCountry={country} // Currently selected country
|
|
86
|
-
onCountryChange={setCountry} // Country selection handler
|
|
87
|
-
countries={customCountries} // Custom countries array
|
|
88
|
-
placeholder="+1 (000) 000-0000" // Placeholder text
|
|
89
|
-
size="md" // Size variant
|
|
90
|
-
disabled={false} // Disabled state
|
|
91
|
-
error={false} // Error state
|
|
92
|
-
errorMessage="Error" // Error message
|
|
93
|
-
extraClear={false} // Show clear button
|
|
94
|
-
onRemove={handleClear} // Clear button handler
|
|
95
|
-
checked={false} // Show validation checkmark
|
|
96
|
-
/>
|
|
97
|
-
```
|
|
71
|
+
Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
98
72
|
|
|
99
|
-
|
|
73
|
+
### Hooks
|
|
100
74
|
|
|
101
|
-
|
|
75
|
+
#### `usePhoneNumber(options?)`
|
|
102
76
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
77
|
+
Manages a phone-number value with normalisation, formatting (via `libphonenumber-js`) and automatic country detection.
|
|
78
|
+
|
|
79
|
+
| Option | Type | Description |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `initialCountry` | `string` | ISO 3166-1 alpha-2 code (e.g. `'US'`). |
|
|
82
|
+
| `initialValue` | `string` | Initial phone-number value. |
|
|
83
|
+
| `onChange` | `(phoneNumber: string) => void` | Fired when the phone number changes. |
|
|
84
|
+
| `onCountryChange` | `(country: Country \| undefined) => void` | Fired when the country changes. |
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
|
|
88
|
+
| Field | Type | Description |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| `phoneNumber` | `string` | Raw phone number (with country code). |
|
|
91
|
+
| `formattedPhoneNumber` | `string` | Display-formatted phone number. |
|
|
92
|
+
| `country` | `Country \| undefined` | Detected/selected country. |
|
|
93
|
+
| `countries` | `Country[]` | All available countries (`allCountries`). |
|
|
94
|
+
| `handlePhoneChange` | `(value: string) => void` | Handle phone input change. |
|
|
95
|
+
| `handleCountryChange` | `(country: Country) => void` | Handle country selection. |
|
|
96
|
+
| `setPhoneNumber` | `(value: string) => void` | Set the phone number programmatically. |
|
|
97
|
+
|
|
98
|
+
### `allCountries`
|
|
99
|
+
|
|
100
|
+
`Country[]` — full list of supported countries.
|
|
101
|
+
|
|
102
|
+
### `defaultCountries`
|
|
103
|
+
|
|
104
|
+
`Country[]` — curated default subset.
|
|
105
|
+
|
|
106
|
+
### `getCountryByCode`
|
|
107
|
+
|
|
108
|
+
`(code: string) => Country | undefined` — look up by ISO alpha-2 code.
|
|
109
|
+
|
|
110
|
+
### `getCountryByDialCode`
|
|
111
|
+
|
|
112
|
+
`(dialCode: string) => Country | undefined` — look up by dial code (e.g. `'+44'`).
|
|
113
|
+
|
|
114
|
+
### `getFlag`
|
|
115
|
+
|
|
116
|
+
`(code: string) => ReactNode` — get the flag icon for a country code.
|
|
117
|
+
|
|
118
|
+
### Types
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
interface Country {
|
|
122
|
+
code: string; // ISO 3166-1 alpha-2 (e.g. "US")
|
|
123
|
+
name: string;
|
|
124
|
+
dialCode: string; // e.g. "+1"
|
|
125
|
+
flag?: ReactNode;
|
|
115
126
|
}
|
|
116
127
|
```
|
|
117
128
|
|
|
118
|
-
|
|
129
|
+
## Examples
|
|
130
|
+
|
|
131
|
+
### With country selection
|
|
119
132
|
|
|
120
133
|
```tsx
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<InputPhone size="lg" placeholder="Large" />
|
|
131
|
-
<InputPhone size="xl" placeholder="Extra Large" />
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
134
|
+
const [phone, setPhone] = useState('');
|
|
135
|
+
const [country, setCountry] = useState<Country | undefined>();
|
|
136
|
+
|
|
137
|
+
<InputPhone
|
|
138
|
+
value={phone}
|
|
139
|
+
onChangeText={setPhone}
|
|
140
|
+
selectedCountry={country}
|
|
141
|
+
onCountryChange={setCountry}
|
|
142
|
+
/>;
|
|
135
143
|
```
|
|
136
144
|
|
|
137
|
-
###
|
|
145
|
+
### Using `usePhoneNumber`
|
|
146
|
+
|
|
147
|
+
Reach for the hook when you want normalisation, formatting (via `libphonenumber-js`) and automatic country detection bundled together; reach for the imperative `selectedCountry`/`onCountryChange` API when you already manage the value and only need a controlled country selector.
|
|
138
148
|
|
|
139
149
|
```tsx
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
{ code: 'DE', name: 'Germany', dialCode: '+49' },
|
|
150
|
-
];
|
|
151
|
-
|
|
152
|
-
return (
|
|
153
|
-
<InputPhone
|
|
154
|
-
value={phone}
|
|
155
|
-
onChange={(e) => setPhone(e.target.value)}
|
|
156
|
-
countries={countries}
|
|
157
|
-
/>
|
|
158
|
-
);
|
|
159
|
-
}
|
|
150
|
+
const { phoneNumber, country, handlePhoneChange, handleCountryChange } =
|
|
151
|
+
usePhoneNumber({ initialCountry: 'MY' });
|
|
152
|
+
|
|
153
|
+
<InputPhone
|
|
154
|
+
value={phoneNumber}
|
|
155
|
+
onChangeText={handlePhoneChange}
|
|
156
|
+
selectedCountry={country}
|
|
157
|
+
onCountryChange={handleCountryChange}
|
|
158
|
+
/>;
|
|
160
159
|
```
|
|
161
160
|
|
|
162
|
-
|
|
161
|
+
### Custom countries
|
|
163
162
|
|
|
164
|
-
|
|
163
|
+
```tsx
|
|
164
|
+
const countries: Country[] = [
|
|
165
|
+
{ code: 'US', name: 'United States', dialCode: '+1' },
|
|
166
|
+
{ code: 'GB', name: 'United Kingdom', dialCode: '+44' },
|
|
167
|
+
{ code: 'DE', name: 'Germany', dialCode: '+49' },
|
|
168
|
+
];
|
|
165
169
|
|
|
166
|
-
|
|
170
|
+
<InputPhone countries={countries} />;
|
|
171
|
+
```
|
|
167
172
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
| placeholder | `string` | `"+1 (000) 000-0000"` | Placeholder text. |
|
|
177
|
-
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | Component size. |
|
|
178
|
-
| disabled | `boolean` | `false` | Disabled state. |
|
|
179
|
-
| error | `boolean` | `false` | Error state. |
|
|
180
|
-
| errorMessage | `string` | - | Error message text. |
|
|
181
|
-
| extraClear | `boolean` | `false` | Show clear button. |
|
|
182
|
-
| onRemove | `() => void` | - | Clear button handler. |
|
|
183
|
-
| checked | `boolean` | `false` | Show validation checkmark. |
|
|
184
|
-
| checkedIcon | `ReactNode` | Check icon | Custom checkmark icon. |
|
|
185
|
-
| testID | `string` | - | Test identifier. |
|
|
186
|
-
|
|
187
|
-
**Country Interface:**
|
|
188
|
-
|
|
189
|
-
```typescript
|
|
190
|
-
interface Country {
|
|
191
|
-
code: string; // ISO 3166-1 alpha-2 (e.g., "US")
|
|
192
|
-
name: string; // Country name
|
|
193
|
-
dialCode: string; // International dial code (e.g., "+1")
|
|
194
|
-
flag?: ReactNode; // Optional flag icon
|
|
195
|
-
}
|
|
173
|
+
### Sizes
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<InputPhone size="xs" placeholder="Extra small" />
|
|
177
|
+
<InputPhone size="sm" placeholder="Small" />
|
|
178
|
+
<InputPhone size="md" placeholder="Medium" />
|
|
179
|
+
<InputPhone size="lg" placeholder="Large" />
|
|
180
|
+
<InputPhone size="xl" placeholder="Extra large" />
|
|
196
181
|
```
|
|
197
182
|
|
|
198
|
-
|
|
183
|
+
### Error state
|
|
199
184
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
185
|
+
```tsx
|
|
186
|
+
<InputPhone
|
|
187
|
+
value="123"
|
|
188
|
+
error
|
|
189
|
+
errorMessage="Please enter a valid phone number"
|
|
190
|
+
/>
|
|
191
|
+
```
|
|
206
192
|
|
|
207
193
|
## Accessibility
|
|
208
194
|
|
|
209
|
-
-
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
195
|
+
- The country selector uses `role="combobox"`; the list uses `role="listbox"` with `role="option"` items, linked via `aria-controls`.
|
|
196
|
+
- The phone field uses `type="tel"` and `inputMode="tel"`.
|
|
197
|
+
- Keyboard: ArrowDown opens / advances; ArrowUp moves up; Enter selects; Escape closes the dropdown.
|
|
198
|
+
- `errorMessage` is linked via `aria-describedby` and marks the input invalid.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-input-phone",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.152.0",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"test:coverage": "vitest run --coverage"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@xsolla/xui-core": "0.
|
|
17
|
-
"@xsolla/xui-primitives-core": "0.
|
|
16
|
+
"@xsolla/xui-core": "0.152.0",
|
|
17
|
+
"@xsolla/xui-primitives-core": "0.152.0",
|
|
18
18
|
"libphonenumber-js": "^1.10.56"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|