@hanzo/react 0.1.2 → 1.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.
Files changed (52) hide show
  1. package/README.md +317 -53
  2. package/dist/index.d.mts +255 -0
  3. package/dist/index.d.ts +255 -0
  4. package/dist/index.js +548 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +539 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +84 -91
  9. package/src/components/HanzoProvider.test.tsx +346 -0
  10. package/src/components/HanzoProvider.tsx +508 -0
  11. package/src/hooks/index.ts +39 -0
  12. package/src/hooks/types.ts +162 -0
  13. package/src/hooks/useAuth.ts +0 -0
  14. package/src/hooks/useComponent.ts +0 -0
  15. package/src/hooks/useGenerativeUI.ts +0 -0
  16. package/src/hooks/useMCP.ts +0 -0
  17. package/src/hooks/useMessage.ts +105 -0
  18. package/src/hooks/useModelConfig.ts +0 -0
  19. package/src/hooks/useStreaming.ts +161 -0
  20. package/src/hooks/useSuggestions.ts +0 -0
  21. package/src/hooks/useThread.ts +0 -0
  22. package/src/hooks/useTool.ts +0 -0
  23. package/src/index.ts +40 -0
  24. package/src/types/index.ts +25 -0
  25. package/src/utils/cn.ts +6 -0
  26. package/src/utils/id.ts +6 -0
  27. package/src/utils/stream.ts +33 -0
  28. package/LICENSE +0 -21
  29. package/dist/index.cjs.js +0 -15755
  30. package/dist/index.cjs.js.map +0 -1
  31. package/dist/index.css +0 -789
  32. package/dist/index.esm.js +0 -15736
  33. package/dist/index.esm.js.map +0 -1
  34. package/dist/index.umd.js +0 -15756
  35. package/dist/index.umd.js.map +0 -1
  36. package/src/controls/.DS_Store +0 -0
  37. package/src/controls/MUICheckbox.js +0 -108
  38. package/src/controls/MUIKeyboardDatePicker.js +0 -90
  39. package/src/controls/MUIPhone.js +0 -33
  40. package/src/controls/MUISwitch.js +0 -107
  41. package/src/controls/MUIText.js +0 -298
  42. package/src/controls/NumericFormats.js +0 -57
  43. package/src/controls/control.js +0 -148
  44. package/src/controls/index.js +0 -7
  45. package/src/controls/material-ui-phone-number/components/Item.js +0 -66
  46. package/src/controls/material-ui-phone-number/components/flags.css +0 -789
  47. package/src/controls/material-ui-phone-number/components/index.js +0 -884
  48. package/src/controls/material-ui-phone-number/components/polyfills.js +0 -82
  49. package/src/controls/material-ui-phone-number/country_data.js +0 -1536
  50. package/src/controls/material-ui-phone-number/index.js +0 -3
  51. package/src/index.js +0 -1
  52. /package/src/{core/index.js → hooks/useAttachments.ts} +0 -0
@@ -1,884 +0,0 @@
1
- import React, { Component } from 'react'
2
- import PropTypes from 'prop-types'
3
- import classNames from 'classnames'
4
- import TextField from '@material-ui/core/TextField'
5
- import InputAdornment from '@material-ui/core/InputAdornment'
6
- import Button from '@material-ui/core/Button'
7
- import Menu from '@material-ui/core/Menu'
8
- import Divider from '@material-ui/core/Divider'
9
- import NativeSelect from '@material-ui/core/NativeSelect'
10
- import withStyles from '@material-ui/core/styles/withStyles'
11
- import memoize from 'fast-memoize'
12
- import countryData from '../country_data'
13
- import Item from './Item'
14
-
15
- import { isString, debounce } from '@hanzo/utils'
16
-
17
- import './polyfills'
18
-
19
- const head = (array) => {
20
- let [h, ...t] = array
21
- return h
22
- }
23
-
24
- const tail = (array) => {
25
- let [h, ...t] = array
26
- return t
27
- }
28
-
29
- const styles = () => ({
30
- flagButton: {
31
- minWidth: 30,
32
- padding: 0,
33
- height: 30,
34
- },
35
- native: {
36
- width: 30,
37
- height: 30,
38
- padding: 8,
39
- },
40
- nativeRoot: {
41
- padding: 0,
42
-
43
- '& + svg': {
44
- display: 'none',
45
- },
46
- },
47
- nativeSelect: {
48
- padding: 0,
49
- lineHeight: 0,
50
- height: 11,
51
- },
52
- positionStart: {
53
- position: 'relative',
54
- },
55
- })
56
-
57
- class MaterialUiPhoneNumber extends Component {
58
- flags = {}
59
-
60
- guessSelectedCountry = memoize((inputNumber, onlyCountries, defaultCountry) => {
61
- const secondBestGuess = onlyCountries.find((c) => c.iso2 === defaultCountry ) || {}
62
- if (inputNumber.trim() === '') return secondBestGuess
63
-
64
- const bestGuess = onlyCountries.reduce((selectedCountry, country) => {
65
- if (inputNumber.startsWith(country.dialCode)) {
66
- if (country.dialCode.length > selectedCountry.dialCode.length) {
67
- return country
68
- }
69
- if (country.dialCode.length === selectedCountry.dialCode.length && country.priority < selectedCountry.priority) {
70
- return country
71
- }
72
- }
73
- return selectedCountry
74
- }, { dialCode: '', priority: 10001 }, this)
75
-
76
- if (!bestGuess.name) return secondBestGuess
77
- return bestGuess
78
- })
79
-
80
- constructor(props) {
81
- super(props)
82
- let filteredCountries = countryData.allCountries
83
-
84
- if (props.disableAreaCodes) filteredCountries = this.deleteAreaCodes(filteredCountries)
85
- if (props.regions) filteredCountries = this.filterRegions(props.regions, filteredCountries)
86
-
87
- const onlyCountries = this.excludeCountries(
88
- this.getOnlyCountries(props.onlyCountries, filteredCountries), props.excludeCountries,
89
- )
90
-
91
- const preferredCountries = filteredCountries.filter((country) => props.preferredCountries.some((preferredCountry) => preferredCountry === country.iso2))
92
-
93
- const inputNumber = props.value || ''
94
-
95
- let countryGuess
96
- if (inputNumber.length > 1) {
97
- // Country detect by value field
98
- countryGuess = this.guessSelectedCountry(inputNumber.replace(/\D/g, '').substring(0, 6), onlyCountries, props.defaultCountry) || 0
99
- } else if (props.defaultCountry) {
100
- // Default country
101
- countryGuess = onlyCountries.find((c) => c.iso2 == props.defaultCountry) || 0
102
- } else {
103
- // Empty params
104
- countryGuess = 0
105
- }
106
-
107
- const countryGuessIndex = countryData.allCountries.findIndex((c) => c.iso2 === countryGuess)
108
- const dialCode = (
109
- inputNumber.length < 2
110
- && countryGuess
111
- && !inputNumber.replace(/\D/g, '').startsWith(countryGuess.dialCode)
112
- ) ? countryGuess.dialCode : ''
113
-
114
- const formattedNumber = (inputNumber === '' && countryGuess === 0) ? ''
115
- : this.formatNumber(
116
- (props.disableCountryCode ? '' : dialCode) + inputNumber.replace(/\D/g, ''),
117
- countryGuess.name ? countryGuess.format : undefined,
118
- )
119
-
120
- this.state = {
121
- formattedNumber,
122
- placeholder: props.placeholder,
123
- onlyCountries,
124
- preferredCountries,
125
- defaultCountry: props.defaultCountry,
126
- selectedCountry: countryGuess,
127
- highlightCountryIndex: countryGuessIndex,
128
- queryString: '',
129
- freezeSelection: false,
130
- debouncedQueryStringSearcher: debounce(this.searchCountry, 100),
131
- anchorEl: null,
132
- }
133
- }
134
-
135
- componentDidMount() {
136
- if (document.addEventListener) {
137
- document.addEventListener('keydown', this.handleKeydown)
138
- }
139
- }
140
-
141
- componentDidUpdate({ value: prevValue }) {
142
- const { defaultCountry: prevDefaultCountry, formattedNumber } = this.state
143
- const { defaultCountry, value } = this.props
144
-
145
- if (defaultCountry && defaultCountry !== prevDefaultCountry) {
146
- this.updateDefaultCountry(defaultCountry)
147
- }
148
-
149
- if (typeof value === 'string' && value !== prevValue && value !== formattedNumber) {
150
- this.updateFormattedNumber(value)
151
- }
152
- }
153
-
154
- componentWillUnmount() {
155
- if (document.removeEventListener) {
156
- document.removeEventListener('keydown', this.handleKeydown)
157
- }
158
- }
159
-
160
- getProbableCandidate = memoize((queryString) => {
161
- if (!queryString || queryString.length === 0) {
162
- return null
163
- }
164
-
165
- const { onlyCountries } = this.state
166
-
167
- // don't include the preferred countries in search
168
- const probableCountries = onlyCountries.filter((country) => country.name.toLowerCase().startsWith(queryString.toLowerCase()), this)
169
- return probableCountries[0]
170
- })
171
-
172
- getOnlyCountries = (onlyCountriesArray, filteredCountries) => {
173
- if (onlyCountriesArray.length === 0) return filteredCountries
174
-
175
- return filteredCountries.filter((country) => onlyCountriesArray.some((element) => element === country.iso2))
176
- }
177
-
178
- excludeCountries = (selectedCountries, excludedCountries) => {
179
- if (excludedCountries.length === 0) {
180
- return selectedCountries
181
- }
182
- return selectedCountries.filter((selCountry) => !excludedCountries.includes(selCountry.iso2))
183
- }
184
-
185
- filterRegions = (regions, filteredCountries) => {
186
- if (typeof regions === 'string') {
187
- const region = regions
188
- return filteredCountries.filter((country) => country.regions.some((element) => element === region))
189
- }
190
-
191
- return filteredCountries.filter((country) => {
192
- const matches = regions.map((region) => country.regions.some((element) => element === region))
193
- return matches.some((el) => el)
194
- })
195
- }
196
-
197
- // Countries array methods
198
- deleteAreaCodes = (filteredCountries) => filteredCountries.filter((country) => country.isAreaCode !== true)
199
-
200
- // Hooks for updated props
201
- updateDefaultCountry = (country) => {
202
- const { onlyCountries } = this.state
203
- const { disableCountryCode } = this.props
204
-
205
- const newSelectedCountry = onlyCountries.find((c) => c.iso2 === country )
206
-
207
- this.setState({
208
- defaultCountry: country,
209
- selectedCountry: newSelectedCountry,
210
- formattedNumber: disableCountryCode ? '' : `+${newSelectedCountry.dialCode}`,
211
- })
212
- }
213
-
214
- // View methods
215
- scrollTo = (country) => {
216
- if (!country) { return }
217
-
218
- const container = this.dropdownContainerRef
219
-
220
- if (!container || !document.body) { return }
221
- container.scrollTop = country.offsetTop
222
- }
223
-
224
- formatNumber = (text, patternArg) => {
225
- const { disableCountryCode, enableLongNumbers, autoFormat } = this.props
226
-
227
- let pattern
228
- if (disableCountryCode && patternArg) {
229
- pattern = patternArg.split(' ')
230
- pattern.shift()
231
- pattern = pattern.join(' ')
232
- } else {
233
- pattern = patternArg
234
- }
235
-
236
- if (!text || text.length === 0) {
237
- return disableCountryCode ? '' : '+'
238
- }
239
-
240
- // for all strings with length less than 3, just return it (1, 2 etc.)
241
- // also return the same text if the selected country has no fixed format
242
- if ((text && text.length < 2) || !pattern || !autoFormat) {
243
- return disableCountryCode ? text : `+${text}`
244
- }
245
-
246
- const formattedObject = pattern.split('').reduce((acc, character) => {
247
- if (acc.remainingText.length === 0) {
248
- return acc
249
- }
250
-
251
- if (character !== '.') {
252
- return {
253
- formattedText: acc.formattedText + character,
254
- remainingText: acc.remainingText,
255
- }
256
- }
257
-
258
- return {
259
- formattedText: acc.formattedText + head(acc.remainingText),
260
- remainingText: tail(acc.remainingText),
261
- }
262
- }, {
263
- formattedText: '',
264
- remainingText: text.split(''),
265
- })
266
-
267
- let formattedNumber
268
- if (enableLongNumbers) {
269
- formattedNumber = formattedObject.formattedText + formattedObject.remainingText.join('')
270
- } else {
271
- formattedNumber = formattedObject.formattedText
272
- }
273
-
274
- // Always close brackets
275
- if (formattedNumber.includes('(') && !formattedNumber.includes(')')) formattedNumber += ')'
276
- return formattedNumber
277
- }
278
-
279
- // Put the cursor to the end of the input (usually after a focus event)
280
- cursorToEnd = () => {
281
- const { isModernBrowser } = this.props
282
-
283
- const input = this.inputRef
284
- input.focus()
285
- if (isModernBrowser) {
286
- const len = input.value.length
287
- input.setSelectionRange(len, len)
288
- }
289
- }
290
-
291
- getElement = (index) => this.flags[`flag_no_${index}`]
292
-
293
- // return country data from state
294
- getCountryData = () => {
295
- const { selectedCountry } = this.state
296
-
297
- if (!selectedCountry) return {}
298
-
299
- return {
300
- name: selectedCountry.name || '',
301
- dialCode: selectedCountry.dialCode || '',
302
- countryCode: selectedCountry.iso2 || '',
303
- }
304
- }
305
-
306
- handleFlagDropdownClick = () => {
307
- const {
308
- anchorEl, selectedCountry, preferredCountries, onlyCountries,
309
- } = this.state
310
- const { disabled } = this.props
311
-
312
- if (!anchorEl && disabled) return
313
-
314
- const highlightCountryIndex = preferredCountries.includes(selectedCountry)
315
- ? preferredCountries.findIndex((c) => { c.iso2 === selectedCountry.iso2 })
316
- : onlyCountries.findIndex((c) => { c.iso2 === selectedCountry.iso2 })
317
-
318
- if (preferredCountries.includes(selectedCountry)) {
319
- this.setState({
320
- highlightCountryIndex,
321
- }, () => {
322
- if (anchorEl) {
323
- this.scrollTo(this.getElement(highlightCountryIndex))
324
- }
325
- })
326
- } else {
327
- this.setState({
328
- highlightCountryIndex,
329
- }, () => {
330
- if (anchorEl) {
331
- this.scrollTo(this.getElement(highlightCountryIndex + preferredCountries.length))
332
- }
333
- })
334
- }
335
- }
336
-
337
- handleInput = (e) => {
338
- let { selectedCountry: newSelectedCountry, freezeSelection } = this.state
339
- const {
340
- selectedCountry, formattedNumber: oldFormattedText, onlyCountries, defaultCountry,
341
- } = this.state
342
- const {
343
- disableCountryCode, countryCodeEditable, isModernBrowser, onChange,
344
- } = this.props
345
-
346
- let formattedNumber = disableCountryCode ? '' : '+'
347
-
348
- if (!countryCodeEditable) {
349
- const updatedInput = `+${newSelectedCountry.dialCode}`
350
- if (e.target.value.length < updatedInput.length) {
351
- return
352
- }
353
- }
354
-
355
- // Does not exceed 15 digit phone number limit
356
- if (e.target.value.replace(/\D/g, '').length > 15) {
357
- return
358
- }
359
-
360
- // if the input is the same as before, must be some special key like enter etc.
361
- if (e.target.value === oldFormattedText) {
362
- return
363
- }
364
-
365
- // ie hack
366
- if (e.preventDefault) {
367
- e.preventDefault()
368
- } else {
369
- e.returnValue = false
370
- }
371
-
372
- if (e.target.value.length > 0) {
373
- // before entering the number in new format, lets check if the dial code now matches some other country
374
- const inputNumber = e.target.value.replace(/\D/g, '')
375
-
376
- // we don't need to send the whole number to guess the country... only the first 6 characters are enough
377
- // the guess country function can then use memoization much more effectively since the set of input it
378
- // gets has drastically reduced
379
- if (!freezeSelection || selectedCountry.dialCode.length > inputNumber.length) {
380
- newSelectedCountry = this.guessSelectedCountry(inputNumber.substring(0, 6), onlyCountries, defaultCountry)
381
- freezeSelection = false
382
- }
383
- // let us remove all non numerals from the input
384
- formattedNumber = this.formatNumber(inputNumber, newSelectedCountry.format)
385
- }
386
-
387
- let caretPosition = e.target.selectionStart
388
- const diff = formattedNumber.length - oldFormattedText.length
389
-
390
- this.setState({
391
- formattedNumber,
392
- freezeSelection,
393
- selectedCountry: newSelectedCountry.dialCode
394
- ? newSelectedCountry
395
- : selectedCountry,
396
- }, () => {
397
- if (isModernBrowser) {
398
- if (diff > 0) {
399
- caretPosition -= diff
400
- }
401
-
402
- const lastChar = formattedNumber.charAt(formattedNumber.length - 1)
403
-
404
- if (lastChar === ')') {
405
- this.inputRef.setSelectionRange(formattedNumber.length - 1, formattedNumber.length - 1)
406
- } else if (caretPosition > 0 && oldFormattedText.length >= formattedNumber.length) {
407
- this.inputRef.setSelectionRange(caretPosition, caretPosition)
408
- }
409
- }
410
-
411
- if (onChange) {
412
- onChange(formattedNumber, this.getCountryData())
413
- }
414
- })
415
- }
416
-
417
- handleRefInput = (ref) => {
418
- const { inputRef, InputProps } = this.props
419
- this.inputRef = ref
420
-
421
- let refProp
422
-
423
- if (inputRef) {
424
- refProp = inputRef
425
- } else if (InputProps && InputProps.ref) {
426
- refProp = InputProps.ref
427
- }
428
-
429
- if (refProp) {
430
- if (typeof refProp === 'function') {
431
- refProp(ref)
432
- } else {
433
- refProp.current = ref
434
- }
435
- }
436
- }
437
-
438
- handleInputClick = (e) => {
439
- const { onClick } = this.props
440
-
441
- if (onClick) {
442
- onClick(e, this.getCountryData())
443
- }
444
- }
445
-
446
- handleFlagItemClick = (country) => {
447
- const { formattedNumber, selectedCountry, onlyCountries } = this.state
448
- const { onChange } = this.props
449
-
450
- const currentSelectedCountry = selectedCountry
451
- const nextSelectedCountry = isString(country) ? onlyCountries.find((c) => c.iso2 === country) : onlyCountries.find((c) => c.iso2 === country.iso2)
452
-
453
- const unformattedNumber = formattedNumber.replace(' ', '').replace('(', '').replace(')', '').replace('-', '')
454
- const newNumber = unformattedNumber.length > 1 ? unformattedNumber.replace(currentSelectedCountry.dialCode, nextSelectedCountry.dialCode) : nextSelectedCountry.dialCode
455
-
456
- const newFormattedNumber = this.formatNumber(newNumber.replace(/\D/g, ''), nextSelectedCountry.format)
457
-
458
- this.setState({
459
- anchorEl: null,
460
- selectedCountry: nextSelectedCountry,
461
- freezeSelection: true,
462
- formattedNumber: newFormattedNumber,
463
- }, () => {
464
- this.cursorToEnd()
465
- if (onChange) {
466
- onChange(newFormattedNumber, this.getCountryData())
467
- }
468
- })
469
- }
470
-
471
- handleInputFocus = (e) => {
472
- const { selectedCountry } = this.state
473
- const { disableCountryCode, onFocus } = this.props
474
-
475
- // if the input is blank, insert dial code of the selected country
476
- if (this.inputRef) {
477
- if (this.inputRef.value === '+' && selectedCountry && !disableCountryCode) {
478
- this.setState({
479
- formattedNumber: `+${selectedCountry.dialCode}`,
480
- }, () => setTimeout(this.cursorToEnd, 10))
481
- }
482
- }
483
-
484
- this.setState({ placeholder: '' })
485
-
486
- if (onFocus) {
487
- onFocus(e, this.getCountryData())
488
- }
489
-
490
- setTimeout(this.cursorToEnd, 10)
491
- }
492
-
493
- handleInputBlur = (e) => {
494
- const { placeholder, onBlur } = this.props
495
-
496
- if (!e.target.value) {
497
- this.setState({ placeholder })
498
- }
499
-
500
- if (onBlur) {
501
- onBlur(e, this.getCountryData())
502
- }
503
- }
504
-
505
- getHighlightCountryIndex = (direction) => {
506
- const { highlightCountryIndex: oldHighlightCountryIndex, onlyCountries, preferredCountries } = this.state
507
-
508
- // had to write own function because underscore does not have findIndex. lodash has it
509
- const highlightCountryIndex = oldHighlightCountryIndex + direction
510
-
511
- if (highlightCountryIndex < 0 || highlightCountryIndex >= (onlyCountries.length + preferredCountries.length)) {
512
- return highlightCountryIndex - direction
513
- }
514
-
515
- return highlightCountryIndex
516
- }
517
-
518
- searchCountry = () => {
519
- const { queryString, onlyCountries, preferredCountries } = this.state
520
-
521
- const probableCandidate = this.getProbableCandidate(queryString) || onlyCountries[0]
522
- const probableCandidateIndex = onlyCountries.findIndex((c) => c.iso2 === probableCandidate.iso2) + preferredCountries.length
523
-
524
- this.scrollTo(this.getElement(probableCandidateIndex), true)
525
-
526
- this.setState({ queryString: '', highlightCountryIndex: probableCandidateIndex })
527
- }
528
-
529
- handleKeydown = (e) => {
530
- const {
531
- anchorEl, highlightCountryIndex, preferredCountries, onlyCountries,
532
- queryString, debouncedQueryStringSearcher,
533
- } = this.state
534
- const { keys, disabled } = this.props
535
-
536
- if (!anchorEl || disabled) return true
537
-
538
- // ie hack
539
- if (e.preventDefault) {
540
- e.preventDefault()
541
- } else {
542
- e.returnValue = false
543
- }
544
-
545
- const moveHighlight = (direction) => {
546
- this.setState({
547
- highlightCountryIndex: this.getHighlightCountryIndex(direction),
548
- }, () => {
549
- this.scrollTo(this.getElement(
550
- highlightCountryIndex + preferredCountries.length,
551
- ), true)
552
- })
553
- }
554
-
555
- switch (e.which) {
556
- case keys.DOWN:
557
- moveHighlight(1)
558
- break
559
- case keys.UP:
560
- moveHighlight(-1)
561
- break
562
- case keys.ENTER:
563
- this.handleFlagItemClick(onlyCountries[highlightCountryIndex], e)
564
- break
565
- case keys.ESC:
566
- this.setState({
567
- anchorEl: null,
568
- }, this.cursorToEnd)
569
- break
570
- default:
571
- if ((e.which >= keys.A && e.which <= keys.Z) || e.which === keys.SPACE) {
572
- this.setState({
573
- queryString: queryString + String.fromCharCode(e.which),
574
- }, debouncedQueryStringSearcher)
575
- }
576
- }
577
- }
578
-
579
- handleInputKeyDown = (e) => {
580
- const { keys, onEnterKeyPress, onKeyDown } = this.props
581
- if (e.which === keys.ENTER && onEnterKeyPress) {
582
- onEnterKeyPress(e)
583
- }
584
-
585
- if (onKeyDown) {
586
- onKeyDown(e)
587
- }
588
- }
589
-
590
- checkIfValid = () => {
591
- const { formattedNumber } = this.state
592
- const { isValid } = this.props
593
-
594
- return isValid(formattedNumber.replace(/\D/g, ''))
595
- }
596
-
597
- updateFormattedNumber = (number) => {
598
- const { onlyCountries, defaultCountry } = this.state
599
- const { disableCountryCode } = this.props
600
-
601
- let countryGuess
602
- let inputNumber = number
603
- let formattedNumber = number
604
-
605
- // if inputNumber does not start with '+', then use default country's dialing prefix,
606
- // otherwise use logic for finding country based on country prefix.
607
- if (!inputNumber.startsWith('+')) {
608
- countryGuess = onlyCountries.find((c) => c.iso2 === defaultCountry)
609
- const dialCode = countryGuess && !inputNumber.replace(/\D/g, '').startsWith(countryGuess.dialCode) ? countryGuess.dialCode : ''
610
- formattedNumber = this.formatNumber(
611
- (disableCountryCode ? '' : dialCode) + inputNumber.replace(/\D/g, ''),
612
- countryGuess ? countryGuess.format : undefined,
613
- )
614
- } else {
615
- inputNumber = inputNumber.replace(/\D/g, '')
616
- countryGuess = this.guessSelectedCountry(inputNumber.substring(0, 6), onlyCountries, defaultCountry)
617
- formattedNumber = this.formatNumber(inputNumber, countryGuess.format)
618
- }
619
-
620
- this.setState({ selectedCountry: countryGuess, formattedNumber })
621
- }
622
-
623
- getDropdownProps = () => {
624
- const {
625
- selectedCountry, anchorEl, preferredCountries, onlyCountries,
626
- } = this.state
627
-
628
- const {
629
- classes, dropdownClass, localization, disableDropdown, native,
630
- } = this.props
631
-
632
- const inputFlagClasses = `flag-icon flag-icon-${selectedCountry.iso2}`
633
-
634
- const dropdownProps = disableDropdown ? {} : {
635
- startAdornment: (
636
- <InputAdornment
637
- className={classes.positionStart}
638
- position="start"
639
- >
640
- {native ? (
641
- <>
642
- <NativeSelect
643
- id="country-menu"
644
- open={Boolean(anchorEl)}
645
- onClose={() => this.setState({ anchorEl: null })}
646
- className={classes.native}
647
- classes={{
648
- root: classNames(classes.nativeRoot, 'native', inputFlagClasses),
649
- select: classes.nativeSelect,
650
- }}
651
- onChange={(e) => this.handleFlagItemClick(e.target.value)}
652
- disableUnderline
653
- >
654
- {!!preferredCountries.length && preferredCountries.map((country, index) => (
655
- <Item
656
- key={`preferred_${country.iso2}_${index}`}
657
- itemRef={(node) => {
658
- this.flags[`flag_no_${index}`] = node
659
- }}
660
- name={country.name}
661
- iso2={country.iso2}
662
- dialCode={country.dialCode}
663
- localization={localization && localization[country.name]}
664
- native
665
- />
666
- ))}
667
-
668
- { onlyCountries.map((country, index) => (
669
- <Item
670
- key={`preferred_${country.iso2}_${index}`}
671
- itemRef={(node) => {
672
- this.flags[`flag_no_${index}`] = node
673
- }}
674
- name={country.name}
675
- iso2={country.iso2}
676
- dialCode={country.dialCode}
677
- localization={localization && localization[country.name]}
678
- native
679
- />
680
- ))}
681
- </NativeSelect>
682
- </>
683
- ) : (
684
- <>
685
- <Button
686
- className={classes.flagButton}
687
- aria-owns={anchorEl ? 'country-menu' : null}
688
- aria-label="Select country"
689
- onClick={(e) => this.setState({ anchorEl: e.currentTarget })}
690
- aria-haspopup
691
- >
692
- <div className={inputFlagClasses} />
693
- </Button>
694
-
695
- <Menu
696
- className={dropdownClass}
697
- id="country-menu"
698
- anchorEl={anchorEl}
699
- open={Boolean(anchorEl)}
700
- onClose={() => this.setState({ anchorEl: null })}
701
- onEnter={this.handleFlagDropdownClick}
702
- PaperProps={{
703
- ref: (node) => {
704
- this.dropdownContainerRef = node
705
- },
706
- }}
707
- >
708
- {!!preferredCountries.length && preferredCountries.map((country, index) => (
709
- <Item
710
- key={`preferred_${country.iso2}_${index}`}
711
- itemRef={(node) => {
712
- this.flags[`flag_no_${index}`] = node
713
- }}
714
- onClick={() => this.handleFlagItemClick(country)}
715
- name={country.name}
716
- iso2={country.iso2}
717
- dialCode={country.dialCode}
718
- localization={localization && localization[country.name]}
719
- />
720
- ))}
721
-
722
- {!!preferredCountries.length && <Divider />}
723
-
724
- { onlyCountries.map((country, index) => (
725
- <Item
726
- key={`preferred_${country.iso2}_${index}`}
727
- itemRef={(node) => {
728
- this.flags[`flag_no_${index}`] = node
729
- }}
730
- onClick={() => this.handleFlagItemClick(country)}
731
- name={country.name}
732
- iso2={country.iso2}
733
- dialCode={country.dialCode}
734
- localization={localization && localization[country.name]}
735
- />
736
- ))}
737
- </Menu>
738
- </>
739
- )}
740
- </InputAdornment>
741
- ),
742
- }
743
-
744
- return dropdownProps
745
- }
746
-
747
- render() {
748
- const {
749
- formattedNumber, placeholder: statePlaceholder,
750
- } = this.state
751
-
752
- const {
753
- // start placeholder props
754
- native, defaultCountry, excludeCountries, onlyCountries, preferredCountries,
755
- dropdownClass, autoFormat, disableAreaCodes, isValid, disableCountryCode,
756
- disableDropdown, enableLongNumbers, countryCodeEditable, onEnterKeyPress,
757
- isModernBrowser, classes, keys, localization, placeholder, regions, onChange,
758
- value,
759
- // end placeholder props
760
- inputClass, error, InputProps,
761
- ...restProps
762
- } = this.props
763
-
764
- const dropdownProps = this.getDropdownProps()
765
-
766
- return (
767
- <TextField
768
- placeholder={statePlaceholder}
769
- value={formattedNumber}
770
- className={inputClass}
771
- inputRef={this.handleRefInput}
772
- error={error || !this.checkIfValid()}
773
- onChange={this.handleInput}
774
- onClick={this.handleInputClick}
775
- onFocus={this.handleInputFocus}
776
- onBlur={this.handleInputBlur}
777
- onKeyDown={this.handleInputKeyDown}
778
- type="tel"
779
- InputProps={{
780
- ...dropdownProps,
781
- ...InputProps,
782
- }}
783
- {...restProps}
784
- />
785
- )
786
- }
787
- }
788
-
789
- MaterialUiPhoneNumber.propTypes = {
790
- classes: PropTypes.object,
791
-
792
- excludeCountries: PropTypes.arrayOf(PropTypes.string),
793
- onlyCountries: PropTypes.arrayOf(PropTypes.string),
794
- preferredCountries: PropTypes.arrayOf(PropTypes.string),
795
- defaultCountry: PropTypes.string,
796
-
797
- value: PropTypes.string,
798
- placeholder: PropTypes.string,
799
- disabled: PropTypes.bool,
800
- error: PropTypes.bool,
801
- variant: PropTypes.string,
802
- native: PropTypes.bool,
803
-
804
- inputClass: PropTypes.string,
805
- dropdownClass: PropTypes.string,
806
- InputProps: PropTypes.object,
807
- inputProps: PropTypes.object,
808
- inputRef: PropTypes.func,
809
-
810
- autoFormat: PropTypes.bool,
811
- disableAreaCodes: PropTypes.bool,
812
- disableCountryCode: PropTypes.bool,
813
- disableDropdown: PropTypes.bool,
814
- enableLongNumbers: PropTypes.bool,
815
- countryCodeEditable: PropTypes.bool,
816
-
817
- regions: PropTypes.oneOfType([
818
- PropTypes.string,
819
- PropTypes.arrayOf(PropTypes.string),
820
- ]),
821
-
822
- localization: PropTypes.object,
823
-
824
- onChange: PropTypes.func,
825
- onFocus: PropTypes.func,
826
- onBlur: PropTypes.func,
827
- onClick: PropTypes.func,
828
- onKeyDown: PropTypes.func,
829
-
830
- isValid: PropTypes.func,
831
- isModernBrowser: PropTypes.func,
832
- onEnterKeyPress: PropTypes.func,
833
- keys: PropTypes.object,
834
- }
835
-
836
- MaterialUiPhoneNumber.defaultProps = {
837
- excludeCountries: [],
838
- onlyCountries: [],
839
- preferredCountries: [],
840
- defaultCountry: '',
841
-
842
- placeholder: '+1 (702) 123-4567',
843
- disabled: false,
844
- error: false,
845
- variant: 'standard',
846
- native: false,
847
-
848
- inputClass: '',
849
- dropdownClass: '',
850
-
851
- autoFormat: true,
852
- disableAreaCodes: false,
853
- isValid: (inputNumber) => countryData.allCountries.some((country) => inputNumber.startsWith(country.dialCode) || country.dialCode.startsWith(inputNumber)),
854
- disableCountryCode: false,
855
- disableDropdown: false,
856
- enableLongNumbers: false,
857
- countryCodeEditable: true,
858
-
859
- regions: '',
860
-
861
- localization: {},
862
-
863
- onEnterKeyPress: () => { },
864
- onChange: () => {},
865
-
866
- isModernBrowser: () => (document.createElement ? Boolean(document.createElement('input').setSelectionRange) : false),
867
-
868
- keys: {
869
- UP: 38,
870
- DOWN: 40,
871
- RIGHT: 39,
872
- LEFT: 37,
873
- ENTER: 13,
874
- ESC: 27,
875
- PLUS: 43,
876
- A: 65,
877
- Z: 90,
878
- SPACE: 32,
879
- },
880
- }
881
-
882
- MaterialUiPhoneNumber.displayName = 'MuiPhoneNumber'
883
-
884
- export default withStyles(styles)(MaterialUiPhoneNumber)