mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-22 16:38:21 +00:00
Updated phone input component
This commit is contained in:
parent
e9dc0f5710
commit
05fb042f2a
4 changed files with 414 additions and 1167 deletions
|
|
@ -1,9 +1,15 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import Accordion from '@/_ui/Accordion';
|
||||
import { baseComponentProperties } from '../DefaultComponent';
|
||||
import Select from '@/_ui/Select';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { countries } from './en';
|
||||
import { getCountries } from 'react-phone-number-input/input';
|
||||
import en from 'react-phone-number-input/locale/en';
|
||||
import flags from 'react-phone-number-input/flags';
|
||||
import FxButton from '@/AppBuilder/CodeBuilder/Elements/FxButton';
|
||||
import CodeHinter from '@/AppBuilder/CodeEditor';
|
||||
import cx from 'classnames';
|
||||
|
||||
export const PhoneInput = ({ componentMeta, darkMode, ...restProps }) => {
|
||||
const {
|
||||
|
|
@ -21,7 +27,17 @@ export const PhoneInput = ({ componentMeta, darkMode, ...restProps }) => {
|
|||
const events = Object.keys(componentMeta.events);
|
||||
const validations = Object.keys(componentMeta.validation || {});
|
||||
const resolvedProperties = useStore((state) => state.getResolvedComponent(component.id)?.properties);
|
||||
const defaultCountry = resolvedProperties?.defaultCountry || 'None';
|
||||
const defaultCountry = resolvedProperties?.defaultCountry;
|
||||
const isDefaultCountryFxOn = componentMeta?.definition?.properties?.dateFormat?.fxActive || false;
|
||||
|
||||
const options = useMemo(
|
||||
() =>
|
||||
getCountries().map((country) => ({
|
||||
label: `${en[country]}`,
|
||||
value: country,
|
||||
})),
|
||||
[]
|
||||
);
|
||||
|
||||
const renderCustomOption = ({ label, value: optionValue }) => {
|
||||
const optionStyle = {
|
||||
|
|
@ -37,10 +53,11 @@ export const PhoneInput = ({ componentMeta, darkMode, ...restProps }) => {
|
|||
fontWeight: '400',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
};
|
||||
const FlagIcon = flags[optionValue];
|
||||
|
||||
return (
|
||||
<div style={optionStyle} className={`selectedOption ${optionValue !== 'none' && 'custom-phone-input-options'}`}>
|
||||
<div style={{ width: '25px', height: '16px' }} className={`flag ${optionValue}`}></div>
|
||||
<div>{FlagIcon ? <FlagIcon style={{ width: '22px', height: '16px' }} /> : null}</div>
|
||||
{label}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -49,17 +66,40 @@ export const PhoneInput = ({ componentMeta, darkMode, ...restProps }) => {
|
|||
const getCountryDropdown = () => {
|
||||
return (
|
||||
<div className="mb-2">
|
||||
<label class="tj-text-xsm color-slate12 mb-2 false">Default country</label>
|
||||
<Select
|
||||
width="100%"
|
||||
options={countries}
|
||||
value={defaultCountry}
|
||||
customOption={renderCustomOption}
|
||||
onChange={(value) => {
|
||||
console.log('value', value);
|
||||
paramUpdated({ name: 'defaultCountry' }, 'value', value, 'properties');
|
||||
}}
|
||||
/>
|
||||
<div className="d-flex justify-content-between mb-1">
|
||||
<label className="form-label"> Default Country</label>
|
||||
<div
|
||||
className={cx({
|
||||
'hide-fx': !isDefaultCountryFxOn,
|
||||
})}
|
||||
>
|
||||
<FxButton
|
||||
active={isDefaultCountryFxOn}
|
||||
onPress={() => {
|
||||
paramUpdated({ name: 'dateFormat' }, 'fxActive', !isDefaultCountryFxOn, 'properties');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{isDefaultCountryFxOn ? (
|
||||
<CodeHinter
|
||||
initialValue={defaultCountry}
|
||||
theme={darkMode ? 'monokai' : 'default'}
|
||||
mode="javascript"
|
||||
lineNumbers={false}
|
||||
onChange={(value) => paramUpdated({ name: 'defaultCountry' }, 'value', value, 'properties')}
|
||||
/>
|
||||
) : (
|
||||
<Select
|
||||
width="100%"
|
||||
options={options}
|
||||
value={defaultCountry}
|
||||
customOption={renderCustomOption}
|
||||
onChange={(value) => {
|
||||
paramUpdated({ name: 'defaultCountry' }, 'value', value, 'properties');
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -145,6 +145,11 @@ export const useInput = ({
|
|||
fireEvent('onChange');
|
||||
};
|
||||
|
||||
const handlePhoneInputChange = (value) => {
|
||||
setInputValue(value);
|
||||
fireEvent('onChange');
|
||||
};
|
||||
|
||||
const handleBlur = (e) => {
|
||||
setShowValidationError(true);
|
||||
setIsFocused(false);
|
||||
|
|
@ -184,6 +189,7 @@ export const useInput = ({
|
|||
validationError,
|
||||
isMandatory,
|
||||
setInputValue,
|
||||
handlePhoneInputChange,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleFocus,
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
import React from 'react';
|
||||
import { default as ReactPhoneInput } from 'react-phone-input-2';
|
||||
import 'react-phone-input-2/lib/style.css';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import Input, { getCountries, getCountryCallingCode } from 'react-phone-number-input/input';
|
||||
import en from 'react-phone-number-input/locale/en';
|
||||
import flags from 'react-phone-number-input/flags';
|
||||
import 'react-phone-number-input/style.css';
|
||||
import Select, { components } from 'react-select';
|
||||
import cx from 'classnames';
|
||||
import SolidIcon from '@/_ui/Icon/SolidIcons';
|
||||
import { useInput } from './BaseComponents/hooks/useInput';
|
||||
import Loader from '@/ToolJetUI/Loader/Loader';
|
||||
import Label from '@/_ui/Label';
|
||||
import TickV3 from '@/_ui/Icon/solidIcons/TickV3';
|
||||
const tinycolor = require('tinycolor2');
|
||||
|
||||
export const PhoneInput = (props) => {
|
||||
const { properties, styles, componentName, darkMode } = props;
|
||||
const transformedProps = {
|
||||
...props,
|
||||
inputType: 'phone',
|
||||
};
|
||||
const inputLogic = useInput(transformedProps);
|
||||
const { properties, styles, componentName, darkMode, height, setExposedVariable, setExposedVariables, fireEvent } =
|
||||
props;
|
||||
const inputLogic = useInput(props);
|
||||
const {
|
||||
inputRef,
|
||||
labelRef,
|
||||
value,
|
||||
visibility,
|
||||
loading,
|
||||
disable,
|
||||
|
|
@ -23,19 +26,18 @@ export const PhoneInput = (props) => {
|
|||
showValidationError,
|
||||
isFocused,
|
||||
labelWidth,
|
||||
iconVisibility,
|
||||
setIconVisibility,
|
||||
isValid,
|
||||
validationError,
|
||||
isMandatory,
|
||||
setInputValue,
|
||||
handleChange,
|
||||
handleBlur,
|
||||
handleFocus,
|
||||
handleKeyUp,
|
||||
value,
|
||||
handlePhoneInputChange,
|
||||
} = inputLogic;
|
||||
const { label, placeholder, isCountryChangeEnabled, defaultCountry = 'us' } = properties;
|
||||
const { label, placeholder, isCountryChangeEnabled, defaultCountry = 'US' } = properties;
|
||||
|
||||
const {
|
||||
padding,
|
||||
textColor,
|
||||
backgroundColor,
|
||||
alignment,
|
||||
|
|
@ -51,47 +53,70 @@ export const PhoneInput = (props) => {
|
|||
} = styles;
|
||||
const _width = (width / 100) * 70;
|
||||
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
|
||||
const isInitialRender = useRef(true);
|
||||
const [country, setCountry] = useState(defaultCountry);
|
||||
|
||||
const inputBorderColor = isFocused
|
||||
? accentColor != '4368E3'
|
||||
? accentColor
|
||||
: 'var(--primary-accent-strong)'
|
||||
: borderColor != '#CCD1D5'
|
||||
? borderColor
|
||||
: disable || loading
|
||||
? '1px solid var(--borders-disabled-on-white)'
|
||||
: 'var(--borders-default)';
|
||||
|
||||
const inputStyle = {
|
||||
color: darkMode && textColor === '#1B1F24' ? '#FFF' : textColor,
|
||||
backgroundColor: disable ? '#e4e7eb' : darkMode && backgroundColor === '#fff' ? '#1c2025' : backgroundColor,
|
||||
border: `${isFocused ? '1.5px' : '1px'} solid ${inputBorderColor}`,
|
||||
boxShadow,
|
||||
borderRadius: `${borderRadius}px`,
|
||||
const getCountryCallingCodeSafe = (country) => {
|
||||
try {
|
||||
return getCountryCallingCode(country);
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const dropdownStyle = {
|
||||
backgroundColor: darkMode ? '#1B1F24' : '#fff',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
const options = useMemo(
|
||||
() =>
|
||||
getCountries().map((country) => ({
|
||||
label: `${en[country]} +${getCountryCallingCodeSafe(country)}`,
|
||||
value: country,
|
||||
})),
|
||||
[]
|
||||
);
|
||||
|
||||
const onInputValueChange = (value) => {
|
||||
setExposedVariables({
|
||||
country: country,
|
||||
countryCode: getCountryCallingCodeSafe(country),
|
||||
formattedValue: `+${getCountryCallingCodeSafe(country)} ${inputRef.current?.value}`,
|
||||
});
|
||||
handlePhoneInputChange(value);
|
||||
};
|
||||
|
||||
const searchStyle = {
|
||||
backgroundColor: darkMode ? '#1B1F24' : '#fff',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
const handleKeyUp = (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
onInputValueChange(value);
|
||||
fireEvent('onEnterPressed');
|
||||
}
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
backgroundColor: darkMode ? '#1B1F24' : '#fff',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
borderRadius: `${borderRadius}px`,
|
||||
};
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
setExposedVariables({
|
||||
country: country,
|
||||
countryCode: getCountryCallingCodeSafe(country),
|
||||
formattedValue: `+${getCountryCallingCodeSafe(country)} ${inputRef.current?.value}`,
|
||||
value: value,
|
||||
setCountryCode: (code) => {
|
||||
let value = getCountryCallingCodeSafe(code);
|
||||
if (value) {
|
||||
setCountry(code);
|
||||
} else {
|
||||
value = getCountries().find((country) => `+${getCountryCallingCode(country)}` === code);
|
||||
setCountry(value ? value : '');
|
||||
}
|
||||
},
|
||||
});
|
||||
isInitialRender.current = false;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const buttonStyle = {
|
||||
backgroundColor: disable ? '#e4e7eb' : darkMode && backgroundColor === '#fff' ? '#1c2025' : backgroundColor,
|
||||
border: `${isFocused ? '1.5px' : '1px'} solid ${inputBorderColor}`,
|
||||
borderTopLeftRadius: `${borderRadius}px`,
|
||||
borderBottomLeftRadius: `${borderRadius}px`,
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!isInitialRender.current) {
|
||||
setCountry(defaultCountry);
|
||||
}
|
||||
}, [defaultCountry]);
|
||||
|
||||
const disabledState = disable || loading;
|
||||
|
||||
const loaderStyle = {
|
||||
right:
|
||||
|
|
@ -112,6 +137,255 @@ export const PhoneInput = (props) => {
|
|||
zIndex: 3,
|
||||
};
|
||||
|
||||
const computedStyles = {
|
||||
height: height == 36 ? (padding == 'default' ? '36px' : '40px') : padding == 'default' ? height : height + 4,
|
||||
borderRadius: `${borderRadius}px`,
|
||||
color: !['#1B1F24', '#000', '#000000ff'].includes(textColor)
|
||||
? textColor
|
||||
: disabledState
|
||||
? 'var(--text-disabled)'
|
||||
: 'var(--text-primary)',
|
||||
borderColor: isFocused
|
||||
? accentColor != '4368E3'
|
||||
? accentColor
|
||||
: 'var(--primary-accent-strong)'
|
||||
: borderColor != '#CCD1D5'
|
||||
? borderColor
|
||||
: disabledState
|
||||
? '1px solid var(--borders-disabled-on-white)'
|
||||
: 'var(--borders-default)',
|
||||
'--tblr-input-border-color-darker': tinycolor(borderColor).darken(24).toString(),
|
||||
backgroundColor:
|
||||
backgroundColor != '#fff'
|
||||
? backgroundColor
|
||||
: disabledState
|
||||
? darkMode
|
||||
? 'var(--surfaces-app-bg-default)'
|
||||
: 'var(--surfaces-surface-03)'
|
||||
: 'var(--surfaces-surface-01)',
|
||||
padding: '8px 10px',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
borderBottomLeftRadius: '0px',
|
||||
borderTopLeftRadius: '0px',
|
||||
borderLeft: 'none',
|
||||
};
|
||||
|
||||
const CustomValueContainer = ({ children, getValue, ...props }) => {
|
||||
const selectedValue = getValue()[0];
|
||||
const FlagIcon = selectedValue ? flags[selectedValue.value] : null;
|
||||
const countryCode = getCountryCallingCodeSafe(selectedValue.value);
|
||||
|
||||
return (
|
||||
<components.ValueContainer {...props}>
|
||||
{FlagIcon ? (
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%' }}>
|
||||
<FlagIcon style={{ height: '16px' }} />
|
||||
<span style={{ marginLeft: '2px' }}>{` +${countryCode}`}</span>
|
||||
</div>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</components.ValueContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomOption = (props) => {
|
||||
const { label, value: optionValue, isSelected } = props;
|
||||
const optionStyle = {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'start',
|
||||
minHeight: '32px',
|
||||
gap: '6px',
|
||||
cursor: 'pointer',
|
||||
fontFamily: 'IBM Plex Sans',
|
||||
fontSize: '12px',
|
||||
lineHeight: '18px',
|
||||
fontWeight: '400',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
width: '100%',
|
||||
};
|
||||
console.log('darkMode', darkMode);
|
||||
const FlagIcon = flags[optionValue];
|
||||
|
||||
return (
|
||||
<components.Option {...props}>
|
||||
<div style={optionStyle}>
|
||||
<div>{FlagIcon ? <FlagIcon style={{ width: '22px', height: '16px' }} /> : null}</div>
|
||||
{label}
|
||||
<div style={{ marginLeft: 'auto', display: isSelected ? 'block' : 'none' }}>
|
||||
<TickV3 width="13.33px" height="11.27px" />
|
||||
</div>
|
||||
</div>
|
||||
</components.Option>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomMenuList = (props) => {
|
||||
const { children, selectProps } = props;
|
||||
const { onInputChange, inputValue } = selectProps;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx('dropdown-multiselect-widget-custom-menu-list', {
|
||||
'theme-dark dark-theme': selectProps?.darkMode,
|
||||
})}
|
||||
style={{ height: '236px' }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="dropdown-multiselect-widget-search-box-wrapper">
|
||||
<span>
|
||||
<SolidIcon name="search01" width="14" />
|
||||
</span>
|
||||
<input
|
||||
autoCorrect="off"
|
||||
autoComplete="off"
|
||||
spellCheck="false"
|
||||
type="text"
|
||||
placeholder="Search"
|
||||
className="dropdown-multiselect-widget-search-box"
|
||||
value={inputValue}
|
||||
onChange={(e) => {
|
||||
onInputChange(e.currentTarget.value, {
|
||||
action: 'input-change',
|
||||
});
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
e.stopPropagation();
|
||||
e.target.focus();
|
||||
}}
|
||||
onTouchEnd={(e) => {
|
||||
e.stopPropagation();
|
||||
e.target.focus();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<components.MenuList {...props}>
|
||||
{children?.length > 0 ? children : <div style={{ padding: '8px', textAlign: 'center' }}>No options</div>}
|
||||
</components.MenuList>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CountrySelect = ({ value, onChange, options, ...rest }) => {
|
||||
const [menuIsOpen, setMenuIsOpen] = useState(false);
|
||||
const dropdownRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||
setMenuIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Add event listener when dropdown is open
|
||||
if (menuIsOpen) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
|
||||
// Clean up the event listener
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [menuIsOpen]);
|
||||
|
||||
const customStyles = {
|
||||
container: (provided) => ({
|
||||
...provided,
|
||||
minWidth: !isCountryChangeEnabled || disabledState ? '77px' : '87px',
|
||||
width: !isCountryChangeEnabled || disabledState ? '77px' : '87px',
|
||||
height: '100%',
|
||||
}),
|
||||
control: (provided, state) => ({
|
||||
...provided,
|
||||
minHeight: '0px',
|
||||
height: '100%',
|
||||
borderTopLeftRadius: `${borderRadius}px`,
|
||||
borderBottomLeftRadius: `${borderRadius}px`,
|
||||
borderTopRightRadius: '0px',
|
||||
borderBottomRightRadius: '0px',
|
||||
borderColor: `${
|
||||
!isValid && showValidationError ? 'var(--status-error-strong)' : computedStyles?.borderColor
|
||||
} !important`,
|
||||
backgroundColor: `${
|
||||
isCountryChangeEnabled
|
||||
? computedStyles?.backgroundColor
|
||||
: darkMode
|
||||
? 'var(--surfaces-app-bg-default)'
|
||||
: 'var(--surfaces-surface-03)'
|
||||
} !important`,
|
||||
}),
|
||||
menu: (provided) => ({
|
||||
...provided,
|
||||
width: '208px',
|
||||
height: '236px',
|
||||
borderRadius: '8px',
|
||||
marginTop: '2px',
|
||||
}),
|
||||
menuList: (provided) => ({
|
||||
...provided,
|
||||
maxHeight: '196px',
|
||||
overflowY: 'auto',
|
||||
scrollbarWidth: 'none',
|
||||
gap: '1px',
|
||||
padding: '8px',
|
||||
borderRadius: '0px 0px 8px 8px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'var(--surfaces-surface-01)',
|
||||
}),
|
||||
option: (provided, state) => ({
|
||||
...provided,
|
||||
backgroundColor: state.isSelected ? '#4368E31A' : 'var(--surfaces-surface-01)',
|
||||
...(state.isSelected && { borderRadius: '8px' }),
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--interactive-overlays-fill-hover)',
|
||||
borderRadius: '8px',
|
||||
},
|
||||
display: 'flex',
|
||||
cursor: 'pointer',
|
||||
padding: '1px 14px',
|
||||
}),
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%' }} onClick={() => setMenuIsOpen((prev) => !prev)} ref={dropdownRef}>
|
||||
<Select
|
||||
options={options}
|
||||
value={value}
|
||||
styles={customStyles}
|
||||
onChange={onChange}
|
||||
hasSearch={false}
|
||||
useCustomStyles={true}
|
||||
menuPortalTarget={document.body}
|
||||
components={{
|
||||
MenuList: CustomMenuList,
|
||||
Option: CustomOption,
|
||||
ValueContainer: CustomValueContainer, // Add this line
|
||||
IndicatorSeparator: () => null,
|
||||
DropdownIndicator:
|
||||
!isCountryChangeEnabled || disabledState
|
||||
? () => null
|
||||
: () => (
|
||||
<div style={{ position: 'relative', display: 'flex', left: '-1px' }}>
|
||||
{menuIsOpen ? (
|
||||
<SolidIcon name="TriangleDownCenter" width="16" height="16" />
|
||||
) : (
|
||||
<SolidIcon name="TriangleUpCenter" width="16" height="16" />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
darkMode={darkMode}
|
||||
isDisabled={disabledState}
|
||||
menuIsOpen={menuIsOpen}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
|
|
@ -144,29 +418,34 @@ export const PhoneInput = (props) => {
|
|||
_width={_width}
|
||||
labelWidth={labelWidth}
|
||||
/>
|
||||
<ReactPhoneInput
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={setInputValue}
|
||||
enableSearch={true}
|
||||
ref={inputRef}
|
||||
inputStyle={inputStyle}
|
||||
buttonStyle={buttonStyle}
|
||||
searchPlaceholder="Search"
|
||||
disabled={disable || loading}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
inputProps={{
|
||||
autoFocus: true,
|
||||
}}
|
||||
onKeyDown={handleKeyUp}
|
||||
disableDropdown={!isCountryChangeEnabled}
|
||||
{...(defaultCountry !== 'none' && { country: defaultCountry })}
|
||||
countryCodeEditable={isCountryChangeEnabled}
|
||||
dropdownStyle={dropdownStyle}
|
||||
searchStyle={searchStyle}
|
||||
containerStyle={containerStyle}
|
||||
/>
|
||||
<div className="d-flex h-100 w-100" style={{ boxShadow, borderRadius: `${borderRadius}px` }}>
|
||||
<CountrySelect
|
||||
value={{ label: `${en[country]} +${getCountryCallingCodeSafe(country)}`, value: country }}
|
||||
options={options}
|
||||
onChange={(selectedOption) => {
|
||||
if (selectedOption) {
|
||||
setCountry(selectedOption.value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
country={country}
|
||||
international={false}
|
||||
value={value}
|
||||
onChange={onInputValueChange}
|
||||
placeholder={placeholder}
|
||||
style={computedStyles}
|
||||
className={`tj-text-input-widget ${
|
||||
!isValid && showValidationError ? 'is-invalid' : ''
|
||||
} validation-without-icon`}
|
||||
disabled={disabledState}
|
||||
data-ignore-hover={true}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
onKeyUp={handleKeyUp}
|
||||
/>
|
||||
</div>
|
||||
{loading && <Loader style={loaderStyle} width="16" />}
|
||||
</div>
|
||||
{showValidationError && visibility && (
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue