mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Phone input done
This commit is contained in:
parent
ccc14a030c
commit
e9dc0f5710
9 changed files with 1464 additions and 70 deletions
|
|
@ -0,0 +1,96 @@
|
|||
import React, { 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';
|
||||
|
||||
export const PhoneInput = ({ componentMeta, darkMode, ...restProps }) => {
|
||||
const {
|
||||
layoutPropertyChanged,
|
||||
component,
|
||||
paramUpdated,
|
||||
dataQueries,
|
||||
currentState,
|
||||
eventsChanged,
|
||||
apps,
|
||||
allComponents,
|
||||
} = restProps;
|
||||
|
||||
const properties = Object.keys(componentMeta.properties);
|
||||
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 renderCustomOption = ({ label, value: optionValue }) => {
|
||||
const optionStyle = {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'start',
|
||||
height: '18px',
|
||||
gap: '6px',
|
||||
cursor: 'pointer',
|
||||
fontFamily: 'IBM Plex Sans',
|
||||
fontSize: '12px',
|
||||
lineHeight: '18px',
|
||||
fontWeight: '400',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={optionStyle} className={`selectedOption ${optionValue !== 'none' && 'custom-phone-input-options'}`}>
|
||||
<div style={{ width: '25px', height: '16px' }} className={`flag ${optionValue}`}></div>
|
||||
{label}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
||||
const filteredProperties = properties.filter(
|
||||
(property) => componentMeta.properties[property].section !== 'additionalActions'
|
||||
);
|
||||
|
||||
const additionalActions = properties.filter(
|
||||
(property) => componentMeta.properties[property].section === 'additionalActions'
|
||||
);
|
||||
|
||||
const accordionItems = baseComponentProperties(
|
||||
filteredProperties,
|
||||
events,
|
||||
component,
|
||||
componentMeta,
|
||||
layoutPropertyChanged,
|
||||
paramUpdated,
|
||||
dataQueries,
|
||||
currentState,
|
||||
eventsChanged,
|
||||
apps,
|
||||
allComponents,
|
||||
validations,
|
||||
darkMode,
|
||||
null,
|
||||
additionalActions
|
||||
);
|
||||
|
||||
accordionItems[0].children.splice(3, 0, getCountryDropdown());
|
||||
|
||||
return <Accordion items={accordionItems} />;
|
||||
};
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
export const countries = Object.entries({
|
||||
af: 'Afghanistan',
|
||||
al: 'Albania',
|
||||
dz: 'Algeria',
|
||||
um: 'United States Minor Outlying Islands',
|
||||
ad: 'Andorra',
|
||||
ao: 'Angola',
|
||||
ai: 'Anguilla',
|
||||
aq: 'Antarctica',
|
||||
ag: 'Antigua and Barbuda',
|
||||
sa: 'Saudi Arabia',
|
||||
ar: 'Argentina',
|
||||
am: 'Armenia',
|
||||
aw: 'Aruba',
|
||||
au: 'Australia',
|
||||
at: 'Austria',
|
||||
az: 'Azerbaijan',
|
||||
bs: 'Bahamas',
|
||||
bh: 'Bahrain',
|
||||
bd: 'Bangladesh',
|
||||
bb: 'Barbados',
|
||||
be: 'Belgium',
|
||||
bz: 'Belize',
|
||||
bj: 'Benin',
|
||||
bm: 'Bermuda',
|
||||
bt: 'Bhutan',
|
||||
by: 'Belarus',
|
||||
bo: 'Bolivia',
|
||||
ba: 'Bosnia and Herzegovina',
|
||||
bw: 'Botswana',
|
||||
br: 'Brazil',
|
||||
bn: 'Brunei',
|
||||
bg: 'Bulgaria',
|
||||
bf: 'Burkina Faso',
|
||||
bi: 'Burundi',
|
||||
kh: 'Cambodia',
|
||||
cm: 'Cameroon',
|
||||
ca: 'Canada',
|
||||
cv: 'Cape Verde',
|
||||
bq: 'Caribbean Netherlands',
|
||||
cz: 'Czechia',
|
||||
ea: 'Ceuta and Melilla',
|
||||
td: 'Chad',
|
||||
cl: 'Chile',
|
||||
cn: 'China',
|
||||
cy: 'Cyprus',
|
||||
va: 'Vatican City',
|
||||
co: 'Colombia',
|
||||
km: 'Comoros',
|
||||
cd: 'Congo - Kinshasa',
|
||||
cg: 'Congo - Brazzaville',
|
||||
kp: 'North Korea',
|
||||
kr: 'South Korea',
|
||||
ci: 'Ivory Coast',
|
||||
cr: 'Costa Rica',
|
||||
hr: 'Croatia',
|
||||
cu: 'Cuba',
|
||||
cw: 'Curaçao',
|
||||
dk: 'Denmark',
|
||||
dg: 'Diego Garcia',
|
||||
dm: 'Dominica',
|
||||
ec: 'Ecuador',
|
||||
eg: 'Egypt',
|
||||
sv: 'El Salvador',
|
||||
ae: 'United Arab Emirates',
|
||||
er: 'Eritrea',
|
||||
ee: 'Estonia',
|
||||
et: 'Ethiopia',
|
||||
fj: 'Fiji',
|
||||
ph: 'Philippines',
|
||||
fi: 'Finland',
|
||||
fr: 'France',
|
||||
ga: 'Gabon',
|
||||
gm: 'Gambia',
|
||||
ge: 'Georgia',
|
||||
gs: 'South Georgia and the South Sandwich Islands',
|
||||
de: 'Germany',
|
||||
gh: 'Ghana',
|
||||
jm: 'Jamaica',
|
||||
jp: 'Japan',
|
||||
gi: 'Gibraltar',
|
||||
dj: 'Djibouti',
|
||||
jo: 'Jordan',
|
||||
gr: 'Greece',
|
||||
gd: 'Grenada',
|
||||
gl: 'Greenland',
|
||||
gp: 'Guadeloupe',
|
||||
gu: 'Guam',
|
||||
gt: 'Guatemala',
|
||||
gg: 'Guernsey',
|
||||
gn: 'Guinea',
|
||||
gq: 'Equatorial Guinea',
|
||||
gw: 'Guinea-Bissau',
|
||||
gy: 'Guyana',
|
||||
gf: 'French Guiana',
|
||||
ht: 'Haiti',
|
||||
hn: 'Honduras',
|
||||
in: 'India',
|
||||
id: 'Indonesia',
|
||||
ir: 'Iran',
|
||||
iq: 'Iraq',
|
||||
ie: 'Ireland',
|
||||
is: 'Iceland',
|
||||
ac: 'Ascension Island',
|
||||
cx: 'Christmas Island',
|
||||
im: 'Isle of Man',
|
||||
nf: 'Norfolk Island',
|
||||
ax: 'Åland Islands',
|
||||
ic: 'Canary Islands',
|
||||
ky: 'Cayman Islands',
|
||||
cc: 'Cocos (Keeling) Islands',
|
||||
ck: 'Cook Islands',
|
||||
fo: 'Faroe Islands',
|
||||
fk: 'Falkland Islands',
|
||||
mp: 'Northern Mariana Islands',
|
||||
mh: 'Marshall Islands',
|
||||
pn: 'Pitcairn Islands',
|
||||
sb: 'Solomon Islands',
|
||||
tc: 'Turks and Caicos Islands',
|
||||
vi: 'U.S. Virgin Islands',
|
||||
vg: 'British Virgin Islands',
|
||||
il: 'Israel',
|
||||
it: 'Italy',
|
||||
je: 'Jersey',
|
||||
kz: 'Kazakhstan',
|
||||
ke: 'Kenya',
|
||||
kg: 'Kyrgyzstan',
|
||||
ki: 'Kiribati',
|
||||
xk: 'Kosovo',
|
||||
kw: 'Kuwait',
|
||||
la: 'Laos',
|
||||
ls: 'Lesotho',
|
||||
lv: 'Latvia',
|
||||
lb: 'Lebanon',
|
||||
lr: 'Liberia',
|
||||
ly: 'Libya',
|
||||
li: 'Liechtenstein',
|
||||
lt: 'Lithuania',
|
||||
lu: 'Luxembourg',
|
||||
mk: 'North Macedonia',
|
||||
mg: 'Madagascar',
|
||||
mw: 'Malawi',
|
||||
my: 'Malaysia',
|
||||
mv: 'Maldives',
|
||||
ml: 'Mali',
|
||||
mt: 'Malta',
|
||||
ma: 'Morocco',
|
||||
mq: 'Martinique',
|
||||
mr: 'Mauritania',
|
||||
mu: 'Mauritius',
|
||||
yt: 'Mayotte',
|
||||
mx: 'Mexico',
|
||||
fm: 'Micronesia',
|
||||
md: 'Moldova',
|
||||
mc: 'Monaco',
|
||||
mn: 'Mongolia',
|
||||
me: 'Montenegro',
|
||||
ms: 'Montserrat',
|
||||
mz: 'Mozambique',
|
||||
mm: 'Myanmar',
|
||||
na: 'Namibia',
|
||||
nr: 'Nauru',
|
||||
np: 'Nepal',
|
||||
ni: 'Nicaragua',
|
||||
ne: 'Niger',
|
||||
ng: 'Nigeria',
|
||||
nu: 'Niue',
|
||||
no: 'Norway',
|
||||
nc: 'New Caledonia',
|
||||
nz: 'New Zealand',
|
||||
om: 'Oman',
|
||||
nl: 'Netherlands',
|
||||
pk: 'Pakistan',
|
||||
pw: 'Palau',
|
||||
pa: 'Panama',
|
||||
pg: 'Papua New Guinea',
|
||||
py: 'Paraguay',
|
||||
pe: 'Peru',
|
||||
pf: 'French Polynesia',
|
||||
pl: 'Poland',
|
||||
pt: 'Portugal',
|
||||
pr: 'Puerto Rico',
|
||||
qa: 'Qatar',
|
||||
hk: 'Hong Kong SAR',
|
||||
mo: 'Macau SAR',
|
||||
gb: 'United Kingdom',
|
||||
cf: 'Central African Republic',
|
||||
do: 'Dominican Republic',
|
||||
re: 'Réunion',
|
||||
ro: 'Romania',
|
||||
rw: 'Rwanda',
|
||||
ru: 'Russia',
|
||||
eh: 'Western Sahara',
|
||||
kn: 'Saint Kitts and Nevis',
|
||||
lc: 'Saint Lucia',
|
||||
mf: 'Saint Martin',
|
||||
vc: 'Saint Vincent and the Grenadines',
|
||||
bl: 'Saint Barthélemy',
|
||||
pm: 'Saint Pierre and Miquelon',
|
||||
ws: 'Samoa',
|
||||
as: 'American Samoa',
|
||||
sm: 'San Marino',
|
||||
sh: 'Saint Helena',
|
||||
st: 'São Tomé and Príncipe',
|
||||
sn: 'Senegal',
|
||||
rs: 'Serbia',
|
||||
sc: 'Seychelles',
|
||||
sl: 'Sierra Leone',
|
||||
sg: 'Singapore',
|
||||
sx: 'Sint Maarten',
|
||||
sy: 'Syria',
|
||||
sk: 'Slovakia',
|
||||
si: 'Slovenia',
|
||||
so: 'Somalia',
|
||||
es: 'Spain',
|
||||
lk: 'Sri Lanka',
|
||||
us: 'United States',
|
||||
ss: 'South Sudan',
|
||||
za: 'South Africa',
|
||||
sd: 'Sudan',
|
||||
sr: 'Suriname',
|
||||
se: 'Sweden',
|
||||
ch: 'Switzerland',
|
||||
tj: 'Tajikistan',
|
||||
th: 'Thailand',
|
||||
tl: 'Timor-Leste',
|
||||
tg: 'Togo',
|
||||
tn: 'Tunisia',
|
||||
tr: 'Turkey',
|
||||
ua: 'Ukraine',
|
||||
ug: 'Uganda',
|
||||
hu: 'Hungary',
|
||||
uy: 'Uruguay',
|
||||
uz: 'Uzbekistan',
|
||||
vn: 'Vietnam',
|
||||
ye: 'Yemen',
|
||||
zm: 'Zambia',
|
||||
zw: 'Zimbabwe',
|
||||
}).map(([value, label]) => ({ value, label }));
|
||||
|
|
@ -8,6 +8,7 @@ import { validateQueryName, convertToKebabCase, resolveReferences } from '@/_hel
|
|||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { DefaultComponent } from './Components/DefaultComponent';
|
||||
import { FilePicker } from './Components/FilePicker';
|
||||
import { PhoneInput } from './Components/PhoneInput/PhoneInput.jsx';
|
||||
import { Modal } from './Components/Modal';
|
||||
import { ModalV2 } from './Components/ModalV2';
|
||||
import { CustomComponent } from './Components/CustomComponent';
|
||||
|
|
@ -734,6 +735,8 @@ const GetAccordion = React.memo(
|
|||
case 'DatePickerV2':
|
||||
case 'TimePicker':
|
||||
return <DatetimePickerV2 {...restProps} componentName={componentName} />;
|
||||
case 'PhoneInput':
|
||||
return <PhoneInput {...restProps} />;
|
||||
|
||||
default: {
|
||||
return <DefaultComponent {...restProps} />;
|
||||
|
|
|
|||
|
|
@ -205,9 +205,9 @@ export const phoneinputConfig = {
|
|||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setText',
|
||||
displayName: 'Set text',
|
||||
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
|
||||
handle: 'setValue',
|
||||
displayName: 'Set Value',
|
||||
params: [{ handle: 'value', displayName: 'value', defaultValue: '00' }],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
|
|
@ -221,16 +221,6 @@ export const phoneinputConfig = {
|
|||
handle: 'setBlur',
|
||||
displayName: 'Set blur',
|
||||
},
|
||||
{
|
||||
handle: 'disable',
|
||||
displayName: 'Disable(deprecated)',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'visibility',
|
||||
displayName: 'Visibility(deprecated)',
|
||||
params: [{ handle: 'visibility', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export const useInput = ({
|
|||
setExposedVariable,
|
||||
setExposedVariables,
|
||||
fireEvent,
|
||||
inputType,
|
||||
}) => {
|
||||
const isInitialRender = useRef(true);
|
||||
const inputRef = useRef();
|
||||
|
|
@ -90,8 +91,9 @@ export const useInput = ({
|
|||
}, [properties.value]);
|
||||
|
||||
useEffect(() => {
|
||||
const setterName = inputType === 'phone' ? 'setValue' : 'setText';
|
||||
const exposedVariables = {
|
||||
setText: async function (text) {
|
||||
[setterName]: async function (text) {
|
||||
setInputValue(text);
|
||||
fireEvent('onChange');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ import Label from '@/_ui/Label';
|
|||
|
||||
export const PhoneInput = (props) => {
|
||||
const { properties, styles, componentName, darkMode } = props;
|
||||
const inputLogic = useInput(props);
|
||||
const transformedProps = {
|
||||
...props,
|
||||
inputType: 'phone',
|
||||
};
|
||||
const inputLogic = useInput(transformedProps);
|
||||
const {
|
||||
inputRef,
|
||||
labelRef,
|
||||
|
|
@ -30,7 +34,7 @@ export const PhoneInput = (props) => {
|
|||
handleFocus,
|
||||
handleKeyUp,
|
||||
} = inputLogic;
|
||||
const { label, placeholder, isCountryChangeEnabled } = properties;
|
||||
const { label, placeholder, isCountryChangeEnabled, defaultCountry = 'us' } = properties;
|
||||
const {
|
||||
textColor,
|
||||
backgroundColor,
|
||||
|
|
@ -42,6 +46,8 @@ export const PhoneInput = (props) => {
|
|||
borderColor,
|
||||
accentColor,
|
||||
errTextColor,
|
||||
boxShadow,
|
||||
borderRadius,
|
||||
} = styles;
|
||||
const _width = (width / 100) * 70;
|
||||
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
|
||||
|
|
@ -57,14 +63,34 @@ export const PhoneInput = (props) => {
|
|||
: 'var(--borders-default)';
|
||||
|
||||
const inputStyle = {
|
||||
color: textColor,
|
||||
backgroundColor,
|
||||
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 dropdownStyle = {
|
||||
backgroundColor: darkMode ? '#1B1F24' : '#fff',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
};
|
||||
|
||||
const searchStyle = {
|
||||
backgroundColor: darkMode ? '#1B1F24' : '#fff',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
backgroundColor: darkMode ? '#1B1F24' : '#fff',
|
||||
color: darkMode ? '#fff' : '#1B1F24',
|
||||
borderRadius: `${borderRadius}px`,
|
||||
};
|
||||
|
||||
const buttonStyle = {
|
||||
backgroundColor: backgroundColor,
|
||||
backgroundColor: disable ? '#e4e7eb' : darkMode && backgroundColor === '#fff' ? '#1c2025' : backgroundColor,
|
||||
border: `${isFocused ? '1.5px' : '1px'} solid ${inputBorderColor}`,
|
||||
borderTopLeftRadius: `${borderRadius}px`,
|
||||
borderBottomLeftRadius: `${borderRadius}px`,
|
||||
};
|
||||
|
||||
const loaderStyle = {
|
||||
|
|
@ -90,7 +116,7 @@ export const PhoneInput = (props) => {
|
|||
<>
|
||||
<div
|
||||
data-cy={`label-${String(componentName).toLowerCase()}`}
|
||||
className={`text-input d-flex ${
|
||||
className={`text-input d-flex phone-input-widget ${
|
||||
defaultAlignment === 'top' &&
|
||||
((width != 0 && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
|
||||
? 'flex-column'
|
||||
|
|
@ -130,8 +156,16 @@ export const PhoneInput = (props) => {
|
|||
disabled={disable || loading}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
onKeyUp={handleKeyUp}
|
||||
disableDropdown={isCountryChangeEnabled}
|
||||
inputProps={{
|
||||
autoFocus: true,
|
||||
}}
|
||||
onKeyDown={handleKeyUp}
|
||||
disableDropdown={!isCountryChangeEnabled}
|
||||
{...(defaultCountry !== 'none' && { country: defaultCountry })}
|
||||
countryCodeEditable={isCountryChangeEnabled}
|
||||
dropdownStyle={dropdownStyle}
|
||||
searchStyle={searchStyle}
|
||||
containerStyle={containerStyle}
|
||||
/>
|
||||
{loading && <Loader style={loaderStyle} width="16" />}
|
||||
</div>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -297,10 +297,18 @@ input:checked+.slider:before {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.theme-dark {
|
||||
.form-control {
|
||||
background-color: unset !important;
|
||||
}
|
||||
|
||||
.react-tel-input .form-control {
|
||||
background-color: inherit !important; // Or any default value you prefer
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
|
|
|
|||
|
|
@ -205,9 +205,9 @@ export const phoneinputConfig = {
|
|||
},
|
||||
actions: [
|
||||
{
|
||||
handle: 'setText',
|
||||
displayName: 'Set text',
|
||||
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
|
||||
handle: 'setValue',
|
||||
displayName: 'Set Value',
|
||||
params: [{ handle: 'value', displayName: 'value', defaultValue: '00' }],
|
||||
},
|
||||
{
|
||||
handle: 'clear',
|
||||
|
|
@ -221,16 +221,6 @@ export const phoneinputConfig = {
|
|||
handle: 'setBlur',
|
||||
displayName: 'Set blur',
|
||||
},
|
||||
{
|
||||
handle: 'disable',
|
||||
displayName: 'Disable(deprecated)',
|
||||
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'visibility',
|
||||
displayName: 'Visibility(deprecated)',
|
||||
params: [{ handle: 'visibility', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
|
||||
},
|
||||
{
|
||||
handle: 'setVisibility',
|
||||
displayName: 'Set visibility',
|
||||
|
|
|
|||
Loading…
Reference in a new issue