@desource/phone-mask-react 0.3.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 +13 -0
- package/LICENSE +21 -0
- package/README.md +455 -0
- package/dist/esm/components/PhoneInput.d.ts +11 -0
- package/dist/esm/components/PhoneInput.d.ts.map +1 -0
- package/dist/esm/consts.d.ts +4 -0
- package/dist/esm/consts.d.ts.map +1 -0
- package/dist/esm/hooks/usePhoneMask.d.ts +7 -0
- package/dist/esm/hooks/usePhoneMask.d.ts.map +1 -0
- package/dist/esm/index.d.ts +14 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +864 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.d.ts +181 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/utils.d.ts +16 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/phone-mask-react.cjs +2 -0
- package/dist/phone-mask-react.cjs.map +1 -0
- package/dist/phone-mask-react.css +1 -0
- package/package.json +77 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @desource/phone-mask-react
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- React: Design React version of phone-mask library
|
|
8
|
+
- Core: Add geoip reusable service for country detection based on IP address
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies []:
|
|
13
|
+
- @desource/phone-mask@0.3.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeSource Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
# @desource/phone-mask-react
|
|
2
|
+
|
|
3
|
+
> React phone input component and hook with smart masking and Google libphonenumber data
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@desource/phone-mask-react)
|
|
6
|
+
[](https://bundlephobia.com/package/@desource/phone-mask-react)
|
|
7
|
+
[](https://github.com/DeSource-Labs/phone-mask/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
Beautiful, accessible, extreme small & tree-shackable React phone input with auto-formatting, country selector, and validation.
|
|
10
|
+
|
|
11
|
+
## ✨ Features
|
|
12
|
+
|
|
13
|
+
- 🎨 **Beautiful UI** — Modern design with light/dark themes
|
|
14
|
+
- 🔍 **Smart Country Search** — Fuzzy matching with keyboard navigation
|
|
15
|
+
- 🎭 **Auto-formatting** — As-you-type formatting with smart cursor
|
|
16
|
+
- ✅ **Validation** — Built-in validation with visual feedback
|
|
17
|
+
- 📋 **Copy Button** — One-click copy to clipboard
|
|
18
|
+
- 🌐 **Auto-detection** — GeoIP and locale-based detection
|
|
19
|
+
- ♿ **Accessible** — ARIA labels, keyboard navigation
|
|
20
|
+
- 📱 **Mobile-friendly** — Optimized for touch devices
|
|
21
|
+
- 🎯 **TypeScript** — Full type safety
|
|
22
|
+
- 🪝 **Hook API** — For custom input implementations
|
|
23
|
+
- ⚡ **Optimized** — Tree-shaking and code splitting
|
|
24
|
+
|
|
25
|
+
## 📦 Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @desource/phone-mask-react
|
|
29
|
+
# or
|
|
30
|
+
yarn add @desource/phone-mask-react
|
|
31
|
+
# or
|
|
32
|
+
pnpm add @desource/phone-mask-react
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🚀 Quick Start
|
|
36
|
+
|
|
37
|
+
### Importing
|
|
38
|
+
|
|
39
|
+
Component mode:
|
|
40
|
+
```tsx
|
|
41
|
+
import { PhoneInput } from '@desource/phone-mask-react';
|
|
42
|
+
import '@desource/phone-mask-react/assets/lib.css'; // Import styles
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Hook mode:
|
|
46
|
+
```tsx
|
|
47
|
+
import { usePhoneMask } from '@desource/phone-mask-react';
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Component Mode
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { useState } from 'react';
|
|
54
|
+
import { PhoneInput } from '@desource/phone-mask-react';
|
|
55
|
+
import '@desource/phone-mask-react/assets/lib.css'; // Import styles
|
|
56
|
+
|
|
57
|
+
function App() {
|
|
58
|
+
const [phone, setPhone] = useState('');
|
|
59
|
+
const [isValid, setIsValid] = useState(false);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
<PhoneInput
|
|
64
|
+
value={phone}
|
|
65
|
+
onChange={setPhone}
|
|
66
|
+
onValidationChange={setIsValid}
|
|
67
|
+
country="US"
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
{isValid && <p>✓ Valid phone number</p>}
|
|
71
|
+
</>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Hook Mode
|
|
77
|
+
|
|
78
|
+
For custom input implementations:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { usePhoneMask } from '@desource/phone-mask-react';
|
|
82
|
+
|
|
83
|
+
function CustomPhoneInput() {
|
|
84
|
+
const { ref, digits, full, fullFormatted, isComplete, country, setCountry } = usePhoneMask({
|
|
85
|
+
country: 'US',
|
|
86
|
+
detect: true,
|
|
87
|
+
onChange: (phone) => {
|
|
88
|
+
console.log(phone.full, phone.digits);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div>
|
|
94
|
+
<input ref={ref} type="tel" placeholder="Phone number" />
|
|
95
|
+
<p>Formatted: {fullFormatted}</p>
|
|
96
|
+
<p>Valid: {isComplete ? 'Yes' : 'No'}</p>
|
|
97
|
+
<p>Country: {country.name}</p>
|
|
98
|
+
<button onClick={() => setCountry('GB')}>Use UK</button>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 📖 Component API
|
|
105
|
+
|
|
106
|
+
### Props
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
interface PhoneInputProps {
|
|
110
|
+
// Controlled value (digits only, without country code)
|
|
111
|
+
value?: string;
|
|
112
|
+
|
|
113
|
+
// Preselected country (ISO 3166-1 alpha-2)
|
|
114
|
+
country?: CountryKey;
|
|
115
|
+
|
|
116
|
+
// Auto-detect country from IP/locale
|
|
117
|
+
detect?: boolean; // Default: true
|
|
118
|
+
|
|
119
|
+
// Locale for country names
|
|
120
|
+
locale?: string; // Default: browser language
|
|
121
|
+
|
|
122
|
+
// Size variant
|
|
123
|
+
size?: 'compact' | 'normal' | 'large'; // Default: 'normal'
|
|
124
|
+
|
|
125
|
+
// Visual theme ("auto" | "light" | "dark")
|
|
126
|
+
theme?: 'auto' | 'light' | 'dark'; // Default: 'auto'
|
|
127
|
+
|
|
128
|
+
// Disabled state
|
|
129
|
+
disabled?: boolean; // Default: false
|
|
130
|
+
|
|
131
|
+
// Readonly state
|
|
132
|
+
readonly?: boolean; // Default: false
|
|
133
|
+
|
|
134
|
+
// Show copy button
|
|
135
|
+
showCopy?: boolean; // Default: true
|
|
136
|
+
|
|
137
|
+
// Show clear button
|
|
138
|
+
showClear?: boolean; // Default: false
|
|
139
|
+
|
|
140
|
+
// Show validation state (borders & outline)
|
|
141
|
+
withValidity?: boolean; // Default: true
|
|
142
|
+
|
|
143
|
+
// Custom search placeholder
|
|
144
|
+
searchPlaceholder?: string; // Default: 'Search country or code...'
|
|
145
|
+
|
|
146
|
+
// Custom no results text
|
|
147
|
+
noResultsText?: string; // Default: 'No countries found'
|
|
148
|
+
|
|
149
|
+
// Custom clear button label
|
|
150
|
+
clearButtonLabel?: string; // Default: 'Clear phone number'
|
|
151
|
+
|
|
152
|
+
// Dropdown menu custom CSS class
|
|
153
|
+
dropdownClass?: string;
|
|
154
|
+
|
|
155
|
+
// Disable default styles
|
|
156
|
+
disableDefaultStyles?: boolean; // Default: false
|
|
157
|
+
|
|
158
|
+
// Callback when the digits value changes.
|
|
159
|
+
// Returns only the digits without country code (e.g. '234567890')
|
|
160
|
+
onChange?: (digits: string) => void;
|
|
161
|
+
|
|
162
|
+
// Callback when the phone number changes.
|
|
163
|
+
// Provides an object with:
|
|
164
|
+
// - full: Full phone number with country code (e.g. +1234567890)
|
|
165
|
+
// - fullFormatted: Full phone number formatted according to country rules (e.g. +1 234-567-890)
|
|
166
|
+
// - digits: Only the digits of the phone number without country code (e.g. 234567890)
|
|
167
|
+
onPhoneChange?: (value: PhoneNumber) => void;
|
|
168
|
+
|
|
169
|
+
// Callback when the selected country changes
|
|
170
|
+
onCountryChange?: (country: MaskFull) => void;
|
|
171
|
+
|
|
172
|
+
// Callback when the validation state changes
|
|
173
|
+
onValidationChange?: (isValid: boolean) => void;
|
|
174
|
+
|
|
175
|
+
// Callback when the input is focused
|
|
176
|
+
onFocus?: (event: FocusEvent<HTMLInputElement>) => void;
|
|
177
|
+
|
|
178
|
+
// Callback when the input is blurred
|
|
179
|
+
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
|
|
180
|
+
|
|
181
|
+
// Callback when phone number is copied
|
|
182
|
+
onCopy?: (value: string) => void;
|
|
183
|
+
|
|
184
|
+
// Callback when input is cleared
|
|
185
|
+
onClear?: () => void;
|
|
186
|
+
|
|
187
|
+
// Render custom action buttons before default ones
|
|
188
|
+
renderActionsBefore?: () => ReactNode;
|
|
189
|
+
|
|
190
|
+
// Render custom flag icons in the country list and country selector
|
|
191
|
+
renderFlag?: (country: MaskFull) => ReactNode;
|
|
192
|
+
|
|
193
|
+
// Render custom copy button SVG
|
|
194
|
+
renderCopySvg?: (copied: boolean) => ReactNode;
|
|
195
|
+
|
|
196
|
+
// Render custom clear button SVG
|
|
197
|
+
renderClearSvg?: () => ReactNode;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Ref Methods
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
const phoneInputRef = useRef<PhoneInputRef>(null);
|
|
205
|
+
|
|
206
|
+
phoneInputRef.current?.focus(); // Focuses the input
|
|
207
|
+
phoneInputRef.current?.blur(); // Blurs the input
|
|
208
|
+
phoneInputRef.current?.clear(); // Clears the input value
|
|
209
|
+
phoneInputRef.current?.selectCountry('GB'); // Programmatically selects a country by ISO code (e.g., 'US', 'DE', 'GB')
|
|
210
|
+
phoneInputRef.current?.getFullNumber(); // Returns the full phone number with country code (e.g., +1234567890)
|
|
211
|
+
phoneInputRef.current?.getFullFormattedNumber(); // Returns the full phone number formatted according to country rules (e.g., +1 234-567-890)
|
|
212
|
+
phoneInputRef.current?.getDigits(); // Returns only the digits of the phone number without country code (e.g., 234567890)
|
|
213
|
+
phoneInputRef.current?.isValid(); // Checks if the current phone number is valid
|
|
214
|
+
phoneInputRef.current?.isComplete(); // Checks if the current phone number is complete
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## 🪝 Hook API
|
|
218
|
+
|
|
219
|
+
### Options
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
interface UsePhoneMaskOptions {
|
|
223
|
+
// Predefined country ISO code (e.g., 'US', 'DE', 'GB')
|
|
224
|
+
country?: string;
|
|
225
|
+
|
|
226
|
+
// Locale for country names (default: navigator.language)
|
|
227
|
+
locale?: string;
|
|
228
|
+
|
|
229
|
+
// Auto-detect country from IP/locale (default: false)
|
|
230
|
+
detect?: boolean;
|
|
231
|
+
|
|
232
|
+
// Value change callback
|
|
233
|
+
onChange?: (phone: PhoneNumber) => void;
|
|
234
|
+
|
|
235
|
+
// Country change callback
|
|
236
|
+
onCountryChange?: (country: MaskFull) => void;
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Return Value
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
interface UsePhoneMaskReturn {
|
|
244
|
+
ref: RefObject<HTMLInputElement>;
|
|
245
|
+
digits: string;
|
|
246
|
+
full: string;
|
|
247
|
+
fullFormatted: string;
|
|
248
|
+
isComplete: boolean;
|
|
249
|
+
isEmpty: boolean;
|
|
250
|
+
shouldShowWarn: boolean;
|
|
251
|
+
country: MaskFull;
|
|
252
|
+
setCountry: (countryCode: string) => void;
|
|
253
|
+
clear: () => void;
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## 🎨 Component Styling
|
|
258
|
+
|
|
259
|
+
### CSS Custom Properties
|
|
260
|
+
|
|
261
|
+
Customize colors via CSS variables:
|
|
262
|
+
|
|
263
|
+
```css
|
|
264
|
+
.phone-input,
|
|
265
|
+
.phone-dropdown {
|
|
266
|
+
/* Colors */
|
|
267
|
+
--pi-bg: #ffffff;
|
|
268
|
+
--pi-fg: #111827;
|
|
269
|
+
--pi-muted: #6b7280;
|
|
270
|
+
--pi-border: #e5e7eb;
|
|
271
|
+
--pi-border-hover: #d1d5db;
|
|
272
|
+
--pi-border-focus: #3b82f6;
|
|
273
|
+
--pi-focus-ring: 3px solid rgb(59 130 246 / 0.15);
|
|
274
|
+
--pi-disabled-bg: #f9fafb;
|
|
275
|
+
--pi-disabled-fg: #9ca3af;
|
|
276
|
+
/* Sizes */
|
|
277
|
+
--pi-font-size: 16px;
|
|
278
|
+
--pi-height: 44px;
|
|
279
|
+
/* Spacing */
|
|
280
|
+
--pi-padding: 12px;
|
|
281
|
+
/* Border radius */
|
|
282
|
+
--pi-radius: 8px;
|
|
283
|
+
/* Shadows */
|
|
284
|
+
--pi-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
285
|
+
--pi-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -2px rgb(0 0 0 / 0.05);
|
|
286
|
+
/* Validation */
|
|
287
|
+
--pi-warning: #f59e0b;
|
|
288
|
+
--pi-warning-light: #fbbf24;
|
|
289
|
+
--pi-success: #10b981;
|
|
290
|
+
--pi-focus-ring-warning: 3px solid rgb(245 158 11 / 0.15);
|
|
291
|
+
--pi-focus-ring-success: 3px solid rgb(16 185 129 / 0.15);
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Dark Theme
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
<PhoneInput value={phone} theme="dark" />
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Or with CSS:
|
|
302
|
+
|
|
303
|
+
```css
|
|
304
|
+
.phone-input[data-theme='dark'] {
|
|
305
|
+
--pi-bg: #1f2937;
|
|
306
|
+
--pi-fg: #f9fafb;
|
|
307
|
+
--pi-border: #374151;
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## 📚 Examples
|
|
312
|
+
|
|
313
|
+
### With Validation
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
import { useState } from 'react';
|
|
317
|
+
import { PhoneInput } from '@desource/phone-mask-react';
|
|
318
|
+
|
|
319
|
+
function Example() {
|
|
320
|
+
const [phone, setPhone] = useState('');
|
|
321
|
+
const [isValid, setIsValid] = useState(false);
|
|
322
|
+
|
|
323
|
+
return (
|
|
324
|
+
<div>
|
|
325
|
+
<PhoneInput value={phone} onChange={setPhone} onValidationChange={setIsValid} />
|
|
326
|
+
|
|
327
|
+
{isValid && <span>✓ Valid phone number</span>}
|
|
328
|
+
</div>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Auto-detect Country
|
|
334
|
+
|
|
335
|
+
```tsx
|
|
336
|
+
import { useState } from 'react';
|
|
337
|
+
import { PhoneInput } from '@desource/phone-mask-react';
|
|
338
|
+
|
|
339
|
+
function Example() {
|
|
340
|
+
const [phone, setPhone] = useState('');
|
|
341
|
+
const [detectedCountry, setDetectedCountry] = useState('');
|
|
342
|
+
|
|
343
|
+
return (
|
|
344
|
+
<>
|
|
345
|
+
<PhoneInput
|
|
346
|
+
value={phone}
|
|
347
|
+
detect
|
|
348
|
+
onChange={setPhone}
|
|
349
|
+
onCountryChange={(country) => setDetectedCountry(country.name)}
|
|
350
|
+
/>
|
|
351
|
+
|
|
352
|
+
{detectedCountry && <p>Detected: {detectedCountry}</p>}
|
|
353
|
+
</>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### With Form Libraries
|
|
359
|
+
|
|
360
|
+
#### React Hook Form
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
364
|
+
import { PhoneInput } from '@desource/phone-mask-react';
|
|
365
|
+
|
|
366
|
+
function Example() {
|
|
367
|
+
const { control } = useForm({
|
|
368
|
+
defaultValues: { phone: '' }
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
return (
|
|
372
|
+
<Controller
|
|
373
|
+
name="phone"
|
|
374
|
+
control={control}
|
|
375
|
+
render={({ field }) => (
|
|
376
|
+
<PhoneInput
|
|
377
|
+
value={field.value}
|
|
378
|
+
onChange={(digits) => field.onChange(digits)}
|
|
379
|
+
onBlur={field.onBlur}
|
|
380
|
+
/>
|
|
381
|
+
)}
|
|
382
|
+
/>
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Multiple Inputs
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
import { useState } from 'react';
|
|
391
|
+
import { PhoneInput } from '@desource/phone-mask-react';
|
|
392
|
+
|
|
393
|
+
function Example() {
|
|
394
|
+
const [form, setForm] = useState({ mobile: '', home: '', work: '' });
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<div className="form">
|
|
398
|
+
<label>
|
|
399
|
+
Mobile
|
|
400
|
+
<PhoneInput value={form.mobile} onChange={(digits) => setForm({ ...form, mobile: digits })} />
|
|
401
|
+
</label>
|
|
402
|
+
|
|
403
|
+
<label>
|
|
404
|
+
Home
|
|
405
|
+
<PhoneInput value={form.home} onChange={(digits) => setForm({ ...form, home: digits })} />
|
|
406
|
+
</label>
|
|
407
|
+
|
|
408
|
+
<label>
|
|
409
|
+
Work
|
|
410
|
+
<PhoneInput value={form.work} onChange={(digits) => setForm({ ...form, work: digits })} />
|
|
411
|
+
</label>
|
|
412
|
+
</div>
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## 🎯 Browser Support
|
|
418
|
+
|
|
419
|
+
- Chrome/Edge 90+
|
|
420
|
+
- Firefox 88+
|
|
421
|
+
- Safari 14+
|
|
422
|
+
- iOS Safari 14+
|
|
423
|
+
- Chrome Mobile
|
|
424
|
+
|
|
425
|
+
## 📦 What's Included
|
|
426
|
+
|
|
427
|
+
```
|
|
428
|
+
@desource/phone-mask-react/
|
|
429
|
+
├── dist/
|
|
430
|
+
│ ├── esm # ESM bundle + types
|
|
431
|
+
│ ├── phone-mask-react.cjs.js # CommonJS bundle
|
|
432
|
+
│ └── phone-mask-react.css # Component styles
|
|
433
|
+
├── README.md # This file
|
|
434
|
+
└── package.json # Package manifest
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## 🔗 Related
|
|
438
|
+
|
|
439
|
+
- [@desource/phone-mask](../phone-mask) — Core library
|
|
440
|
+
- [@desource/phone-mask-nuxt](../phone-mask-nuxt) — Nuxt module
|
|
441
|
+
- [@desource/phone-mask-vue](../phone-mask-vue) — Vue 3 bindings
|
|
442
|
+
|
|
443
|
+
## 📄 License
|
|
444
|
+
|
|
445
|
+
[MIT](../../LICENSE) © 2026 DeSource Labs
|
|
446
|
+
|
|
447
|
+
## 🤝 Contributing
|
|
448
|
+
|
|
449
|
+
See [Contributing Guide](../../CONTRIBUTING.md)
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
<div align="center">
|
|
454
|
+
<sub>Made with ❤️ by <a href="https://github.com/DeSource-Labs">DeSource Labs</a></sub>
|
|
455
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Ref } from 'react';
|
|
2
|
+
import type { PhoneInputProps, PhoneInputRef } from '../types';
|
|
3
|
+
type PhoneInputComponent = PhoneInputProps & {
|
|
4
|
+
ref?: Ref<PhoneInputRef>;
|
|
5
|
+
};
|
|
6
|
+
export declare const PhoneInput: {
|
|
7
|
+
({ ref, ...props }: PhoneInputComponent): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
displayName: string;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=PhoneInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhoneInput.d.ts","sourceRoot":"","sources":["../../../src/components/PhoneInput.tsx"],"names":[],"mappings":"AAAA,OAAc,EAQZ,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAYf,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAe,MAAM,UAAU,CAAC;AAS5E,KAAK,mBAAmB,GAAG,eAAe,GAAG;IAAE,GAAG,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAA;CAAE,CAAC;AAE1E,eAAO,MAAM,UAAU;wBAAuB,mBAAmB;;CAuwBhE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,UAAuB,CAAC;AAC/C,eAAO,MAAM,cAAc,UAA4E,CAAC;AACxG,eAAO,MAAM,cAAc,QAAgB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UsePhoneMaskOptions, UsePhoneMaskReturn } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* React hook for phone number masking.
|
|
4
|
+
* Provides low-level phone masking functionality for custom input implementations.
|
|
5
|
+
*/
|
|
6
|
+
export declare function usePhoneMask(options?: UsePhoneMaskOptions): UsePhoneMaskReturn;
|
|
7
|
+
//# sourceMappingURL=usePhoneMask.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePhoneMask.d.ts","sourceRoot":"","sources":["../../../src/hooks/usePhoneMask.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAe,MAAM,UAAU,CAAC;AAyBrF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,kBAAkB,CAwTlF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { countPlaceholders, formatDigitsWithMap, pickMaskVariant, removeCountryCodePrefix, toArray } from '@desource/phone-mask';
|
|
2
|
+
export { PhoneInput } from './components/PhoneInput';
|
|
3
|
+
export { usePhoneMask } from './hooks/usePhoneMask';
|
|
4
|
+
export type { PhoneInputProps, PhoneInputRef, PhoneNumber, UsePhoneMaskOptions, UsePhoneMaskReturn, Size as PhoneInputSize, Theme as PhoneInputTheme } from './types';
|
|
5
|
+
export type { CountryKey as PCountryKey, MaskBase as PMaskBase, MaskBaseMap as PMaskBaseMap, Mask as PMask, MaskMap as PMaskMap, MaskWithFlag as PMaskWithFlag, MaskWithFlagMap as PMaskWithFlagMap, MaskFull as PMaskFull, MaskFullMap as PMaskFullMap } from '@desource/phone-mask';
|
|
6
|
+
export declare const PMaskHelpers: {
|
|
7
|
+
getFlagEmoji: (cc: string) => string;
|
|
8
|
+
countPlaceholders: typeof countPlaceholders;
|
|
9
|
+
formatDigitsWithMap: typeof formatDigitsWithMap;
|
|
10
|
+
pickMaskVariant: typeof pickMaskVariant;
|
|
11
|
+
removeCountryCodePrefix: typeof removeCountryCodePrefix;
|
|
12
|
+
toArray: typeof toArray;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACvB,OAAO,EACR,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,IAAI,IAAI,cAAc,EACtB,KAAK,IAAI,eAAe,EACzB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,UAAU,IAAI,WAAW,EACzB,QAAQ,IAAI,SAAS,EACrB,WAAW,IAAI,YAAY,EAC3B,IAAI,IAAI,KAAK,EACb,OAAO,IAAI,QAAQ,EACnB,YAAY,IAAI,aAAa,EAC7B,eAAe,IAAI,gBAAgB,EACnC,QAAQ,IAAI,SAAS,EACrB,WAAW,IAAI,YAAY,EAC5B,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,YAAY;;;;;;;CAOxB,CAAC"}
|