@superdispatch/phones 0.25.2 → 0.26.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.
@@ -19,13 +19,11 @@ var DEFAULT_COUNTRY = 'US';
19
19
  var COUNTRIES = [];
20
20
  var COUNTRY_CODE_MAP = /*#__PURE__*/new Map();
21
21
  var COUNTRY_NAME_MAP = /*#__PURE__*/new Map();
22
-
23
22
  for (var [country, code, name] of COUNTRY_CODE_METADATA) {
24
23
  COUNTRIES.push(country);
25
24
  COUNTRY_CODE_MAP.set(country, code);
26
25
  COUNTRY_NAME_MAP.set(country, name);
27
26
  }
28
-
29
27
  function listCountries() {
30
28
  return COUNTRIES;
31
29
  }
@@ -46,9 +44,14 @@ var loadError;
46
44
  var loadedAPN;
47
45
  function loadAPN() {
48
46
  return Promise.resolve().then(() => require('awesome-phonenumber')).then(apn => {
49
- loadedAPN = apn.default;
47
+ loadedAPN = {
48
+ parsePhoneNumber: apn.parsePhoneNumber,
49
+ getAsYouType: apn.getAsYouType,
50
+ getExample: apn.getExample
51
+ };
50
52
  return loadedAPN;
51
53
  }, error => {
54
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
52
55
  loadError = error;
53
56
  throw error;
54
57
  });
@@ -57,95 +60,78 @@ function getAPN() {
57
60
  if (loadError) {
58
61
  throw loadError;
59
62
  }
60
-
61
63
  if (!loadedAPN) {
62
64
  // eslint-disable-next-line @typescript-eslint/no-throw-literal
63
65
  throw loadAPN();
64
66
  }
65
-
66
67
  return loadedAPN;
67
68
  }
68
69
 
69
70
  var PLUS_SIGN = '+';
70
71
  var NON_PHONE_SYMBOLS_PATTERN = /[^+\d]/g;
71
72
  var PHONE_PATTERN = /^\+?\d+/g;
72
-
73
73
  function getPrefix(country) {
74
74
  return PLUS_SIGN + String(getCountryCode(toCountryISO(country)));
75
75
  }
76
-
77
76
  function trim(input) {
78
77
  return typeof input == 'string' ? input.trim() : undefined;
79
78
  }
80
-
81
79
  function normalize(input) {
82
80
  if (typeof input == 'string') {
83
81
  var matches = input.replace(NON_PHONE_SYMBOLS_PATTERN, '').match(PHONE_PATTERN);
84
82
  if (matches !== null && matches !== void 0 && matches[0]) return matches[0];
85
83
  }
86
-
87
84
  return '';
88
85
  }
89
-
90
86
  function normalizeNationalNumber(country, input) {
91
87
  var phone = normalize(input);
92
88
  var prefix = getPrefix(country);
93
-
94
89
  if (phone.startsWith(PLUS_SIGN)) {
95
90
  return phone.slice(prefix.length);
96
91
  }
97
-
98
92
  return phone;
99
93
  }
100
-
101
94
  class PhoneService {
102
95
  static load() {
103
96
  return loadAPN().then(APN => new PhoneService(APN));
104
97
  }
105
-
106
98
  static checkPossibility(input) {
107
99
  return this.load().then(phoneService => phoneService.checkPossibility(input));
108
100
  }
109
-
110
101
  static validate(input, rules) {
111
102
  return this.load().then(phoneService => phoneService.validate(input, rules));
112
103
  }
113
-
114
104
  constructor(APN) {
115
105
  this.APN = APN;
116
106
  }
117
-
118
107
  createAPN(phone, country) {
119
108
  var asYouType = this.APN.getAsYouType(toCountryISO(country));
120
109
  asYouType.reset(normalize(phone));
121
110
  return asYouType.getPhoneNumber();
122
111
  }
123
-
124
112
  getJSON(phone, country) {
125
- return this.createAPN(phone, country).toJSON();
113
+ return this.createAPN(phone, country);
126
114
  }
127
-
128
115
  checkPossibility(input) {
129
116
  var phone = trim(input);
130
-
131
117
  if (!phone) {
132
118
  return 'unknown';
133
119
  }
134
-
135
- var apn = phone.startsWith(PLUS_SIGN) ? new this.APN(phone) : new this.APN(phone, DEFAULT_COUNTRY);
120
+ var apn = phone.startsWith(PLUS_SIGN) ? this.APN.parsePhoneNumber(phone) : this.APN.parsePhoneNumber(phone, {
121
+ regionCode: DEFAULT_COUNTRY
122
+ });
136
123
  var {
137
124
  valid,
138
125
  possible,
139
126
  possibility
140
- } = apn.toJSON(); // Avoid false positive short phone numbers.
127
+ } = apn;
141
128
 
129
+ // Avoid false positive short phone numbers.
142
130
  if (!valid && possible) {
143
131
  return 'invalid-number';
144
132
  }
145
-
146
133
  return possibility;
147
134
  }
148
-
149
135
  validate(input) {
150
136
  var {
151
137
  required,
@@ -155,40 +141,30 @@ class PhoneService {
155
141
  tooShortMessage = 'Phone number is too short'
156
142
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
157
143
  var phone = trim(input);
158
-
159
144
  if (!phone) {
160
145
  if (required) {
161
146
  return requiredMessage;
162
147
  }
163
-
164
148
  return undefined;
165
149
  }
166
-
167
150
  switch (this.checkPossibility(phone)) {
168
151
  case 'is-possible':
169
152
  return undefined;
170
-
171
153
  case 'too-long':
172
154
  return tooLongMessage;
173
-
174
155
  case 'too-short':
175
156
  return tooShortMessage;
176
157
  }
177
-
178
158
  return invalidMessage;
179
159
  }
180
-
181
160
  deletePrefix(phone, country) {
182
161
  var prefix = getPrefix(country);
183
-
184
162
  if (phone.startsWith(PLUS_SIGN)) {
185
163
  var subNumber = phone.slice(prefix.length);
186
164
  return trim(subNumber);
187
165
  }
188
-
189
166
  return phone;
190
167
  }
191
-
192
168
  getInfo(phone) {
193
169
  var {
194
170
  regionCode,
@@ -199,82 +175,70 @@ class PhoneService {
199
175
  } = this.getJSON(phone);
200
176
  var nationalNumber = '';
201
177
  var country = toCountryISO(regionCode);
202
-
203
178
  if (!internationalNumber) {
204
179
  nationalNumber = normalizeNationalNumber(country, input);
205
180
  } else {
206
181
  nationalNumber = this.deletePrefix(internationalNumber, country);
207
182
  }
208
-
209
183
  return {
210
184
  country,
211
185
  nationalNumber
212
186
  };
213
187
  }
214
-
215
188
  format(input) {
189
+ var _apn$number;
216
190
  var {
217
191
  fallback = '',
218
192
  format = 'e164',
219
193
  country: countryOption
220
194
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
221
195
  var phone = normalize(input);
222
-
223
196
  if (!phone) {
224
197
  return fallback;
225
198
  }
226
-
227
- var apn = this.createAPN(phone, countryOption);
228
- var country = countryOption || toCountryISO(apn.getRegionCode());
229
- var formatted = format === 'national' ? this.formatNationalNumber(apn, country) : apn.getNumber(format);
230
-
199
+ var apn = this.APN.parsePhoneNumber(phone, {
200
+ regionCode: countryOption
201
+ });
202
+ var country = countryOption || toCountryISO(apn.regionCode);
203
+ var international = (_apn$number = apn.number) === null || _apn$number === void 0 ? void 0 : _apn$number.international;
204
+ var formattedNumber = apn.number ? apn.number[format] : '';
205
+ var {
206
+ regionCode
207
+ } = apn;
208
+ var formatted = format === 'national' ? this.formatNationalNumber(country, international) : formattedNumber;
231
209
  if (!formatted) {
232
- return this.customFormat(apn, phone, format);
210
+ return this.customFormat(phone, format, regionCode);
233
211
  }
234
-
235
212
  return formatted;
236
213
  }
237
-
238
- formatNationalNumber(apn, country) {
239
- var internationalNumber = apn.getNumber('international');
240
-
214
+ formatNationalNumber(country, internationalNumber) {
241
215
  if (!internationalNumber) {
242
216
  return undefined;
243
217
  }
244
-
245
218
  return this.deletePrefix(internationalNumber, country);
246
219
  }
247
-
248
- customFormat(apn, phone, format) {
220
+ customFormat(phone, format, regionCode) {
249
221
  var formatted = '';
250
- var country = toCountryISO(apn.getRegionCode());
222
+ var country = toCountryISO(regionCode);
251
223
  var nationalNumber = normalizeNationalNumber(country, phone);
252
-
253
224
  if (format === 'national') {
254
225
  return nationalNumber;
255
226
  }
256
-
257
227
  var prefix = '';
258
228
  var separator = '';
259
-
260
229
  if (format === 'rfc3966') {
261
230
  prefix = 'tel:';
262
231
  separator = '-';
263
232
  }
264
-
265
233
  if (format === 'international') {
266
234
  separator = ' ';
267
235
  }
268
-
269
236
  formatted = prefix + getPrefix(country);
270
-
271
237
  if (nationalNumber) {
272
238
  formatted += separator + nationalNumber;
273
239
  }
274
-
275
240
  return formatted;
276
241
  }
277
-
278
242
  }
279
243
  function usePhoneService() {
280
244
  var APN = getAPN();
@@ -292,7 +256,6 @@ function useFormattedPhoneNumber(input) {
292
256
  if (phoneService.checkPossibility(input) !== 'is-possible') {
293
257
  return fallback;
294
258
  }
295
-
296
259
  return phoneService.format(input, {
297
260
  format,
298
261
  country,
@@ -312,14 +275,12 @@ var useStyles = /*#__PURE__*/styles.makeStyles(theme => ({
312
275
  });
313
276
  var PhoneFieldFlag = /*#__PURE__*/react.forwardRef((_ref, ref) => {
314
277
  var {
315
- country,
316
- alt = country,
317
- className
318
- } = _ref,
319
- props = _objectWithoutProperties(_ref, _excluded);
320
-
278
+ country,
279
+ alt = country,
280
+ className
281
+ } = _ref,
282
+ props = _objectWithoutProperties(_ref, _excluded);
321
283
  var styles = useStyles();
322
-
323
284
  if (country === 'AC' || country === 'BQ' || country === 'EH' || country === 'TA') {
324
285
  return /*#__PURE__*/jsxRuntime.jsx(core.Typography, {
325
286
  ref: ref,
@@ -331,7 +292,6 @@ var PhoneFieldFlag = /*#__PURE__*/react.forwardRef((_ref, ref) => {
331
292
  children: country
332
293
  });
333
294
  }
334
-
335
295
  return /*#__PURE__*/jsxRuntime.jsx("img", _objectSpread(_objectSpread({}, props), {}, {
336
296
  alt: alt,
337
297
  ref: ref,
@@ -342,7 +302,7 @@ var PhoneFieldFlag = /*#__PURE__*/react.forwardRef((_ref, ref) => {
342
302
  if (process.env.NODE_ENV !== "production") PhoneFieldFlag.displayName = "PhoneFieldFlag";
343
303
 
344
304
  var _excluded$1 = ["country", "classes"],
345
- _excluded2 = ["flag"];
305
+ _excluded2 = ["flag"];
346
306
  var useStyles$1 = /*#__PURE__*/styles.makeStyles(theme => ({
347
307
  dense: {},
348
308
  gutters: {},
@@ -356,19 +316,17 @@ var useStyles$1 = /*#__PURE__*/styles.makeStyles(theme => ({
356
316
  });
357
317
  var PhoneFieldMenuItem = /*#__PURE__*/react.forwardRef((_ref, ref) => {
358
318
  var {
359
- country,
360
- classes
361
- } = _ref,
362
- props = _objectWithoutProperties(_ref, _excluded$1);
363
-
319
+ country,
320
+ classes
321
+ } = _ref,
322
+ props = _objectWithoutProperties(_ref, _excluded$1);
364
323
  var _useStyles = useStyles$1({
365
- classes
366
- }),
367
- {
368
- flag: flagClassName
369
- } = _useStyles,
370
- styles = _objectWithoutProperties(_useStyles, _excluded2);
371
-
324
+ classes
325
+ }),
326
+ {
327
+ flag: flagClassName
328
+ } = _useStyles,
329
+ styles = _objectWithoutProperties(_useStyles, _excluded2);
372
330
  var countryCode = react.useMemo(() => getCountryCode(country), [country]);
373
331
  return /*#__PURE__*/jsxRuntime.jsxs(core.MenuItem, _objectSpread(_objectSpread({}, props), {}, {
374
332
  ref: ref,
@@ -472,21 +430,18 @@ var PhoneFieldStartAdornment = /*#__PURE__*/react.forwardRef((_ref, ref) => {
472
430
  if (process.env.NODE_ENV !== "production") PhoneFieldStartAdornment.displayName = "PhoneFieldStartAdornment";
473
431
 
474
432
  var _excluded$2 = ["value", "onBlur", "onFocus", "onChange"],
475
- _excluded2$1 = ["label", "fullWidth", "helperText", "suspenseFallback"];
476
-
433
+ _excluded2$1 = ["label", "fullWidth", "helperText", "suspenseFallback"];
477
434
  function normalizeValue(value) {
478
435
  return typeof value === 'string' ? value : '';
479
436
  }
480
-
481
437
  var PhoneField = /*#__PURE__*/react.forwardRef((_ref, ref) => {
482
438
  var {
483
- value: valueProp,
484
- onBlur: _onBlur,
485
- onFocus: _onFocus,
486
- onChange: _onChange
487
- } = _ref,
488
- props = _objectWithoutProperties(_ref, _excluded$2);
489
-
439
+ value: valueProp,
440
+ onBlur: _onBlur,
441
+ onFocus: _onFocus,
442
+ onChange: _onChange
443
+ } = _ref,
444
+ props = _objectWithoutProperties(_ref, _excluded$2);
490
445
  var rootRef = react.useRef(null);
491
446
  var inputRef = react.useRef(null);
492
447
  var [menuAnchor, setMenuAnchor] = react.useState(null);
@@ -499,8 +454,10 @@ var PhoneField = /*#__PURE__*/react.forwardRef((_ref, ref) => {
499
454
  country,
500
455
  nationalNumber
501
456
  }, setValue] = react.useState(() => createState(value));
502
- var placeholder = react.useMemo(() => phoneService.APN.getExample(country).getNumber('international'), [country, phoneService.APN]);
503
-
457
+ var placeholder = react.useMemo(() => {
458
+ var _phoneService$APN$get;
459
+ return ((_phoneService$APN$get = phoneService.APN.getExample(country).number) === null || _phoneService$APN$get === void 0 ? void 0 : _phoneService$APN$get.international) || '';
460
+ }, [country, phoneService.APN]);
504
461
  function handleChange(fn, nextCountry, nextNationalNumber) {
505
462
  if (fn) {
506
463
  var nextValue = phoneService.format(nextNationalNumber, {
@@ -514,14 +471,12 @@ var PhoneField = /*#__PURE__*/react.forwardRef((_ref, ref) => {
514
471
  fn(nextValue);
515
472
  }
516
473
  }
517
-
518
474
  function handleChangeEvent(fn, _ref2) {
519
475
  var {
520
476
  target: {
521
477
  value: nextValue
522
478
  }
523
479
  } = _ref2;
524
-
525
480
  if (fn) {
526
481
  handleChange(fn, country, phoneService.format(nextValue, {
527
482
  country,
@@ -529,9 +484,9 @@ var PhoneField = /*#__PURE__*/react.forwardRef((_ref, ref) => {
529
484
  }));
530
485
  }
531
486
  }
532
-
533
487
  react.useEffect(() => {
534
- setValue(prev => // Ignore `props.value` changes when they were performed from inside.
488
+ setValue(prev =>
489
+ // Ignore `props.value` changes when they were performed from inside.
535
490
  prev.value === value ? prev : createState(value));
536
491
  }, [value, createState]);
537
492
  return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
@@ -566,11 +521,10 @@ var PhoneField = /*#__PURE__*/react.forwardRef((_ref, ref) => {
566
521
  country: country,
567
522
  isExpanded: !!menuAnchor,
568
523
  onClick: () => {
569
- var _inputRef$current; // `FocusTrap` inside of `Menu` will restore focus to
524
+ var _inputRef$current;
525
+ // `FocusTrap` inside of `Menu` will restore focus to
570
526
  // the last focused element. We want to manually focus input
571
527
  // to trick the `FocusTrap`.
572
-
573
-
574
528
  (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
575
529
  setMenuAnchor(rootRef.current);
576
530
  }
@@ -582,19 +536,18 @@ var PhoneField = /*#__PURE__*/react.forwardRef((_ref, ref) => {
582
536
  if (process.env.NODE_ENV !== "production") PhoneField.displayName = "PhoneField";
583
537
  var SuspendedPhoneField = /*#__PURE__*/react.forwardRef((_ref3, ref) => {
584
538
  var {
585
- label,
586
- fullWidth,
587
- helperText,
588
- suspenseFallback = /*#__PURE__*/jsxRuntime.jsx(core.TextField, {
589
- disabled: true,
590
- label: label,
591
- fullWidth: fullWidth,
592
- helperText: helperText,
593
- placeholder: "Loading\u2026"
594
- })
595
- } = _ref3,
596
- props = _objectWithoutProperties(_ref3, _excluded2$1);
597
-
539
+ label,
540
+ fullWidth,
541
+ helperText,
542
+ suspenseFallback = /*#__PURE__*/jsxRuntime.jsx(core.TextField, {
543
+ disabled: true,
544
+ label: label,
545
+ fullWidth: fullWidth,
546
+ helperText: helperText,
547
+ placeholder: "Loading\u2026"
548
+ })
549
+ } = _ref3,
550
+ props = _objectWithoutProperties(_ref3, _excluded2$1);
598
551
  return /*#__PURE__*/jsxRuntime.jsx(react.Suspense, {
599
552
  fallback: suspenseFallback,
600
553
  children: /*#__PURE__*/jsxRuntime.jsx(PhoneField, _objectSpread(_objectSpread({}, props), {}, {
@@ -608,22 +561,20 @@ var SuspendedPhoneField = /*#__PURE__*/react.forwardRef((_ref3, ref) => {
608
561
  if (process.env.NODE_ENV !== "production") SuspendedPhoneField.displayName = "SuspendedPhoneField";
609
562
 
610
563
  var _excluded$3 = ["phone", "country", "fallback", "format"],
611
- _excluded2$2 = ["suspenseFallback"];
564
+ _excluded2$2 = ["suspenseFallback"];
612
565
  var PhoneLink = /*#__PURE__*/react.forwardRef((_ref, ref) => {
613
566
  var {
614
- phone,
615
- country,
616
- fallback,
617
- format = 'international'
618
- } = _ref,
619
- props = _objectWithoutProperties(_ref, _excluded$3);
620
-
567
+ phone,
568
+ country,
569
+ fallback,
570
+ format = 'international'
571
+ } = _ref,
572
+ props = _objectWithoutProperties(_ref, _excluded$3);
621
573
  var service = usePhoneService();
622
574
  var [text, href] = react.useMemo(() => {
623
575
  if (service.checkPossibility(phone) !== 'is-possible') {
624
576
  return [undefined, undefined];
625
577
  }
626
-
627
578
  return [service.format(phone, {
628
579
  country,
629
580
  format
@@ -641,10 +592,9 @@ var PhoneLink = /*#__PURE__*/react.forwardRef((_ref, ref) => {
641
592
  if (process.env.NODE_ENV !== "production") PhoneLink.displayName = "PhoneLink";
642
593
  var SuspendedPhoneLink = /*#__PURE__*/react.forwardRef((_ref2, ref) => {
643
594
  var {
644
- suspenseFallback = null
645
- } = _ref2,
646
- props = _objectWithoutProperties(_ref2, _excluded2$2);
647
-
595
+ suspenseFallback = null
596
+ } = _ref2,
597
+ props = _objectWithoutProperties(_ref2, _excluded2$2);
648
598
  return /*#__PURE__*/jsxRuntime.jsx(react.Suspense, {
649
599
  fallback: suspenseFallback,
650
600
  children: /*#__PURE__*/jsxRuntime.jsx(PhoneLink, _objectSpread(_objectSpread({}, props), {}, {
@@ -670,10 +620,9 @@ function PhoneText(_ref) {
670
620
  }
671
621
  function SuspendedPhoneText(_ref2) {
672
622
  var {
673
- suspenseFallback = null
674
- } = _ref2,
675
- props = _objectWithoutProperties(_ref2, _excluded$4);
676
-
623
+ suspenseFallback = null
624
+ } = _ref2,
625
+ props = _objectWithoutProperties(_ref2, _excluded$4);
677
626
  return /*#__PURE__*/jsxRuntime.jsx(react.Suspense, {
678
627
  fallback: suspenseFallback,
679
628
  children: /*#__PURE__*/jsxRuntime.jsx(PhoneText, _objectSpread({}, props))