Merge pull request #12414 from ToolJet/feat/currency-input

Feat/currency input
This commit is contained in:
Johnson Cherian 2025-04-07 11:07:24 +05:30 committed by GitHub
commit 3254a51c71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 5511 additions and 175 deletions

View file

@ -0,0 +1,39 @@
import React from 'react';
const EmailInput = ({ fill = '#D7DBDF', width = 24, className = '', viewBox = '0 0 49 48' }) => (
<svg
width={width}
height={width}
viewBox={viewBox}
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M2.39498 1.9349C3.35945 0.97044 4.66757 0.428589 6.03153 0.428589H43.7458C45.1097 0.428589 46.418 0.97044 47.3825 1.9349C48.347 2.89935 48.8887 4.20746 48.8887 5.57145V17.3819C47.4096 16.4176 45.6432 15.8572 43.7458 15.8572H28.3172C23.11 15.8572 18.8887 20.0785 18.8887 25.2857V31.2857H6.03153C4.66754 31.2857 3.35945 30.7439 2.39498 29.7794C1.43051 28.815 0.888672 27.5068 0.888672 26.1429V5.57145C0.888672 4.20749 1.43051 2.89935 2.39498 1.9349Z"
fill="#CCD1D5"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.8886 10.2858C14.0721 10.2858 15.0315 11.2451 15.0315 12.4286V19.2858C15.0315 20.4692 14.0721 21.4286 12.8886 21.4286C11.7052 21.4286 10.7458 20.4692 10.7458 19.2858V12.4286C10.7458 11.2451 11.7052 10.2858 12.8886 10.2858Z"
fill="#4368E3"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M28.3172 20.1428C25.4769 20.1428 23.1744 22.4453 23.1744 25.2857V36.4285C23.1744 39.2688 25.4769 41.5714 28.3172 41.5714H43.7458C46.586 41.5714 48.8887 39.2688 48.8887 36.4285V25.2857C48.8887 22.4453 46.586 20.1428 43.7458 20.1428H28.3172Z"
fill="#4368E3"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M48.7087 23.9319L36.0315 29.7828L23.3545 23.9318C23.2371 24.3631 23.1744 24.8171 23.1744 25.2857V28.5688L35.1337 34.0886C35.7034 34.3515 36.36 34.3515 36.9298 34.0886L48.8887 28.5689V25.2857C48.8887 24.8172 48.8259 24.3632 48.7087 23.9319Z"
fill="#CCD1D5"
/>
</svg>
);
export default EmailInput;

View file

@ -59,6 +59,8 @@ import Upstatistics from './upstatistics.jsx';
import Verticaldivider from './verticaldivider.jsx';
import TimePicker from './timepicker.jsx';
import DatepickerV2 from './datepickerv2.jsx';
import PhoneInput from './phoneinput.jsx';
import EmailInput from './emailinput.jsx';
const WidgetIcon = (props) => {
switch (props.name) {
@ -99,6 +101,10 @@ const WidgetIcon = (props) => {
return <Datepicker {...props} />;
case 'datetimepickerv2':
return <DateTimePickerV2 {...props} />;
case 'emailinput':
return <EmailInput {...props} />;
case 'phoneinput':
return <PhoneInput {...props} />;
case 'daterangepicker':
return <Daterangepicker {...props} />;
case 'horizontaldivider':
@ -180,6 +186,7 @@ const WidgetIcon = (props) => {
case 'text':
return <Text {...props} />;
case 'textarea':
case 'textarealegacy':
return <TextArea {...props} />;
case 'textinput':
return <Textinput {...props} />;

View file

@ -0,0 +1,36 @@
import React from 'react';
const PhoneInput = ({ fill = '#D7DBDF', width = 24, className = '', viewBox = '0 0 49 48' }) => (
<svg
width={width}
height={width}
viewBox={viewBox}
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.60296 9.85718C4.99933 9.85718 2.88867 11.9678 2.88867 14.5715V33.4286C2.88867 36.0322 4.99933 38.1429 7.60296 38.1429H42.1744C44.7779 38.1429 46.8887 36.0322 46.8887 33.4286V14.5715C46.8887 11.9678 44.7779 9.85718 42.1744 9.85718H7.60296Z"
fill="#CCD1D5"
/>
<path
d="M26.853 27.0714C25.7681 27.0714 24.8887 27.9508 24.8887 29.0357C24.8887 30.1205 25.7681 31 26.853 31H32.8884C33.9733 31 34.8527 30.1205 34.8527 29.0357C34.8527 27.9508 33.9733 27.0714 32.8884 27.0714H26.853Z"
fill="#4368E3"
/>
<g clip-path="url(#clip0_39_14)">
<path
d="M14.113 30.4517C13.4512 30.8793 12.6626 31.0657 11.8797 30.9794C11.0969 30.8932 10.3675 30.5396 9.81433 29.9781L9.33073 29.5045C9.11871 29.2873 9 28.9956 9 28.6919C9 28.3881 9.11871 28.0965 9.33073 27.8793L11.3834 25.845C11.5984 25.6333 11.8879 25.5147 12.1894 25.5147C12.4909 25.5147 12.7803 25.6333 12.9954 25.845C13.2122 26.0573 13.5035 26.1762 13.8068 26.1762C14.11 26.1762 14.4013 26.0573 14.6181 25.845L17.8422 22.616C17.9497 22.5099 18.0351 22.3834 18.0934 22.2439C18.1517 22.1043 18.1817 21.9546 18.1817 21.8034C18.1817 21.6522 18.1517 21.5024 18.0934 21.3629C18.0351 21.2234 17.9497 21.0969 17.8422 20.9908C17.6308 20.7754 17.5124 20.4855 17.5124 20.1835C17.5124 19.8815 17.6308 19.5916 17.8422 19.3763L19.8841 17.3312C20.1009 17.1189 20.3922 17 20.6954 17C20.9987 17 21.29 17.1189 21.5068 17.3312L21.9797 17.8156C22.5403 18.3696 22.8933 19.1001 22.9794 19.8842C23.0656 20.6682 22.8795 21.4581 22.4525 22.1209C20.2279 25.4045 17.3973 28.2321 14.113 30.4517Z"
fill="#4368E3"
/>
</g>
<defs>
<clipPath id="clip0_39_14">
<rect width="14" height="14" fill="white" transform="translate(9 17)" />
</clipPath>
</defs>
</svg>
);
export default PhoneInput;

View file

@ -96,6 +96,7 @@
"react-circular-progressbar": "^2.1.0",
"react-color": "^2.19.3",
"react-copy-to-clipboard": "^5.1.0",
"react-currency-input-field": "^3.10.0",
"react-datepicker": "^7.6.0",
"react-dates": "^21.8.0",
"react-datetime": "^3.2.0",
@ -118,6 +119,7 @@
"react-multi-select-component": "^4.3.4",
"react-pdf": "^6.2.2",
"react-phone-input-2": "^2.15.1",
"react-phone-number-input": "^3.4.12",
"react-plotly.js": "^2.6.0",
"react-qr-reader": "^2.2.1",
"react-rnd": "^10.4.1",
@ -29820,6 +29822,11 @@
"node": ">=10"
}
},
"node_modules/country-flag-icons": {
"version": "1.5.18",
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.18.tgz",
"integrity": "sha512-z+Uzesi8u8IdkViqqbzzbkf3+a7WJpcET5B7sPwTg7GXqPYpVEgNlZ/FC3l8KO4mEf+mNkmzKLppKTN4PlCJEQ=="
},
"node_modules/country-regex": {
"version": "1.1.0",
"license": "MIT",
@ -34649,6 +34656,26 @@
"version": "0.2.4",
"license": "MIT"
},
"node_modules/input-format": {
"version": "0.3.14",
"resolved": "https://registry.npmjs.org/input-format/-/input-format-0.3.14.tgz",
"integrity": "sha512-gHMrgrbCgmT4uK5Um5eVDUohuV9lcs95ZUUN9Px2Y0VIfjTzT2wF8Q3Z4fwLFm7c5Z2OXCm53FHoovj6SlOKdg==",
"dependencies": {
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": ">=18.1.0",
"react-dom": ">=18.1.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/internal-slot": {
"version": "1.0.7",
"license": "MIT",
@ -36786,6 +36813,11 @@
"url": "https://github.com/sponsors/dmonad"
}
},
"node_modules/libphonenumber-js": {
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz",
"integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw=="
},
"node_modules/lie": {
"version": "3.1.1",
"license": "MIT",
@ -41248,6 +41280,14 @@
"framework-utils": "^1.1.0"
}
},
"node_modules/react-currency-input-field": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/react-currency-input-field/-/react-currency-input-field-3.10.0.tgz",
"integrity": "sha512-GRmZogHh1e1LrmgXg/fKHSuRLYUnj/c/AumfvfuDMA0UX1mDR6u2NR0fzDemRdq4tNHNLucJeJ2OKCr3ehqyDA==",
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-date-picker": {
"version": "10.6.0",
"license": "MIT",
@ -42035,6 +42075,22 @@
"react-dom": "^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0"
}
},
"node_modules/react-phone-number-input": {
"version": "3.4.12",
"resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.12.tgz",
"integrity": "sha512-Raob77KdtLGm49iC6nuOX9qy6Mg16idkgC7Y1mHmvG2WBYoauHpzxYNlfmFskQKeiztrJIwPhPzBhjFwjenNCA==",
"dependencies": {
"classnames": "^2.5.1",
"country-flag-icons": "^1.5.17",
"input-format": "^0.3.10",
"libphonenumber-js": "^1.11.20",
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/react-plotly.js": {
"version": "2.6.0",
"license": "MIT",

View file

@ -91,6 +91,7 @@
"react-circular-progressbar": "^2.1.0",
"react-color": "^2.19.3",
"react-copy-to-clipboard": "^5.1.0",
"react-currency-input-field": "^3.10.0",
"react-datepicker": "^7.6.0",
"react-dates": "^21.8.0",
"react-datetime": "^3.2.0",
@ -113,6 +114,7 @@
"react-multi-select-component": "^4.3.4",
"react-pdf": "^6.2.2",
"react-phone-input-2": "^2.15.1",
"react-phone-number-input": "^3.4.12",
"react-plotly.js": "^2.6.0",
"react-qr-reader": "^2.2.1",
"react-rnd": "^10.4.1",

View file

@ -10,7 +10,11 @@ import { BOX_PADDING } from './appCanvasConstants';
const shouldAddBoxShadowAndVisibility = [
'Table',
'TextInput',
'TextArea',
'PasswordInput',
'EmailInput',
'PhoneInput',
'CurrencyInput',
'NumberInput',
'Text',
'Checkbox',
@ -87,6 +91,7 @@ const RenderWidget = ({
...{ widgetValue: value },
...{ validationObject: unResolvedValidation },
customResolveObjects: customResolvables,
componentType,
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[validateWidget, customResolvables, unResolvedValidation, resolvedValidation]

View file

@ -118,7 +118,10 @@ export const ComponentsManagerTab = ({ darkMode }) => {
'TextInput',
'NumberInput',
'PasswordInput',
'Textarea',
'TextArea',
'EmailInput',
'PhoneInput',
'CurrencyInput',
'ToggleSwitchV2',
'DropdownV2',
'MultiselectV2',

View file

@ -1 +1,9 @@
export const LEGACY_ITEMS = ['ToggleSwitch', 'DropDown', 'Multiselect', 'RadioButton', 'Datepicker', 'Modal'];
export const LEGACY_ITEMS = [
'ToggleSwitch',
'DropDown',
'Multiselect',
'RadioButton',
'Datepicker',
'Modal',
'TextArea',
];

View file

@ -0,0 +1,132 @@
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 flags from 'react-phone-number-input/flags';
import FxButton from '@/AppBuilder/CodeBuilder/Elements/FxButton';
import CodeHinter from '@/AppBuilder/CodeEditor';
import cx from 'classnames';
import { CurrencyMap } from '@/AppBuilder/Widgets/PhoneCurrency/constants';
export const CurrencyInput = ({ 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 || 'US';
const isDefaultCountryFxOn = componentMeta?.definition?.properties?.dateFormat?.fxActive || false;
const options = useMemo(() => {
return Object.keys(CurrencyMap).map((country) => ({
label: `${CurrencyMap[country].prefix} (${CurrencyMap[country].currency})`,
value: country,
}));
}, []);
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',
};
const FlagIcon = flags[optionValue];
return (
<div style={optionStyle} className={`selectedOption ${optionValue !== 'none' && 'custom-phone-input-options'}`}>
<div>{FlagIcon ? <FlagIcon style={{ width: '22px', height: '16px' }} /> : null}</div>
{label}
</div>
);
};
const getCountryDropdown = () => {
return (
<div className="mb-2">
<div className="d-flex justify-content-between mb-1">
<label className="form-label"> Default Currency</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>
);
};
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(4, 0, getCountryDropdown());
return <Accordion items={accordionItems} />;
};

View file

@ -14,8 +14,12 @@ const SHOW_ADDITIONAL_ACTIONS = [
'Text',
'Container',
'TextInput',
'TextArea',
'NumberInput',
'PasswordInput',
'EmailInput',
'PhoneInput',
'CurrencyInput',
'ToggleSwitchV2',
'Checkbox',
'DropdownV2',
@ -33,6 +37,7 @@ const PROPERTIES_VS_ACCORDION_TITLE = {
NumberInput: 'Data',
ToggleSwitchV2: 'Data',
Checkbox: 'Data',
TextArea: 'Data',
Button: 'Data',
Image: 'Data',
Container: 'Data',
@ -122,6 +127,10 @@ export const baseComponentProperties = (
'Modal',
'TextInput',
'PasswordInput',
'TextArea',
'EmailInput',
'PhoneInput',
'CurrencyInput',
'NumberInput',
'Text',
'Table',

View file

@ -0,0 +1,135 @@
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 { 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 {
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 || 'US';
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 = {
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',
};
const FlagIcon = flags[optionValue];
return (
<div style={optionStyle} className={`selectedOption ${optionValue !== 'none' && 'custom-phone-input-options'}`}>
<div>{FlagIcon ? <FlagIcon style={{ width: '22px', height: '16px' }} /> : null}</div>
{label}
</div>
);
};
const getCountryDropdown = () => {
return (
<div className="mb-2">
<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>
);
};
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} />;
};

View file

@ -8,6 +8,8 @@ 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 { CurrencyInput } from './Components/CurrencyInput/CurrencyInput.jsx';
import { Modal } from './Components/Modal';
import { ModalV2 } from './Components/ModalV2';
import { CustomComponent } from './Components/CustomComponent';
@ -36,6 +38,7 @@ import { EMPTY_ARRAY } from '@/_stores/editorStore';
import { Select } from './Components/Select';
import { deepClone } from '@/_helpers/utilities/utils.helpers';
import useStore from '@/AppBuilder/_stores/store';
// import { componentTypes } from '@/Editor/WidgetManager/components';
import { componentTypes } from '@/AppBuilder/WidgetManager/componentTypes';
import { copyComponents } from '@/AppBuilder/AppCanvas/appCanvasUtils.js';
import DatetimePickerV2 from './Components/DatetimePickerV2.jsx';
@ -66,7 +69,11 @@ const INSPECTOR_HEADER_OPTIONS = [
const NEW_REVAMPED_COMPONENTS = [
'Text',
'TextInput',
'TextArea',
'PasswordInput',
'EmailInput',
'PhoneInput',
'CurrencyInput',
'NumberInput',
'Table',
'ToggleSwitchV2',
@ -731,6 +738,10 @@ const GetAccordion = React.memo(
case 'DatePickerV2':
case 'TimePicker':
return <DatetimePickerV2 {...restProps} componentName={componentName} />;
case 'PhoneInput':
return <PhoneInput {...restProps} />;
case 'CurrencyInput':
return <CurrencyInput {...restProps} componentName={componentName} />;
default: {
return <DefaultComponent {...restProps} />;

View file

@ -43,6 +43,9 @@ export function renderCustomStyles(
componentConfig.component == 'TextInput' ||
componentConfig.component == 'NumberInput' ||
componentConfig.component == 'PasswordInput' ||
componentConfig.component == 'EmailInput' ||
componentConfig.component == 'PhoneInput' ||
componentConfig.component == 'CurrencyInput' ||
componentConfig.component == 'ToggleSwitchV2' ||
componentConfig.component == 'Checkbox' ||
componentConfig.component == 'Table' ||

View file

@ -13,6 +13,7 @@ const NEW_WIDGETS = [
'DatePickerV2',
'TimePicker',
'ModalV2',
'TextArea',
];
export const WidgetBox = ({ component, darkMode }) => {

View file

@ -58,6 +58,9 @@ import {
linkConfig,
iconConfig,
boundedBoxConfig,
emailinputConfig,
phoneinputConfig,
currencyinputConfig,
} from '../widgets';
export const widgets = [
@ -70,6 +73,9 @@ export const widgets = [
textinputConfig,
numberinputConfig,
passinputConfig,
emailinputConfig,
phoneinputConfig,
currencyinputConfig,
datepickerConfig,
datetimePickerV2Config,
datePickerV2Config,

View file

@ -0,0 +1,305 @@
export const currencyinputConfig = {
name: 'CurrencyInput',
displayName: 'Currency Input',
description: 'Currency input field',
component: 'CurrencyInput',
defaultSize: {
width: 10,
height: 40,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
label: {
type: 'code',
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Enter your number',
},
},
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 0,
},
},
decimalPlaces: {
type: 'code',
displayName: 'Decimal places',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: '2' },
},
isCountryChangeEnabled: {
type: 'toggle',
displayName: 'Enable currency change',
validation: { schema: { type: 'boolean' }, defaultValue: true },
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minValue: { type: 'code', displayName: 'Min value', placeholder: 'Enter min value' },
maxValue: { type: 'code', displayName: 'Max value', placeholder: 'Enter max value' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
accordian: 'field',
visibility: false,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setValue',
displayName: 'Set Value',
params: [
{ handle: 'value', displayName: 'value', defaultValue: '' },
{ handle: 'country', displayName: 'country', defaultValue: '' },
],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
handle: 'setBlur',
displayName: 'Set blur',
},
{
handle: 'setVisibility',
displayName: 'Set visibility',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minValue: { value: '' },
maxValue: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: { value: '0' },
label: { value: 'Label' },
placeholder: { value: 'Enter amount' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
isCountryChangeEnabled: { value: '{{true}}' },
decimalPlaces: { value: '2' },
},
events: [],
styles: {
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CFD3D859' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconHome2' },
iconVisibility: { value: false },
},
},
};

View file

@ -0,0 +1,292 @@
export const emailinputConfig = {
name: 'EmailInput',
displayName: 'Email Input',
description: 'Email input field',
component: 'EmailInput',
defaultSize: {
width: 10,
height: 40,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
label: {
type: 'code',
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Enter email',
},
},
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconMailFilled' },
accordian: 'field',
visibility: true,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setText',
displayName: 'Set text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
handle: 'setBlur',
displayName: 'Set blur',
},
{
handle: 'setVisibility',
displayName: 'Set visibility',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter email' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
},
events: [],
styles: {
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CCD1D5' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconMailFilled' },
iconVisibility: { value: true },
},
},
};

View file

@ -58,6 +58,9 @@ import { kanbanBoardConfig } from './kanbanBoard';
import { datetimePickerV2Config } from './datetimepickerV2';
import { datePickerV2Config } from './datepickerV2';
import { timePickerConfig } from './timepicker';
import { emailinputConfig } from './emailinput';
import { phoneinputConfig } from './phoneinput';
import { currencyinputConfig } from './currencyinput';
export {
buttonConfig,
@ -73,6 +76,9 @@ export {
datetimePickerV2Config,
datePickerV2Config,
timePickerConfig,
emailinputConfig,
phoneinputConfig,
currencyinputConfig,
checkboxConfig,
radiobuttonConfig, //!Depreciated
radiobuttonV2Config,

View file

@ -0,0 +1,288 @@
export const phoneinputConfig = {
name: 'PhoneInput',
displayName: 'Phone Input',
description: 'Phone input field',
component: 'PhoneInput',
defaultSize: {
width: 10,
height: 40,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
label: {
type: 'code',
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Enter your input',
},
},
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
isCountryChangeEnabled: {
type: 'toggle',
displayName: 'Enable country change',
validation: { schema: { type: 'boolean' }, defaultValue: true },
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
borderRadius: {
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setValue',
displayName: 'Set Value',
params: [
{ handle: 'value', displayName: 'value', defaultValue: '' },
{ handle: 'country', displayName: 'country', defaultValue: '' },
],
},
{
handle: 'setCountryCode',
displayName: 'Set country code',
params: [{ handle: 'countryCode', displayName: 'Country code', defaultValue: '' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
handle: 'setBlur',
displayName: 'Set blur',
},
{
handle: 'setVisibility',
displayName: 'Set visibility',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter your phone' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
isCountryChangeEnabled: { value: '{{true}}' },
},
events: [],
styles: {
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
},
},
};

View file

@ -4,7 +4,7 @@ export const textareaConfig = {
description: 'Multi-line text input',
component: 'TextArea',
defaultSize: {
width: 6,
width: 10,
height: 100,
},
others: {
@ -12,82 +12,291 @@ export const textareaConfig = {
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
value: {
label: {
type: 'code',
displayName: 'Default value',
validation: {
schema: { type: 'string' },
defaultValue: 'default text',
},
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Placeholder text',
defaultValue: 'Enter your input',
},
},
},
events: {},
styles: {
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: {
schema: { type: 'boolean' },
defaultValue: true,
},
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: {
schema: { type: 'boolean' },
defaultValue: false,
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
accordian: 'field',
visibility: false,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'code',
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'number' },
defaultValue: 4,
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value:
'ToolJet is an open-source low-code platform for building and deploying internal tools with minimal engineering efforts 🚀',
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setText',
displayName: 'Set Text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New Text' }],
displayName: 'Set text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
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',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: {
value:
'ToolJet is an open-source low-code platform for building and deploying internal tools with minimal engineering efforts 🚀',
},
placeholder: { value: 'Placeholder text' },
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter your input' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
},
events: [],
styles: {
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
borderRadius: { value: '{{4}}' },
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CFD3D859' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconHome2' },
iconVisibility: { value: false },
},
},
};

View file

@ -0,0 +1,240 @@
import React, { forwardRef } from 'react';
import Label from '@/_ui/Label';
import Loader from '@/ToolJetUI/Loader/Loader';
import * as Icons from '@tabler/icons-react';
const tinycolor = require('tinycolor2');
const RenderInput = forwardRef((props, ref) => {
return props.inputType !== 'textarea' ? <input {...props} ref={ref} /> : <textarea {...props} ref={ref} />;
});
export const BaseInput = ({
height,
styles,
properties,
darkMode,
componentName,
dataCy,
// From useInput hook
inputRef,
labelRef,
visibility,
loading,
labelWidth,
validationError,
showValidationError,
isFocused,
isMandatory,
disable,
value,
handleChange,
handleBlur,
handleFocus,
handleKeyUp,
isValid,
// Input specific props
inputType = 'text',
additionalInputProps = {},
rightIcon,
getCustomStyles,
}) => {
const {
padding,
borderRadius,
borderColor,
backgroundColor,
textColor,
boxShadow,
width,
alignment,
direction,
color,
auto,
errTextColor,
iconColor,
accentColor,
iconVisibility: showLeftIcon,
icon,
} = styles;
const { label, placeholder } = properties;
const _width = (width / 100) * 70;
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
const computedStyles = {
height: height == 36 ? (padding == 'default' ? '36px' : '40px') : padding == 'default' ? height : height + 4,
borderRadius: `${borderRadius}px`,
color: !['#1B1F24', '#000', '#000000ff'].includes(textColor)
? textColor
: disable || loading
? 'var(--text-disabled)'
: 'var(--text-primary)',
borderColor: isFocused
? accentColor != '4368E3'
? accentColor
: 'var(--primary-accent-strong)'
: borderColor != '#CCD1D5'
? borderColor
: disable || loading
? '1px solid var(--borders-disabled-on-white)'
: 'var(--borders-default)',
'--tblr-input-border-color-darker': tinycolor(borderColor).darken(24).toString(),
backgroundColor:
backgroundColor != '#fff'
? backgroundColor
: disable || loading
? darkMode
? 'var(--surfaces-app-bg-default)'
: 'var(--surfaces-surface-03)'
: 'var(--surfaces-surface-01)',
boxShadow,
padding: showLeftIcon ? '8px 10px 8px 29px' : '8px 10px',
overflow: 'hidden',
textOverflow: 'ellipsis',
};
let loaderStyle;
// for textarea loader position is fixed on top right of input box.
if (inputType !== 'textarea') {
loaderStyle = {
right:
direction === 'right' &&
defaultAlignment === 'side' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0))
? `${labelWidth + 11}px`
: '11px',
top:
defaultAlignment === 'top'
? ((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
'calc(50% + 10px)'
: '',
transform:
defaultAlignment === 'top' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
' translateY(-50%)',
zIndex: 3,
};
} else {
loaderStyle = {
right:
direction === 'right' &&
defaultAlignment === 'side' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0))
? `${labelWidth + 11}px`
: '11px',
top: defaultAlignment === 'top' ? '30px' : '10px',
transform: 'none',
zIndex: 3,
};
}
// eslint-disable-next-line import/namespace
const IconElement = Icons[icon] ?? Icons['IconHome2'];
const finalStyles = getCustomStyles ? getCustomStyles(computedStyles) : computedStyles;
return (
<>
<div
data-cy={`label-${String(componentName).toLowerCase()}`}
className={`text-input d-flex ${
defaultAlignment === 'top' &&
((width != 0 && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
? 'flex-column'
: inputType != 'textarea' && 'align-items-center'
} ${direction === 'right' && defaultAlignment === 'side' ? 'flex-row-reverse' : ''}
${direction === 'right' && defaultAlignment === 'top' ? 'text-right' : ''}
${visibility || 'invisible'}`}
style={{
position: 'relative',
whiteSpace: 'nowrap',
width: '100%',
}}
>
<Label
label={label}
width={width}
labelRef={labelRef}
darkMode={darkMode}
color={color}
defaultAlignment={defaultAlignment}
direction={direction}
auto={auto}
isMandatory={isMandatory}
_width={_width}
labelWidth={labelWidth}
top={inputType === 'textarea' && defaultAlignment === 'side' && '9px'}
/>
{showLeftIcon && (
<IconElement
data-cy={'text-input-icon'}
style={{
width: '16px',
height: '16px',
left:
direction === 'right'
? '11px'
: defaultAlignment === 'top'
? '11px'
: (label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)
? `${labelWidth + 11}px`
: '11px',
position: 'absolute',
top:
inputType === 'textarea'
? defaultAlignment === 'top'
? '38px'
: '18px'
: defaultAlignment === 'side'
? '50%'
: (label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)
? 'calc(50% + 10px)'
: '50%',
transform: 'translateY(-50%)',
color: iconColor !== '#CFD3D859' ? iconColor : 'var(--icons-weak-disabled)',
zIndex: 3,
}}
stroke={1.5}
/>
)}
<RenderInput
inputType={inputType}
data-cy={dataCy}
ref={inputRef}
type={inputType}
className={`tj-text-input-widget ${
!isValid && showValidationError ? 'is-invalid' : ''
} validation-without-icon`}
value={value}
onChange={handleChange}
onBlur={handleBlur}
onFocus={handleFocus}
onKeyUp={handleKeyUp}
disabled={disable || loading}
placeholder={placeholder}
style={finalStyles}
{...additionalInputProps}
/>
{rightIcon}
{loading && <Loader style={loaderStyle} width="16" />}
</div>
{showValidationError && visibility && (
<div
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
style={{
color: errTextColor !== '#D72D39' ? errTextColor : 'var(--status-error-strong)',
textAlign: direction == 'left' && 'end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
}}
>
{validationError}
</div>
)}
</>
);
};

View file

@ -0,0 +1,235 @@
import { useState, useRef, useEffect } from 'react';
import { useGridStore } from '@/_stores/gridStore';
//eslint-disable-next-line import/no-unresolved
import { getCountryCallingCode } from 'react-phone-number-input';
export const useInput = ({
id,
properties,
styles,
validation,
validate,
setExposedVariable,
setExposedVariables,
fireEvent,
inputType,
}) => {
const isInitialRender = useRef(true);
const inputRef = useRef();
const labelRef = useRef();
const { loadingState, disabledState, label, visibility: initialVisibility } = properties;
const isResizing = useGridStore((state) => state.resizingComponentId === id);
const [value, setValue] = useState(properties.value ?? '');
const [visibility, setVisibility] = useState(initialVisibility);
const [loading, setLoading] = useState(loadingState);
const [disable, setDisable] = useState(disabledState || loadingState);
const [validationStatus, setValidationStatus] = useState(validate(value));
const [showValidationError, setShowValidationError] = useState(false);
const [isFocused, setIsFocused] = useState(false);
const [labelWidth, setLabelWidth] = useState(0);
const [iconVisibility, setIconVisibility] = useState(false);
const [country, setCountry] = useState(properties.defaultCountry || 'US');
const { isValid, validationError } = validationStatus;
const isMandatory = validation?.mandatory ?? false;
const getCountryCallingCodeSafe = (country) => {
try {
return getCountryCallingCode(country);
} catch (error) {
return '';
}
};
useEffect(() => {
if (labelRef?.current) {
const absolutewidth = labelRef?.current?.getBoundingClientRect()?.width;
setLabelWidth(absolutewidth);
} else setLabelWidth(0);
}, [
isResizing,
styles.width,
styles.auto,
styles.alignment,
styles.iconVisibility,
label?.length,
isMandatory,
styles.padding,
styles.direction,
labelRef?.current?.getBoundingClientRect()?.width,
]);
useEffect(() => {
if (isInitialRender.current) return;
setExposedVariable('label', label);
}, [label]);
useEffect(() => {
disable !== disabledState && setDisable(disabledState);
if (isInitialRender.current) return;
setExposedVariable('isDisabled', disabledState);
}, [disabledState]);
useEffect(() => {
visibility !== properties.visibility && setVisibility(properties.visibility);
if (isInitialRender.current) return;
setExposedVariable('isVisible', properties.visibility);
}, [properties.visibility]);
useEffect(() => {
loading !== loadingState && setLoading(loadingState);
if (isInitialRender.current) return;
setExposedVariable('isLoading', loadingState);
}, [loadingState]);
useEffect(() => {
if (isInitialRender.current) return;
setExposedVariable('isMandatory', isMandatory);
}, [isMandatory]);
useEffect(() => {
if (isInitialRender.current) return;
const validationStatus = validate(value);
setValidationStatus(validationStatus);
setExposedVariable('isValid', validationStatus?.isValid);
}, [validate]);
useEffect(() => {
if (inputType === 'phone') {
let code = getCountryCallingCodeSafe(country);
setInputValue(`+${code}${properties.value}`);
} else {
setInputValue(properties.value ?? '');
}
}, [properties.value]);
useEffect(() => {
if (inputType !== 'phone') return;
setExposedVariable('setValue', async function (value, countryCode = country) {
const code = getCountryCallingCodeSafe(country);
setInputValue(`+${code}${value}`);
setCountry(countryCode);
fireEvent('onChange');
});
}, [inputType, country]);
useEffect(() => {
if (inputType !== 'currency') return;
setExposedVariable('setValue', async function (value, countryCode = country) {
setInputValue(value);
setCountry(countryCode);
fireEvent('onChange');
});
}, [inputType, country]);
useEffect(() => {
const exposedVariables = {
...(inputType !== 'phone' && {
setText: async function (text) {
setInputValue(text);
fireEvent('onChange');
},
}),
clear: async function () {
setInputValue('');
fireEvent('onChange');
},
setFocus: async function () {
inputRef.current.focus();
},
setBlur: async function () {
inputRef.current.blur();
},
setVisibility: async function (state) {
setVisibility(state);
setExposedVariable('isVisible', state);
},
setDisable: async function (disable) {
setDisable(disable);
setExposedVariable('isDisabled', disable);
},
setLoading: async function (loading) {
setLoading(loading);
setExposedVariable('isLoading', loading);
},
label,
isValid,
value: properties.value ?? '',
isMandatory,
isLoading: loading,
isVisible: visibility,
isDisabled: disable,
};
setExposedVariables(exposedVariables);
isInitialRender.current = false;
}, []);
const setInputValue = (value) => {
setValue(value);
setExposedVariable('value', value);
const validationStatus = validate(value);
setValidationStatus(validationStatus);
setExposedVariable('isValid', validationStatus?.isValid);
};
const handleChange = (e) => {
setInputValue(e.target.value);
fireEvent('onChange');
};
const handlePhoneCurrencyInputChange = (value) => {
setInputValue(value);
fireEvent('onChange');
};
const handleBlur = (e) => {
setShowValidationError(true);
setIsFocused(false);
e.stopPropagation();
fireEvent('onBlur');
};
const handleFocus = (e) => {
setIsFocused(true);
e.stopPropagation();
setTimeout(() => {
fireEvent('onFocus');
}, 0);
};
const handleKeyUp = (e) => {
if (e.key === 'Enter') {
setInputValue(e.target.value);
fireEvent('onEnterPressed');
}
};
return {
inputRef,
labelRef,
value,
visibility,
loading,
disable,
country,
setCountry,
validationStatus,
showValidationError,
isFocused,
labelWidth,
iconVisibility,
setIconVisibility,
isValid,
validationError,
isMandatory,
setInputValue,
handlePhoneCurrencyInputChange,
handleChange,
handleBlur,
handleFocus,
handleKeyUp,
};
};

View file

@ -0,0 +1,12 @@
import React from 'react';
import { BaseInput } from './BaseComponents/BaseInput';
import { useInput } from './BaseComponents/hooks/useInput';
export const EmailInput = (props) => {
const inputLogic = useInput(props);
const additionalInputProps = {
autocomplete: 'email',
name: 'email',
};
return <BaseInput {...props} {...inputLogic} inputType="email" additionalInputProps={additionalInputProps} />;
};

View file

@ -97,6 +97,9 @@ export function generateUIComponents(JSONSchema, advanced, componentName = '') {
if (uiComponentsDraft?.length > 0 && uiComponentsDraft[index * 2 + 1]) {
switch (typeResolver(value?.type)) {
case 'TextInput':
case 'EmailInput':
case 'PhoneInput':
case 'CurrencyInput':
if (value?.styles?.backgroundColor)
uiComponentsDraft[index * 2 + 1]['definition']['styles']['backgroundColor'] =
value?.styles?.backgroundColor;
@ -127,6 +130,15 @@ export function generateUIComponents(JSONSchema, advanced, componentName = '') {
if (value?.value) uiComponentsDraft[index * 2 + 1]['definition']['properties']['value'] = value?.value;
if (value?.placeholder)
uiComponentsDraft[index * 2 + 1]['definition']['properties']['placeholder'] = value?.placeholder;
if (value?.defaultCountry && ['PhoneInput', 'CurrencyInput'].includes(typeResolver(value?.type))) {
uiComponentsDraft[index * 2 + 1]['definition']['properties']['defaultCountry'] = value?.defaultCountry;
}
if (value?.defaultCountry && typeResolver(value?.type) === 'CurrencyInput') {
uiComponentsDraft[index * 2 + 1]['definition']['properties']['decimalPlaces'] = value?.decimalPlaces;
}
// prevent label from showing up in text input, because it is already shown in the text component. (Defaults to "Label" if not updated explicitly with an empty string)
uiComponentsDraft[index * 2 + 1]['definition']['properties']['label'] = '';
break;
@ -482,6 +494,12 @@ const typeResolver = (type) => {
return 'DropDown';
case 'button':
return 'Button';
case 'emailinput':
return 'EmailInput';
case 'phoneinput':
return 'PhoneInput';
case 'currencyinput':
return 'CurrencyInput';
case 'text':
return 'Text';
case 'number':

View file

@ -26,6 +26,7 @@ const RenderSchema = ({ component, parent, id, onOptionChange, onOptionsChange,
return validateWidget({
...{ widgetValue: value },
...{ validationObject: component.definition.validation },
componentType: component?.component,
});
},
[component.definition.validation]

View file

@ -0,0 +1,169 @@
import React, { useEffect } from 'react';
import { BaseInput } from './BaseComponents/BaseInput';
import { useInput } from './BaseComponents/hooks/useInput';
import SolidIcon from '@/_ui/Icon/SolidIcons';
export const NumberInput = (props) => {
const inputLogic = useInput({
...props,
properties: {
...props.properties,
value: Number(parseFloat(props.properties.value).toFixed(props.properties.decimalPlaces)),
},
});
const handleChange = (e) => {
if (e.target.value === '') {
inputLogic.setInputValue(null);
props.fireEvent('onChange');
} else {
const newValue = Number(parseFloat(e.target.value));
inputLogic.setInputValue(newValue);
if (!isNaN(newValue)) {
props.fireEvent('onChange');
}
}
};
const handleBlur = (e) => {
const value = Number(parseFloat(e.target.value).toFixed(props.properties.decimalPlaces));
inputLogic.setInputValue(value);
e.stopPropagation();
props.fireEvent('onBlur');
inputLogic.setIsFocused(false);
};
const handleIncrement = (e) => {
e.preventDefault();
const newValue = (inputLogic.value || 0) + 1;
inputLogic.setInputValue(newValue);
if (!isNaN(newValue)) {
props.fireEvent('onChange');
}
};
const handleDecrement = (e) => {
e.preventDefault();
const newValue = (inputLogic.value || 0) - 1;
inputLogic.setInputValue(newValue);
if (!isNaN(newValue)) {
props.fireEvent('onChange');
}
};
// Override the base input styles to account for number controls
const getCustomStyles = (baseStyles) => {
return {
...baseStyles,
paddingRight: '20px', // Make room for number controls
};
};
const numberControls = !inputLogic.isResizing && (
<div
style={{
position: 'absolute',
right:
inputLogic.labelWidth === 0
? 0
: props.styles.alignment === 'side' && props.styles.direction === 'right'
? `${inputLogic.labelWidth}px`
: 0,
top: 0,
height: '100%',
width: '20px',
display: 'flex',
flexDirection: 'column',
zIndex: 2,
}}
>
<div
onClick={handleIncrement}
style={{
height: '50%',
cursor: 'pointer',
position: 'relative',
}}
>
<SolidIcon
width={props.styles.padding === 'default' ? `${props.height / 2 - 1}px` : `${props.height / 2 + 1}px`}
height={props.styles.padding === 'default' ? `${props.height / 2 - 1}px` : `${props.height / 2 + 1}px`}
fill={'var(--icons-default)'}
style={{
position: 'absolute',
top:
props.styles.alignment === 'top' && props.properties.label?.length > 0 && props.styles.width > 0
? '21px'
: '1px',
right: '1px',
borderLeft:
inputLogic.disable || inputLogic.loading
? '1px solid var(--borders-weak-disabled)'
: '1px solid var(--borders-default)',
borderBottom:
inputLogic.disable || inputLogic.loading
? '1px solid var(--borders-weak-disabled)'
: '.5px solid var(--borders-default)',
borderTopRightRadius: props.styles.borderRadius - 1,
backgroundColor: 'transparent',
}}
className="numberinput-up-arrow arrow number-input-arrow"
name="TriangleDownCenter"
/>
</div>
<div
onClick={handleDecrement}
style={{
height: '50%',
cursor: 'pointer',
position: 'relative',
}}
>
<SolidIcon
fill={'var(--icons-default)'}
style={{
position: 'absolute',
right: '1px',
bottom: '1px',
borderLeft:
inputLogic.disable || inputLogic.loading
? '1px solid var(--borders-weak-disabled)'
: '1px solid var(--borders-default)',
borderTop:
inputLogic.disable || inputLogic.loading
? '1px solid var(--borders-weak-disabled)'
: '.5px solid var(--borders-default)',
borderBottomRightRadius: props.styles.borderRadius - 1,
backgroundColor: 'transparent',
}}
width={props.styles.padding === 'default' ? `${props.height / 2 - 1}px` : `${props.height / 2 + 1}px`}
height={props.styles.padding === 'default' ? `${props.height / 2 - 1}px` : `${props.height / 2 + 1}px`}
className="numberinput-down-arrow arrow number-input-arrow"
name="TriangleUpCenter"
/>
</div>
</div>
);
useEffect(() => {
if (isNaN(inputLogic.value) || inputLogic.value === '') {
props.setExposedVariable('value', null);
}
}, [inputLogic.value]);
return (
<BaseInput
{...props}
{...inputLogic}
inputType="number"
handleChange={handleChange}
handleBlur={handleBlur}
additionalInputProps={{
min: props.validation?.minValue ?? null,
max: props.validation?.maxValue ?? null,
}}
rightIcon={numberControls}
getCustomStyles={getCustomStyles}
/>
);
};

View file

@ -0,0 +1,43 @@
import React from 'react';
import { BaseInput } from './BaseComponents/BaseInput';
import { useInput } from './BaseComponents/hooks/useInput';
import SolidIcon from '@/_ui/Icon/SolidIcons';
export const PasswordInput = (props) => {
const inputLogic = useInput(props);
const toggleVisibility = () => {
inputLogic.setIconVisibility(!inputLogic.iconVisibility);
};
const passwordIcon = (
<div
onClick={toggleVisibility}
style={{
width: '16px',
height: '16px',
position: 'absolute',
right: '11px',
display: 'flex',
zIndex: 3,
}}
>
<SolidIcon
width={16}
fill={'var(--icons-weak-disabled)'}
className="password-component-eye"
name={!inputLogic.iconVisibility ? 'eye1' : 'eyedisable'}
/>
</div>
);
return (
<BaseInput
{...props}
{...inputLogic}
inputType={inputLogic.iconVisibility ? 'text' : 'password'}
additionalInputProps={{ autoComplete: 'new-password' }}
rightIcon={!inputLogic.loading && passwordIcon}
/>
);
};

View file

@ -0,0 +1,141 @@
import React, { useEffect, useRef, useState } from 'react';
import Select from 'react-select';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { CustomMenuList } from './CustomMenuList';
import { CustomOption } from './CustomOption';
import { CustomValueContainer } from './CustomValueContainer';
export const CountrySelect = ({ value, onChange, options, ...rest }) => {
const {
isCountryChangeEnabled,
isCurrencyInput = false,
disabledState,
borderRadius,
isValid,
showValidationError,
computedStyles,
darkMode,
filterOption,
} = rest;
const [menuIsOpen, setMenuIsOpen] = useState(false);
const dropdownRef = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setMenuIsOpen(false);
}
};
if (menuIsOpen) {
document.addEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [menuIsOpen]);
const customStyles = {
container: (provided) => ({
...provided,
minWidth: !isCountryChangeEnabled || disabledState ? '77px' : isCurrencyInput ? '87px' : '93px',
width: !isCountryChangeEnabled || disabledState ? '77px' : isCurrencyInput ? '87px' : '93px',
height: '100%',
}),
valueContainer: (provided) => ({
...provided,
padding: '0px',
}),
control: (provided) => ({
...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: `${computedStyles?.backgroundColor} !important`,
}),
menu: (provided) => ({
...provided,
width: '208px',
height: '236px',
borderRadius: '8px',
marginTop: '2px',
boxShadow: 'var(--elevation-400-box-shadow)',
}),
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
onClick={() => {
if (disabledState || !isCountryChangeEnabled) return;
setMenuIsOpen((prev) => !prev);
}}
ref={dropdownRef}
>
<Select
options={options}
value={value}
styles={customStyles}
onChange={onChange}
hasSearch={false}
useCustomStyles={true}
menuPortalTarget={document.body}
isCurrencyInput={isCurrencyInput}
isCountryChangeEnabled={isCountryChangeEnabled}
{...(filterOption && { filterOption })}
components={{
MenuList: CustomMenuList,
Option: (props) => <CustomOption {...props} />,
ValueContainer: (props) => <CustomValueContainer {...props} />, // Add this line
IndicatorSeparator: () => null,
DropdownIndicator:
!isCountryChangeEnabled || disabledState
? () => null
: () => (
<div style={{ position: 'relative', display: 'flex', left: '-2px' }}>
{menuIsOpen ? (
<SolidIcon name="TriangleDownCenter" width="16" height="16" />
) : (
<SolidIcon name="TriangleUpCenter" width="16" height="16" />
)}
</div>
),
}}
darkMode={darkMode}
isDisabled={disabledState}
menuIsOpen={menuIsOpen}
onMenuOpen={() => setMenuIsOpen(true)}
onMenuClose={() => setMenuIsOpen(false)}
/>
</div>
);
};

View file

@ -0,0 +1,266 @@
import React, { useEffect, useMemo, useRef } from 'react';
import { default as ReactCurrencyInput } from 'react-currency-input-field';
import { useInput } from '../BaseComponents/hooks/useInput';
import Loader from '@/ToolJetUI/Loader/Loader';
import Label from '@/_ui/Label';
import { CountrySelect } from './CountrySelect';
import { CurrencyMap } from './constants';
const tinycolor = require('tinycolor2');
export const CurrencyInput = (props) => {
const { properties, styles, componentName, darkMode, setExposedVariables, fireEvent } = props;
const transformedProps = {
...props,
inputType: 'currency',
};
const inputLogic = useInput(transformedProps);
const {
inputRef,
labelRef,
visibility,
loading,
disable,
showValidationError,
handlePhoneCurrencyInputChange,
isFocused,
labelWidth,
isValid,
validationError,
isMandatory,
handleBlur,
handleFocus,
value,
country,
setCountry,
} = inputLogic;
const { label, placeholder, decimalPlaces, isCountryChangeEnabled, defaultCountry = 'US' } = properties;
const handleKeyUp = (e) => {
if (e.key === 'Enter') {
fireEvent('onEnterPressed');
}
};
const options = useMemo(() => {
return Object.keys(CurrencyMap).map((ele) => ({
label: `${CurrencyMap[ele].prefix} (${CurrencyMap[ele].currency})`,
value: ele,
country: CurrencyMap[ele].country,
}));
}, []);
const onInputValueChange = (value) => {
handlePhoneCurrencyInputChange(value);
setExposedVariables({
country: country,
formattedValue: `${CurrencyMap[country]?.prefix} ${inputRef.current?.value}`,
});
};
const {
textColor,
backgroundColor,
alignment,
width,
direction,
auto,
color,
borderColor,
accentColor,
errTextColor,
boxShadow,
borderRadius,
} = styles;
const _width = (width / 100) * 70;
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
const disabledState = disable || loading;
const isInitialRender = useRef(true);
const computedStyles = {
height: '100%',
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 loaderStyle = {
right:
direction === 'right' &&
defaultAlignment === 'side' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0))
? `${labelWidth + 11}px`
: '11px',
top:
defaultAlignment === 'top'
? ((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
'calc(50% + 10px)'
: '',
transform:
defaultAlignment === 'top' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
' translateY(-50%)',
zIndex: 3,
};
useEffect(() => {
if (!isInitialRender.current) {
setCountry(defaultCountry);
}
}, [defaultCountry]);
useEffect(() => {
if (!isInitialRender.current) {
setExposedVariables({
country: country,
formattedValue: `${CurrencyMap[country]?.prefix} ${value}`,
});
}
}, [country]);
useEffect(() => {
if (isInitialRender.current) {
setExposedVariables({
country: country,
formattedValue: `${CurrencyMap[country]?.prefix} ${value}`,
value: value,
setCountryCode: (code) => {
setCountry(code);
},
});
isInitialRender.current = false;
}
}, []);
return (
<>
<div
data-cy={`label-${String(componentName).toLowerCase()}`}
className={`text-input d-flex phone-input-widget ${
defaultAlignment === 'top' &&
((width != 0 && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
? 'flex-column'
: 'align-items-center'
} ${direction === 'right' && defaultAlignment === 'side' ? 'flex-row-reverse' : ''}
${direction === 'right' && defaultAlignment === 'top' ? 'text-right' : ''}
${visibility || 'invisible'}`}
style={{
position: 'relative',
whiteSpace: 'nowrap',
width: '100%',
height: '100%',
}}
>
<Label
label={label}
width={width}
labelRef={labelRef}
darkMode={darkMode}
color={color}
defaultAlignment={defaultAlignment}
direction={direction}
auto={auto}
isMandatory={isMandatory}
_width={_width}
labelWidth={labelWidth}
/>
<div className="d-flex h-100 w-100" style={{ boxShadow, borderRadius: `${borderRadius}px` }}>
<CountrySelect
value={{
label: `${CurrencyMap?.[country]?.prefix} (${CurrencyMap?.[country]?.currency})`,
value: country,
country: CurrencyMap?.[country]?.country,
}}
options={options}
isCountryChangeEnabled={isCountryChangeEnabled}
disabledState={disabledState}
borderRadius={borderRadius}
isValid={isValid}
filterOption={(option, inputValue) => {
return (
option.label.toLowerCase().includes(inputValue.toLowerCase()) ||
option.data.country.toLowerCase().includes(inputValue.toLowerCase())
);
}}
computedStyles={computedStyles}
showValidationError={showValidationError}
darkMode={darkMode}
isCurrencyInput={true}
onChange={(selectedOption) => {
if (selectedOption) {
setCountry(selectedOption.value);
fireEvent('onChange');
setExposedVariables({
country: selectedOption.value,
formattedValue: `${CurrencyMap[selectedOption.value]?.prefix} ${selectedOption.value}`,
});
}
}}
/>
<ReactCurrencyInput
ref={inputRef}
placeholder={placeholder}
className={`tj-text-input-widget ${
!isValid && showValidationError ? 'is-invalid' : ''
} validation-without-icon`}
value={value}
decimalsLimit={decimalPlaces}
style={computedStyles}
data-ignore-hover={true}
onValueChange={(newVal) => {
if (newVal === value) return;
onInputValueChange(newVal);
}}
// prefix={`${CurrencyMap?.[country]?.prefix || ''} `}
prefix={''}
disabled={disabledState}
onBlur={handleBlur}
onFocus={handleFocus}
onKeyUp={handleKeyUp}
/>
</div>
{loading && <Loader style={loaderStyle} width="16" />}
</div>
{showValidationError && visibility && (
<div
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
style={{
color: errTextColor !== '#D72D39' ? errTextColor : 'var(--status-error-strong)',
textAlign: direction == 'left' && 'end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
}}
>
{validationError}
</div>
)}
</>
);
};

View file

@ -0,0 +1,51 @@
import React from 'react';
import { components } from 'react-select';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import cx from 'classnames';
export 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>
);
};

View file

@ -0,0 +1,38 @@
import React from 'react';
import { components } from 'react-select';
// eslint-disable-next-line import/no-unresolved
import flags from 'react-phone-number-input/flags';
import TickV3 from '@/_ui/Icon/solidIcons/TickV3';
export const CustomOption = (props) => {
const { label, value: optionValue, isSelected } = props;
const { darkMode } = props?.selectProps || {};
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%',
};
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>
);
};

View file

@ -0,0 +1,49 @@
import React from 'react';
import { components } from 'react-select';
// eslint-disable-next-line import/no-unresolved
import flags from 'react-phone-number-input/flags';
import Planet from '@/_ui/Icon/bulkIcons/Planet';
import { getCountryCallingCodeSafe } from './utils';
import { CurrencyMap } from './constants';
export const CustomValueContainer = ({ getValue, ...props }) => {
const selectedValue = getValue()[0];
const country = selectedValue?.value;
const { isCurrencyInput, isCountryChangeEnabled } = props?.selectProps || {};
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%',
marginLeft: isCountryChangeEnabled ? '4px' : '0px',
}}
>
<>
<FlagIcon style={{ height: '16px' }} />{' '}
<span style={{ marginLeft: '6px' }}>
{isCurrencyInput ? ` ${CurrencyMap?.[country]?.prefix}` : ` +${countryCode}`}
</span>
</>
</div>
) : (
<div
style={{
display: 'flex',
marginLeft: isCurrencyInput ? '6px' : '17px',
marginTop: '4px',
justifyContent: 'center',
}}
>
<Planet width={24} height={24} />
</div>
)}
</components.ValueContainer>
);
};

View file

@ -0,0 +1,254 @@
import React, { useEffect, useMemo, useRef } from 'react';
// eslint-disable-next-line import/no-unresolved
import Input, { getCountries, getCountryCallingCode } from 'react-phone-number-input/input';
import { getCountryCallingCodeSafe } from './utils';
// eslint-disable-next-line import/no-unresolved
import en from 'react-phone-number-input/locale/en';
import 'react-phone-number-input/style.css';
import { useInput } from '../BaseComponents/hooks/useInput';
import Loader from '@/ToolJetUI/Loader/Loader';
import Label from '@/_ui/Label';
import { CountrySelect } from './CountrySelect';
const tinycolor = require('tinycolor2');
export const PhoneInput = (props) => {
const { properties, styles, componentName, darkMode, setExposedVariables, fireEvent } = props;
const transformedProps = {
...props,
inputType: 'phone',
};
const inputLogic = useInput(transformedProps);
const {
inputRef,
labelRef,
visibility,
loading,
disable,
showValidationError,
isFocused,
labelWidth,
isValid,
validationError,
isMandatory,
handleBlur,
handleFocus,
value,
handlePhoneCurrencyInputChange,
country,
setCountry,
} = inputLogic;
const { label, placeholder, isCountryChangeEnabled, defaultCountry = 'US' } = properties;
const {
textColor,
backgroundColor,
alignment,
width,
direction,
auto,
color,
borderColor,
accentColor,
errTextColor,
boxShadow,
borderRadius,
} = styles;
const _width = (width / 100) * 70;
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
const isInitialRender = useRef(true);
const options = useMemo(
() =>
getCountries()
.map((country) => ({
label: `${en[country]} +${getCountryCallingCodeSafe(country)}`,
value: country,
}))
.sort((a, b) => a.label.localeCompare(b.label)),
[]
);
const onInputValueChange = (value) => {
setExposedVariables({
country: country,
countryCode: `+${getCountryCallingCodeSafe(country)}`,
formattedValue: `+${getCountryCallingCodeSafe(country)} ${inputRef.current?.value}`,
});
handlePhoneCurrencyInputChange(value);
};
const handleKeyUp = (e) => {
if (e.key === 'Enter') {
fireEvent('onEnterPressed');
}
};
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;
}
}, []);
useEffect(() => {
if (!isInitialRender.current) {
setCountry(defaultCountry);
}
}, [defaultCountry]);
const disabledState = disable || loading;
const loaderStyle = {
right:
direction === 'right' &&
defaultAlignment === 'side' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0))
? `${labelWidth + 11}px`
: '11px',
top:
defaultAlignment === 'top'
? ((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
'calc(50% + 10px)'
: '',
transform:
defaultAlignment === 'top' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
' translateY(-50%)',
zIndex: 3,
};
const computedStyles = {
height: '100%',
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',
};
return (
<>
<div
data-cy={`label-${String(componentName).toLowerCase()}`}
className={`text-input d-flex phone-input-widget ${
defaultAlignment === 'top' &&
((width != 0 && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
? 'flex-column'
: 'align-items-center'
} ${direction === 'right' && defaultAlignment === 'side' ? 'flex-row-reverse' : ''}
${direction === 'right' && defaultAlignment === 'top' ? 'text-right' : ''}
${visibility || 'invisible'}`}
style={{
position: 'relative',
whiteSpace: 'nowrap',
width: '100%',
height: '100%',
}}
>
<Label
label={label}
width={width}
labelRef={labelRef}
darkMode={darkMode}
color={color}
defaultAlignment={defaultAlignment}
direction={direction}
auto={auto}
isMandatory={isMandatory}
_width={_width}
labelWidth={labelWidth}
/>
<div className="d-flex h-100 w-100" style={{ boxShadow, borderRadius: `${borderRadius}px` }}>
<CountrySelect
value={{ label: `${en[country]} +${getCountryCallingCodeSafe(country)}`, value: country }}
options={options}
isCountryChangeEnabled={isCountryChangeEnabled}
disabledState={disabledState}
borderRadius={borderRadius}
isValid={isValid}
computedStyles={computedStyles}
showValidationError={showValidationError}
darkMode={darkMode}
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 && (
<div
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
style={{
color: errTextColor !== '#D72D39' ? errTextColor : 'var(--status-error-strong)',
textAlign: direction == 'left' && 'end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
}}
>
{validationError}
</div>
)}
</>
);
};

View file

@ -0,0 +1,597 @@
export const CurrencyMap = {
AE: {
currency: 'AED',
prefix: 'د.إ.',
country: 'United Arab Emirates',
},
AF: {
currency: 'AFN',
prefix: '؋',
country: 'Afghanistan',
},
AL: {
currency: 'ALL',
prefix: 'Lek',
country: 'Albania',
},
AM: {
currency: 'AMD',
prefix: 'դր.',
country: 'Armenia',
},
AR: {
currency: 'ARS',
prefix: '$',
country: 'Argentina',
},
AU: {
currency: 'AUD',
prefix: '$',
country: 'Australia',
},
AZ: {
currency: 'AZN',
prefix: 'ман.',
country: 'Azerbaijan',
},
BA: {
currency: 'BAM',
prefix: 'KM',
country: 'Bosnia and Herzegovina',
},
BD: {
currency: 'BDT',
prefix: '৳',
country: 'Bangladesh',
},
BG: {
currency: 'BGN',
prefix: 'лв.',
country: 'Bulgaria',
},
BH: {
currency: 'BHD',
prefix: 'د.ب.',
country: 'Bahrain',
},
BI: {
currency: 'BIF',
prefix: 'FBu',
country: 'Burundi',
},
BN: {
currency: 'BND',
prefix: '$',
country: 'Brunei Darussalam',
},
BO: {
currency: 'BOB',
prefix: 'Bs',
country: 'Bolivia',
},
BR: {
currency: 'BRL',
prefix: 'R$',
country: 'Brazil',
},
BV: {
currency: 'NOK',
prefix: 'kr',
country: 'Bouvet Island',
},
BW: {
currency: 'BWP',
prefix: 'P',
country: 'Botswana',
},
BY: {
currency: 'BYR',
prefix: 'BYR',
country: 'Belarus',
},
BZ: {
currency: 'BZD',
prefix: '$',
country: 'Belize',
},
CA: {
currency: 'CAD',
prefix: '$',
country: 'Canada',
},
CD: {
currency: 'CDF',
prefix: 'FrCD',
country: 'Congo, Democratic Republic of the',
},
CF: {
currency: 'XAF',
prefix: 'FCFA',
country: 'Central African Republic',
},
CH: {
currency: 'CHF',
prefix: 'CHF',
country: 'Switzerland',
},
CL: {
currency: 'CLP',
prefix: '$',
country: 'Chile',
},
CN: {
currency: 'CNY',
prefix: 'CN¥',
country: 'China',
},
CO: {
currency: 'COP',
prefix: '$',
country: 'Colombia',
},
CR: {
currency: 'CRC',
prefix: '₡',
country: 'Costa Rica',
},
CV: {
currency: 'CVE',
prefix: 'CV$',
country: 'Cape Verde',
},
CZ: {
currency: 'CZK',
prefix: 'Kč',
country: 'Czech Republic',
},
DJ: {
currency: 'DJF',
prefix: 'Fdj',
country: 'Djibouti',
},
DK: {
currency: 'DKK',
prefix: 'kr',
country: 'Denmark',
},
DO: {
currency: 'DOP',
prefix: 'RD$',
country: 'Dominican Republic',
},
DZ: {
currency: 'DZD',
prefix: 'د.ج.',
country: 'Algeria',
},
EG: {
currency: 'EGP',
prefix: 'ج.م.',
country: 'Egypt',
},
ER: {
currency: 'ERN',
prefix: 'Nfk',
country: 'Eritrea',
},
EU: {
currency: 'EUR',
prefix: '€',
country: 'European Union',
},
ET: {
currency: 'ETB',
prefix: 'Br',
country: 'Ethiopia',
},
GB: {
currency: 'GBP',
prefix: '£',
country: 'United Kingdom',
},
GE: {
currency: 'GEL',
prefix: 'GEL',
country: 'Georgia',
},
GH: {
currency: 'GHS',
prefix: 'GH₵',
country: 'Ghana',
},
GN: {
currency: 'GNF',
prefix: 'FG',
country: 'Guinea',
},
GT: {
currency: 'GTQ',
prefix: 'Q',
country: 'Guatemala',
},
HK: {
currency: 'HKD',
prefix: '$',
country: 'Hong Kong',
},
HN: {
currency: 'HNL',
prefix: 'L',
country: 'Honduras',
},
HR: {
currency: 'HRK',
prefix: 'kn',
country: 'Croatia',
},
HU: {
currency: 'HUF',
prefix: 'Ft',
country: 'Hungary',
},
ID: {
currency: 'IDR',
prefix: 'Rp',
country: 'Indonesia',
},
IL: {
currency: 'ILS',
prefix: '₪',
country: 'Israel',
},
IN: {
currency: 'INR',
prefix: '₹',
country: 'India',
},
IQ: {
currency: 'IQD',
prefix: 'د.ع.',
country: 'Iraq',
},
IR: {
currency: 'IRR',
prefix: '﷼',
country: 'Iran, Islamic Republic of',
},
IS: {
currency: 'ISK',
prefix: 'kr',
country: 'Iceland',
},
JM: {
currency: 'JMD',
prefix: '$',
country: 'Jamaica',
},
JO: {
currency: 'JOD',
prefix: 'د.أ.',
country: 'Jordan',
},
JP: {
currency: 'JPY',
prefix: '¥',
country: 'Japan',
},
KE: {
currency: 'KES',
prefix: 'Ksh',
country: 'Kenya',
},
KH: {
currency: 'KHR',
prefix: '៛',
country: 'Cambodia',
},
KM: {
currency: 'KMF',
prefix: 'FC',
country: 'Comoros',
},
KR: {
currency: 'KRW',
prefix: '₩',
country: 'Korea, Republic of',
},
KW: {
currency: 'KWD',
prefix: 'د.ك.',
country: 'Kuwait',
},
KZ: {
currency: 'KZT',
prefix: 'тңг.',
country: 'Kazakhstan',
},
LB: {
currency: 'LBP',
prefix: 'ل.ل.',
country: 'Lebanon',
},
LK: {
currency: 'LKR',
prefix: 'SL Re',
country: 'Sri Lanka',
},
LT: {
currency: 'LTL',
prefix: 'Lt',
country: 'Lithuania',
},
LY: {
currency: 'LYD',
prefix: 'د.ل.',
country: 'Libya',
},
MA: {
currency: 'MAD',
prefix: 'د.م.',
country: 'Morocco',
},
MD: {
currency: 'MDL',
prefix: 'MDL',
country: 'Moldova, Republic of',
},
MG: {
currency: 'MGA',
prefix: 'MGA',
country: 'Madagascar',
},
MK: {
currency: 'MKD',
prefix: 'MKD',
country: 'Macedonia, the Former Yugoslav Republic of',
},
MM: {
currency: 'MMK',
prefix: 'K',
country: 'Myanmar',
},
MO: {
currency: 'MOP',
prefix: 'MOP$',
country: 'Macao',
},
MU: {
currency: 'MUR',
prefix: 'MURs',
country: 'Mauritius',
},
MX: {
currency: 'MXN',
prefix: '$',
country: 'Mexico',
},
MY: {
currency: 'MYR',
prefix: 'RM',
country: 'Malaysia',
},
MZ: {
currency: 'MZN',
prefix: 'MTn',
country: 'Mozambique',
},
NA: {
currency: 'NAD',
prefix: 'N$',
country: 'Namibia',
},
NG: {
currency: 'NGN',
prefix: '₦',
country: 'Nigeria',
},
NI: {
currency: 'NIO',
prefix: 'C$',
country: 'Nicaragua',
},
NO: {
currency: 'NOK',
prefix: 'kr',
country: 'Norway',
},
NP: {
currency: 'NPR',
prefix: 'नेरू',
country: 'Nepal',
},
NZ: {
currency: 'NZD',
prefix: '$',
country: 'New Zealand',
},
OM: {
currency: 'OMR',
prefix: 'ر.ع.',
country: 'Oman',
},
PA: {
currency: 'PAB',
prefix: 'B/.',
country: 'Panama',
},
PE: {
currency: 'PEN',
prefix: 'S/.',
country: 'Peru',
},
PH: {
currency: 'PHP',
prefix: '₱',
country: 'Philippines',
},
PK: {
currency: 'PKR',
prefix: '₨',
country: 'Pakistan',
},
PL: {
currency: 'PLN',
prefix: 'zł',
country: 'Poland',
},
PY: {
currency: 'PYG',
prefix: '₲',
country: 'Paraguay',
},
QA: {
currency: 'QAR',
prefix: 'ر.ق.',
country: 'Qatar',
},
RO: {
currency: 'RON',
prefix: 'RON',
country: 'Romania',
},
RS: {
currency: 'RSD',
prefix: 'дин.',
country: 'Serbia',
},
RU: {
currency: 'RUB',
prefix: '₽',
country: 'Russian Federation',
},
RW: {
currency: 'RWF',
prefix: 'FR',
country: 'Rwanda',
},
SA: {
currency: 'SAR',
prefix: 'ر.س.',
country: 'Saudi Arabia',
},
SD: {
currency: 'SDG',
prefix: 'SDG',
country: 'Sudan',
},
SE: {
currency: 'SEK',
prefix: 'kr',
country: 'Sweden',
},
SG: {
currency: 'SGD',
prefix: '$',
country: 'Singapore',
},
SJ: {
currency: 'NOK',
prefix: 'kr',
country: 'Svalbard and Jan Mayen',
},
SN: {
currency: 'XOF',
prefix: 'CFA',
country: 'Senegal',
},
SO: {
currency: 'SOS',
prefix: 'Ssh',
country: 'Somalia',
},
SY: {
currency: 'SYP',
prefix: 'ل.س.',
country: 'Syrian Arab Republic',
},
TH: {
currency: 'THB',
prefix: '฿',
country: 'Thailand',
},
TN: {
currency: 'TND',
prefix: 'د.ت.',
country: 'Tunisia',
},
TO: {
currency: 'TOP',
prefix: 'T$',
country: 'Tonga',
},
TR: {
currency: 'TRY',
prefix: 'TL',
country: 'Turkey',
},
TT: {
currency: 'TTD',
prefix: '$',
country: 'Trinidad and Tobago',
},
TW: {
currency: 'TWD',
prefix: 'NT$',
country: 'Taiwan, Province of China',
},
TZ: {
currency: 'TZS',
prefix: 'TSh',
country: 'United Republic of Tanzania',
},
UA: {
currency: 'UAH',
prefix: '₴',
country: 'Ukraine',
},
UG: {
currency: 'UGX',
prefix: 'USh',
country: 'Uganda',
},
US: {
currency: 'USD',
prefix: '$',
country: 'United States',
},
UY: {
currency: 'UYU',
prefix: '$',
country: 'Uruguay',
},
UZ: {
currency: 'UZS',
prefix: 'UZS',
country: 'Uzbekistan',
},
VE: {
currency: 'VEF',
prefix: 'Bs.F.',
country: 'Venezuela',
},
VN: {
currency: 'VND',
prefix: '₫',
country: 'Vietnam',
},
VU: {
currency: 'VUV',
prefix: 'VT',
country: 'Vanuatu',
},
YE: {
currency: 'YER',
prefix: 'ر.ي.',
country: 'Yemen',
},
ZA: {
currency: 'ZAR',
prefix: 'R',
country: 'South Africa',
},
ZM: {
currency: 'ZMK',
prefix: 'ZK',
country: 'Zambia',
},
};

View file

@ -0,0 +1,10 @@
// eslint-disable-next-line import/no-unresolved
import { getCountryCallingCode } from 'react-phone-number-input/input';
export const getCountryCallingCodeSafe = (country) => {
try {
return getCountryCallingCode(country);
} catch (error) {
return '';
}
};

View file

@ -0,0 +1,256 @@
import React, { useEffect, useMemo, useRef } from 'react';
// eslint-disable-next-line import/no-unresolved
import Input, { getCountries, getCountryCallingCode } from 'react-phone-number-input/input';
import { getCountryCallingCodeSafe } from './utils';
// eslint-disable-next-line import/no-unresolved
import en from 'react-phone-number-input/locale/en';
import 'react-phone-number-input/style.css';
import { useInput } from '../BaseComponents/hooks/useInput';
import Loader from '@/ToolJetUI/Loader/Loader';
import Label from '@/_ui/Label';
import { CountrySelect } from './CountrySelect';
const tinycolor = require('tinycolor2');
export const PhoneInput = (props) => {
const { properties, styles, componentName, darkMode, setExposedVariables, fireEvent } = props;
const transformedProps = {
...props,
inputType: 'phone',
};
const inputLogic = useInput(transformedProps);
const {
inputRef,
labelRef,
visibility,
loading,
disable,
showValidationError,
isFocused,
labelWidth,
isValid,
validationError,
isMandatory,
handleBlur,
handleFocus,
value,
handlePhoneInputChange,
country,
setCountry,
} = inputLogic;
const { label, placeholder, isCountryChangeEnabled, defaultCountry = 'US' } = properties;
const {
textColor,
backgroundColor,
alignment,
width,
direction,
auto,
color,
borderColor,
accentColor,
errTextColor,
boxShadow,
borderRadius,
} = styles;
const _width = (width / 100) * 70;
const defaultAlignment = alignment === 'side' || alignment === 'top' ? alignment : 'side';
const isInitialRender = useRef(true);
const options = useMemo(
() =>
getCountries()
.map((country) => ({
label: `${en[country]} +${getCountryCallingCodeSafe(country)}`,
value: country,
}))
.sort((a, b) => a.label.localeCompare(b.label)),
[]
);
const onInputValueChange = (value) => {
setExposedVariables({
country: country,
countryCode: `+${getCountryCallingCodeSafe(country)}`,
formattedValue: `+${getCountryCallingCodeSafe(country)} ${inputRef.current?.value}`,
});
handlePhoneInputChange(value);
};
const handleKeyUp = (e) => {
if (e.key === 'Enter') {
fireEvent('onEnterPressed');
}
};
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;
}
}, []);
useEffect(() => {
if (!isInitialRender.current) {
setCountry(defaultCountry);
}
}, [defaultCountry]);
const disabledState = disable || loading;
const loaderStyle = {
right:
direction === 'right' &&
defaultAlignment === 'side' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0))
? `${labelWidth + 11}px`
: '11px',
top:
defaultAlignment === 'top'
? ((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
'calc(50% + 10px)'
: '',
transform:
defaultAlignment === 'top' &&
((label?.length > 0 && width > 0) || (auto && width == 0 && label && label?.length != 0)) &&
' translateY(-50%)',
zIndex: 3,
};
const computedStyles = {
height: '100%',
borderRadius: `0px ${borderRadius}px ${borderRadius}px 0px`,
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 countryCode = getCountryCallingCodeSafe(country);
console.log(countryCode);
return (
<>
<div
data-cy={`label-${String(componentName).toLowerCase()}`}
className={`text-input d-flex phone-input-widget ${
defaultAlignment === 'top' &&
((width != 0 && label?.length != 0) || (auto && width == 0 && label && label?.length != 0))
? 'flex-column'
: 'align-items-center'
} ${direction === 'right' && defaultAlignment === 'side' ? 'flex-row-reverse' : ''}
${direction === 'right' && defaultAlignment === 'top' ? 'text-right' : ''}
${visibility || 'invisible'}`}
style={{
position: 'relative',
whiteSpace: 'nowrap',
width: '100%',
height: '100%',
}}
>
<Label
label={label}
width={width}
labelRef={labelRef}
darkMode={darkMode}
color={color}
defaultAlignment={defaultAlignment}
direction={direction}
auto={auto}
isMandatory={isMandatory}
_width={_width}
labelWidth={labelWidth}
/>
<div className="d-flex h-100 w-100" style={{ boxShadow, borderRadius: `${borderRadius}px` }}>
<CountrySelect
value={{ label: `${en[country]} +${getCountryCallingCodeSafe(country)}`, value: country }}
options={options}
isCountryChangeEnabled={isCountryChangeEnabled}
disabledState={disabledState}
borderRadius={borderRadius}
isValid={isValid}
computedStyles={computedStyles}
showValidationError={showValidationError}
darkMode={darkMode}
onChange={(selectedOption) => {
if (selectedOption) {
setCountry(selectedOption.value);
}
}}
/>
<Input
ref={inputRef}
{...(countryCode && { country: country })}
// 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 && (
<div
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
style={{
color: errTextColor !== '#D72D39' ? errTextColor : 'var(--status-error-strong)',
textAlign: direction == 'left' && 'end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
}}
>
{validationError}
</div>
)}
</>
);
};

View file

@ -0,0 +1,9 @@
import React from 'react';
import { BaseInput } from './BaseComponents/BaseInput';
import { useInput } from './BaseComponents/hooks/useInput';
export const TextArea = (props) => {
const inputLogic = useInput(props);
return <BaseInput {...props} {...inputLogic} inputType="textarea" />;
};

View file

@ -0,0 +1,9 @@
import React from 'react';
import { BaseInput } from './BaseComponents/BaseInput';
import { useInput } from './BaseComponents/hooks/useInput';
export const TextInput = (props) => {
const inputLogic = useInput(props);
return <BaseInput {...props} {...inputLogic} inputType="text" />;
};

View file

@ -4,9 +4,9 @@ import { Text } from '@/Editor/Components/Text';
// import { Table } from '@/Editor/Components/Table/Table';
import { Table } from '@/AppBuilder/Widgets/Table/Table';
import { TextInput } from '@/Editor/Components/TextInput';
import { NumberInput } from '@/Editor/Components/NumberInput';
import { TextArea } from '@/Editor/Components/TextArea';
import { TextInput } from '@/AppBuilder/Widgets/TextInput';
import { TextArea } from '@/AppBuilder/Widgets/TextArea';
import { NumberInput } from '@/AppBuilder/Widgets/NumberInput';
import { RichTextEditor } from '@/Editor/Components/RichTextEditor';
import { DropDown } from '@/Editor/Components/DropDown';
import { DropdownV2 } from '@/Editor/Components/DropdownV2/DropdownV2';
@ -29,7 +29,10 @@ import { RadioButtonV2 } from '@/Editor/Components/RadioButtonV2/RadioButtonV2';
import { StarRating } from '@/Editor/Components/StarRating';
import { Divider } from '@/Editor/Components/Divider';
import { FilePicker } from '@/Editor/Components/FilePicker';
import { PasswordInput } from '@/Editor/Components/PasswordInput';
import { PasswordInput } from '@/AppBuilder/Widgets/PasswordInput';
import { EmailInput } from '@/AppBuilder/Widgets/EmailInput';
import { PhoneInput } from '@/AppBuilder/Widgets/PhoneCurrency/PhoneInput';
import { CurrencyInput } from '@/AppBuilder/Widgets/PhoneCurrency/CurrencyInput';
// import { Calendar } from '@/Editor/Components/Calendar';
// import { Listview } from '@/Editor/Components/Listview';
import { IFrame } from '@/Editor/Components/IFrame';
@ -118,6 +121,9 @@ export const AllComponents = {
Divider,
FilePicker,
PasswordInput,
EmailInput,
PhoneInput,
CurrencyInput,
Calendar,
IFrame,
CodeEditor,

View file

@ -439,7 +439,7 @@ export const createComponentsSlice = (set, get) => ({
}
},
validateWidget: ({ validationObject, widgetValue, customResolveObjects }) => {
validateWidget: ({ validationObject, widgetValue, customResolveObjects, componentType }) => {
const { getResolvedValue } = get();
let isValid = true;
let validationError = null;
@ -455,6 +455,17 @@ export const createComponentsSlice = (set, get) => ({
validationRegex = typeof validationRegex === 'string' ? validationRegex : '';
const re = new RegExp(validationRegex, 'g');
if (componentType === 'EmailInput' && widgetValue) {
const validationRegex = '^(?!.*\\.\\.)([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})$';
const emailRegex = new RegExp(validationRegex, 'g');
if (!emailRegex.test(widgetValue)) {
return {
isValid: false,
validationError: 'Input should be a valid email',
};
}
}
if (!re.test(widgetValue)) {
return {
isValid: false,
@ -1833,6 +1844,9 @@ export const createComponentsSlice = (set, get) => ({
![
'TextInput',
'PasswordInput',
'EmailInput',
'PhoneInput',
'CurrencyInput',
'NumberInput',
'DropdownV2',
'MultiselectV2',
@ -1841,6 +1855,7 @@ export const createComponentsSlice = (set, get) => ({
'DaterangePicker',
'DatePickerV2',
'TimePicker',
'TextArea',
].includes(componentType)
) {
return layoutData?.height;

View file

@ -1,62 +0,0 @@
import React, { useState, useEffect, useRef } from 'react';
export const TextArea = function TextArea({
height,
properties,
styles,
setExposedVariable,
setExposedVariables,
dataCy,
}) {
const isInitialRender = useRef(true);
const [value, setValue] = useState(properties.value);
useEffect(() => {
if (isInitialRender.current) return;
setValue(properties.value);
setExposedVariable('value', properties.value);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [properties.value]);
useEffect(() => {
const exposedVariables = {
setText: async function (text) {
setValue(text);
setExposedVariable('value', text);
},
clear: async function () {
setValue('');
setExposedVariable('value', '');
},
value: properties.value,
};
setExposedVariables(exposedVariables);
setValue(properties.value);
isInitialRender.current = false;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<textarea
disabled={styles.disabledState}
onChange={(e) => {
setValue(e.target.value);
setExposedVariable('value', e.target.value);
}}
type="text"
className="form-control textarea"
placeholder={properties.placeholder}
style={{
height,
resize: 'none',
display: styles.visibility ? '' : 'none',
borderRadius: `${styles.borderRadius}px`,
boxShadow: styles.boxShadow,
}}
value={value}
data-cy={dataCy}
></textarea>
);
};

View file

@ -1,4 +1,4 @@
import { widgets } from './widgetConfig';
import { widgets } from '../../AppBuilder/WidgetManager/configs/widgetConfig';
const universalProps = {
properties: {},

View file

@ -4,7 +4,7 @@ export const textareaConfig = {
description: 'Multi-line text input',
component: 'TextArea',
defaultSize: {
width: 6,
width: 10,
height: 100,
},
others: {
@ -12,82 +12,291 @@ export const textareaConfig = {
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
value: {
label: {
type: 'code',
displayName: 'Default value',
validation: {
schema: { type: 'string' },
defaultValue: 'default text',
},
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Placeholder text',
defaultValue: 'Enter your input',
},
},
},
events: {},
styles: {
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: {
schema: { type: 'boolean' },
defaultValue: true,
},
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: {
schema: { type: 'boolean' },
defaultValue: false,
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
accordian: 'field',
visibility: false,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'code',
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'number' },
defaultValue: 4,
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value:
'ToolJet is an open-source low-code platform for building and deploying internal tools with minimal engineering efforts 🚀',
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setText',
displayName: 'Set Text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New Text' }],
displayName: 'Set text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
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',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: {
value:
'ToolJet is an open-source low-code platform for building and deploying internal tools with minimal engineering efforts 🚀',
},
placeholder: { value: 'Placeholder text' },
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter your input' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
},
events: [],
styles: {
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
borderRadius: { value: '{{4}}' },
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CFD3D859' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconHome2' },
iconVisibility: { value: false },
},
},
};

View file

@ -4,4 +4,5 @@ export const LEGACY_ITEMS = [
'MultiselectLegacy',
'RadioButtonLegacy',
'ModalLegacy',
'TextareaLegacy',
];

View file

@ -2486,7 +2486,9 @@ export const setMultipleComponentsSelected = (components) => {
export const calculateMoveableBoxHeight = (componentType, layoutData, stylesDefinition, label) => {
// Early return for non input components
if (!['TextInput', 'PasswordInput', 'NumberInput', 'DropdownV2', 'MultiselectV2'].includes(componentType)) {
if (
!['TextInput', 'PasswordInput', 'NumberInput', 'DropdownV2', 'MultiselectV2', 'TextArea'].includes(componentType)
) {
return layoutData?.height;
}
const { alignment = { value: null }, width = { value: null }, auto = { value: null } } = stylesDefinition ?? {};

View file

@ -4,7 +4,6 @@ import { Text } from '@/Editor/Components/Text';
import { Table } from '@/Editor/Components/Table/Table';
import { TextInput } from '@/Editor/Components/TextInput';
import { NumberInput } from '@/Editor/Components/NumberInput';
import { TextArea } from '@/Editor/Components/TextArea';
import { Container } from '@/Editor/Components/Container';
import { Tabs } from '@/Editor/Components/Tabs';
import { RichTextEditor } from '@/Editor/Components/RichTextEditor';
@ -81,7 +80,6 @@ export const AllComponents = {
TextInput,
NumberInput,
Table,
TextArea,
Container,
Tabs,
RichTextEditor,

View file

@ -15766,6 +15766,11 @@ tbody {
/* Set the desired width */
}
textarea.tj-text-input-widget{
resize: none !important;
overflow-y: auto !important;
}
.tj-text-input-widget {
border: 1px solid var(--borders-default);
background-color: var(--surfaces-surface-01);
@ -15777,7 +15782,7 @@ tbody {
background-color: var(--surfaces-surface-03);
}
&:hover:not(:focus) {
&:hover:not(:focus):not([data-ignore-hover="true"]) {
border: 1px solid var(--tblr-input-border-color-darker) !important;
}
@ -18664,6 +18669,16 @@ section.ai-message-prompt-input-wrapper {
}
}
.phone-input-widget {
.tj-text-input-widget.is-invalid {
border-left: none !important;
}
input[type="tel"] {
border-top-left-radius: '0px' !important;
border-bottom-left-radius: '0px' !important;
}
}
.single-line-codehinter-input {
.cm-editor {

View file

@ -0,0 +1,27 @@
import React from 'react';
const Globe = ({ fill = '#C1C8CD', width = '25', className = '', viewBox = '0 0 25 25' }) => (
<svg
width={width}
height={width}
viewBox={viewBox}
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M10.0007 0.833252C10.1655 0.833252 10.3293 0.837601 10.492 0.84619V4.38097C10.492 4.77954 10.3363 5.15899 10.0635 5.43657C9.79126 5.71355 9.42517 5.86654 9.04648 5.86667C8.63079 5.86643 8.21968 5.95133 7.83775 6.1159C7.45585 6.28045 7.11138 6.52109 6.82442 6.82273C6.53749 7.12434 6.31388 7.48082 6.16617 7.87057C6.02018 8.25585 5.95111 8.66633 5.96263 9.07827V10.9704C5.96263 11.1675 5.92448 11.3623 5.85066 11.5436C5.77687 11.7249 5.66908 11.8887 5.53411 12.026C5.39917 12.1633 5.23975 12.2715 5.06535 12.345C4.89095 12.4185 4.70456 12.4561 4.51666 12.4561H1.1669C0.950015 11.6744 0.834106 10.8507 0.834106 9.9999C0.834106 4.9373 4.93815 0.833252 10.0007 0.833252Z"
fill="#ACB2B9"
/>
<path
d="M10.0008 19.1667C6.40942 19.1667 3.30045 17.1013 1.79675 14.0937H4.51669C4.92362 14.0937 5.32619 14.012 5.70134 13.854C6.07645 13.6959 6.41635 13.4645 6.702 13.1739C6.98763 12.8832 7.21346 12.539 7.36728 12.1611C7.52111 11.7832 7.60009 11.3787 7.60009 10.9705V9.06607C7.60009 9.0572 7.59995 9.04833 7.59966 9.03946C7.59313 8.83827 7.62646 8.63807 7.69738 8.45092C7.76829 8.26379 7.87513 8.09405 8.0108 7.95142C8.14645 7.80883 8.30811 7.6963 8.48572 7.61977C8.66331 7.54325 8.85367 7.50407 9.04561 7.50419C9.868 7.50419 10.6542 7.17162 11.2314 6.58439C11.808 5.99764 12.1295 5.20482 12.1295 4.38106V1.08179C15.6979 1.93038 18.4579 4.86524 19.0496 8.52639H13.5132C13.489 8.52639 13.4648 8.52747 13.4407 8.5296C12.6407 8.60066 11.8929 8.96189 11.3459 9.54756C10.7984 10.1337 10.492 10.9024 10.492 11.7031C10.492 12.5039 10.7984 13.2725 11.3459 13.8587C11.8929 14.4443 12.6407 14.8056 13.4407 14.8767C13.4679 14.8791 13.4952 14.8802 13.5225 14.8799C13.6425 14.8784 13.7613 14.9005 13.8716 14.9441C13.982 14.9877 14.0811 15.0518 14.1639 15.1318C14.2467 15.2118 14.3114 15.306 14.3552 15.4086C14.3989 15.511 14.4212 15.6203 14.4212 15.7302V18.0323C13.1104 18.7552 11.6036 19.1667 10.0008 19.1667Z"
fill="#ACB2B9"
/>
<path
d="M16.0586 16.8795C17.9267 15.2333 19.119 12.8381 19.1659 10.1636H13.553C13.1621 10.2061 12.8033 10.3858 12.5425 10.665C12.2749 10.9514 12.1294 11.3219 12.1294 11.7029C12.1294 12.0839 12.2749 12.4544 12.5425 12.7408C12.8032 13.0199 13.1619 13.1996 13.5527 13.2422C13.8677 13.2446 14.18 13.3051 14.4733 13.4209C14.7816 13.5428 15.0635 13.7237 15.3019 13.9542C15.5404 14.1847 15.7307 14.4602 15.861 14.7653C15.9912 15.0702 16.0586 15.3982 16.0586 15.7299V16.8795Z"
fill="#ACB2B9"
/>
</svg>
);
export default Globe;

View file

@ -118,6 +118,7 @@ import Lock from './Lock.jsx';
import AddTemplate from './AddTemplate.jsx';
import InviteCollaborator from './InviteCollabarator.jsx';
import CloseIcon from './CloseIcon.jsx';
import Planet from './Planet.jsx';
const Icon = (props) => {
switch (props.name) {
@ -361,7 +362,8 @@ const Icon = (props) => {
return <Comments {...props} />;
case 'checkcircle':
return <CheckCircle {...props} />;
case 'planet':
return <Planet {...props} />;
default:
return <Apps {...props} />;
}

View file

@ -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 {

View file

@ -0,0 +1,64 @@
import { Component } from 'src/entities/component.entity';
import { processDataInBatches } from '@helpers/migration.helper';
import { EntityManager, MigrationInterface, QueryRunner } from 'typeorm';
export class MoveVisibilityDisabledStatesToPropertiesTextarea1736448327127 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const batchSize = 100;
const entityManager = queryRunner.manager;
await processDataInBatches(
entityManager,
async (entityManager: EntityManager) => {
return await entityManager.find(Component, {
where: { type: 'TextArea' },
order: { createdAt: 'ASC' },
});
},
async (entityManager: EntityManager, components: Component[]) => {
await this.processUpdates(entityManager, components);
},
batchSize
);
}
private async processUpdates(entityManager, components) {
for (const component of components) {
const properties = component.properties;
const styles = component.styles;
const general = component.general;
const generalStyles = component.generalStyles;
const validation = component.validation;
if (styles.visibility) {
properties.visibility = styles?.visibility;
delete styles?.visibility;
}
if (styles.disabledState) {
properties.disabledState = styles?.disabledState;
delete styles?.disabledState;
}
if (generalStyles?.boxShadow) {
styles.boxShadow = generalStyles?.boxShadow;
delete generalStyles?.boxShadow;
}
// Label and value
if (properties.label == undefined || null) {
properties.label = '';
}
await entityManager.update(Component, component.id, {
properties,
styles,
general,
generalStyles,
validation,
});
}
}
public async down(queryRunner: QueryRunner): Promise<void> {}
}

View file

@ -0,0 +1,305 @@
export const currencyinputConfig = {
name: 'CurrencyInput',
displayName: 'Currency Input',
description: 'Currency input field',
component: 'CurrencyInput',
defaultSize: {
width: 10,
height: 40,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
label: {
type: 'code',
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Enter your number',
},
},
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 0,
},
},
decimalPlaces: {
type: 'code',
displayName: 'Decimal places',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: '2' },
},
isCountryChangeEnabled: {
type: 'toggle',
displayName: 'Enable currency change',
validation: { schema: { type: 'boolean' }, defaultValue: true },
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minValue: { type: 'code', displayName: 'Min value', placeholder: 'Enter min value' },
maxValue: { type: 'code', displayName: 'Max value', placeholder: 'Enter max value' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
accordian: 'field',
visibility: false,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setValue',
displayName: 'Set Value',
params: [
{ handle: 'value', displayName: 'value', defaultValue: '' },
{ handle: 'country', displayName: 'country', defaultValue: '' },
],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
handle: 'setBlur',
displayName: 'Set blur',
},
{
handle: 'setVisibility',
displayName: 'Set visibility',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minValue: { value: '' },
maxValue: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: { value: '0' },
label: { value: 'Label' },
placeholder: { value: 'Enter amount' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
isCountryChangeEnabled: { value: '{{true}}' },
decimalPlaces: { value: '2' },
},
events: [],
styles: {
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CFD3D859' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconHome2' },
iconVisibility: { value: false },
},
},
};

View file

@ -0,0 +1,292 @@
export const emailinputConfig = {
name: 'EmailInput',
displayName: 'Email Input',
description: 'Email input field',
component: 'EmailInput',
defaultSize: {
width: 10,
height: 40,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
label: {
type: 'code',
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Enter email',
},
},
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconMailFilled' },
accordian: 'field',
visibility: true,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setText',
displayName: 'Set text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
handle: 'setBlur',
displayName: 'Set blur',
},
{
handle: 'setVisibility',
displayName: 'Set visibility',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter email' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
},
events: [],
styles: {
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CCD1D5' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconMailFilled' },
iconVisibility: { value: true },
},
},
};

View file

@ -58,6 +58,9 @@ import { kanbanBoardConfig } from './kanbanBoard';
import { datetimePickerV2Config } from './datetimepickerV2';
import { datePickerV2Config } from './datepickerV2';
import { timePickerConfig } from './timepicker';
import { emailinputConfig } from './emailinput';
import { phoneinputConfig } from './phoneinput';
import {currencyinputConfig} from './currencyinput';
const widgets = {
buttonConfig,
@ -73,12 +76,15 @@ const widgets = {
datetimePickerV2Config,
datePickerV2Config,
timePickerConfig,
emailinputConfig,
phoneinputConfig,
currencyinputConfig,
checkboxConfig,
radiobuttonConfig, //!Depreciated
radiobuttonV2Config,
toggleswitchConfig, //!Depreciated
toggleSwitchV2Config,
textareaConfig,
textareaConfig, //! Deprecated
daterangepickerConfig,
textConfig,
imageConfig,

View file

@ -0,0 +1,288 @@
export const phoneinputConfig = {
name: 'PhoneInput',
displayName: 'Phone Input',
description: 'Phone input field',
component: 'PhoneInput',
defaultSize: {
width: 10,
height: 40,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
label: {
type: 'code',
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Enter your input',
},
},
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
isCountryChangeEnabled: {
type: 'toggle',
displayName: 'Enable country change',
validation: { schema: { type: 'boolean' }, defaultValue: true },
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
borderRadius: {
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setValue',
displayName: 'Set Value',
params: [
{ handle: 'value', displayName: 'value', defaultValue: '' },
{ handle: 'country', displayName: 'country', defaultValue: '' },
],
},
{
handle: 'setCountryCode',
displayName: 'Set country code',
params: [{ handle: 'countryCode', displayName: 'Country code', defaultValue: '' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
handle: 'setBlur',
displayName: 'Set blur',
},
{
handle: 'setVisibility',
displayName: 'Set visibility',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter your phone' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
isCountryChangeEnabled: { value: '{{true}}' },
},
events: [],
styles: {
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
},
},
};

View file

@ -4,7 +4,7 @@ export const textareaConfig = {
description: 'Multi-line text input',
component: 'TextArea',
defaultSize: {
width: 6,
width: 10,
height: 100,
},
others: {
@ -12,82 +12,291 @@ export const textareaConfig = {
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
value: {
label: {
type: 'code',
displayName: 'Default value',
validation: {
schema: { type: 'string' },
defaultValue: 'default text',
},
displayName: 'Label',
validation: { schema: { type: 'string' }, defaultValue: 'Label' },
},
placeholder: {
type: 'code',
displayName: 'Placeholder',
validation: {
schema: { type: 'string' },
defaultValue: 'Placeholder text',
defaultValue: 'Enter your input',
},
},
},
events: {},
styles: {
value: {
type: 'code',
displayName: 'Default value',
validation: {
schema: {
type: 'string',
},
defaultValue: 'Default value',
},
},
loadingState: {
type: 'toggle',
displayName: 'Loading state',
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
visibility: {
type: 'toggle',
displayName: 'Visibility',
validation: {
schema: { type: 'boolean' },
defaultValue: true,
},
validation: { schema: { type: 'boolean' }, defaultValue: true },
section: 'additionalActions',
},
disabledState: {
type: 'toggle',
displayName: 'Disable',
validation: {
schema: { type: 'boolean' },
defaultValue: false,
validation: { schema: { type: 'boolean' }, defaultValue: false },
section: 'additionalActions',
},
tooltip: {
type: 'code',
displayName: 'Tooltip',
validation: { schema: { type: 'string' }, defaultValue: 'Tooltip text' },
section: 'additionalActions',
placeholder: 'Enter tooltip text',
},
},
validation: {
mandatory: { type: 'toggle', displayName: 'Make this field mandatory' },
regex: { type: 'code', displayName: 'Regex', placeholder: '^[a-zA-Z0-9_ -]{3,16}$' },
minLength: { type: 'code', displayName: 'Min length', placeholder: 'Enter min length' },
maxLength: { type: 'code', displayName: 'Max length', placeholder: 'Enter max length' },
customRule: {
type: 'code',
displayName: 'Custom validation',
placeholder: `{{components.text2.text=='yes'&&'valid'}}`,
},
},
events: {
onChange: { displayName: 'On change' },
onEnterPressed: { displayName: 'On enter pressed' },
onFocus: { displayName: 'On focus' },
onBlur: { displayName: 'On blur' },
},
styles: {
color: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'label',
},
alignment: {
type: 'switch',
displayName: 'Alignment',
validation: { schema: { type: 'string' }, defaultValue: 'side' },
options: [
{ displayName: 'Side', value: 'side' },
{ displayName: 'Top', value: 'top' },
],
accordian: 'label',
},
direction: {
type: 'switch',
displayName: '',
validation: { schema: { type: 'string' }, defaultValue: 'left' },
showLabel: false,
isIcon: true,
options: [
{ displayName: 'alignleftinspector', value: 'left', iconName: 'alignleftinspector' },
{ displayName: 'alignrightinspector', value: 'right', iconName: 'alignrightinspector' },
],
accordian: 'label',
isFxNotRequired: true,
},
width: {
type: 'slider',
displayName: 'Width',
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
auto: {
type: 'checkbox',
displayName: 'auto',
showLabel: false,
validation: { schema: { type: 'boolean' }, defaultValue: true },
accordian: 'label',
conditionallyRender: {
key: 'alignment',
value: 'side',
},
isFxNotRequired: true,
},
backgroundColor: {
type: 'color',
displayName: 'Background',
validation: { schema: { type: 'string' }, defaultValue: '#fff' },
accordian: 'field',
},
borderColor: {
type: 'color',
displayName: 'Border',
validation: { schema: { type: 'string' }, defaultValue: '#CCD1D5' },
accordian: 'field',
},
accentColor: {
type: 'color',
displayName: 'Accent',
validation: { schema: { type: 'string' }, defaultValue: '#4368E3' },
accordian: 'field',
},
textColor: {
type: 'color',
displayName: 'Text',
validation: { schema: { type: 'string' }, defaultValue: '#1B1F24' },
accordian: 'field',
},
errTextColor: {
type: 'color',
displayName: 'Error text',
validation: { schema: { type: 'string' }, defaultValue: '#D72D39' },
accordian: 'field',
},
icon: {
type: 'icon',
displayName: 'Icon',
validation: { schema: { type: 'string' }, defaultValue: 'IconHome2' },
accordian: 'field',
visibility: false,
},
iconColor: {
type: 'color',
displayName: 'Icon color',
validation: { schema: { type: 'string' }, defaultValue: '#CFD3D859' },
accordian: 'field',
visibility: false,
showLabel: false,
},
borderRadius: {
type: 'code',
type: 'numberInput',
displayName: 'Border radius',
validation: { schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] }, defaultValue: 6 },
accordian: 'field',
},
boxShadow: {
type: 'boxShadow',
displayName: 'Box Shadow',
validation: {
schema: { type: 'number' },
defaultValue: 4,
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: '0px 0px 0px 0px #00000040',
},
accordian: 'field',
},
padding: {
type: 'switch',
displayName: 'Padding',
validation: {
schema: { type: 'union', schemas: [{ type: 'string' }, { type: 'number' }] },
defaultValue: 'default',
},
isFxNotRequired: true,
options: [
{ displayName: 'Default', value: 'default' },
{ displayName: 'None', value: 'none' },
],
accordian: 'container',
},
},
exposedVariables: {
value:
'ToolJet is an open-source low-code platform for building and deploying internal tools with minimal engineering efforts 🚀',
value: '',
isMandatory: false,
isVisible: true,
isDisabled: false,
isLoading: false,
},
actions: [
{
handle: 'setText',
displayName: 'Set Text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New Text' }],
displayName: 'Set text',
params: [{ handle: 'text', displayName: 'text', defaultValue: 'New text' }],
},
{
handle: 'clear',
displayName: 'Clear',
},
{
handle: 'setFocus',
displayName: 'Set focus',
},
{
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',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setDisable',
displayName: 'Set disable',
params: [{ handle: 'disable', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
{
handle: 'setLoading',
displayName: 'Set loading',
params: [{ handle: 'loading', displayName: 'Value', defaultValue: '{{false}}', type: 'toggle' }],
},
],
definition: {
validation: {
mandatory: { value: '{{false}}' },
regex: { value: '' },
minLength: { value: '' },
maxLength: { value: '' },
customRule: { value: '' },
},
others: {
showOnDesktop: { value: '{{true}}' },
showOnMobile: { value: '{{false}}' },
},
properties: {
value: {
value:
'ToolJet is an open-source low-code platform for building and deploying internal tools with minimal engineering efforts 🚀',
},
placeholder: { value: 'Placeholder text' },
value: { value: '' },
label: { value: 'Label' },
placeholder: { value: 'Enter your input' },
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
loadingState: { value: '{{false}}' },
tooltip: { value: '' },
},
events: [],
styles: {
visibility: { value: '{{true}}' },
disabledState: { value: '{{false}}' },
borderRadius: { value: '{{4}}' },
textColor: { value: '#1B1F24' },
borderColor: { value: '#CCD1D5' },
accentColor: { value: '#4368E3' },
errTextColor: { value: '#D72D39' },
borderRadius: { value: '{{6}}' },
backgroundColor: { value: '#fff' },
iconColor: { value: '#CFD3D859' },
direction: { value: 'left' },
width: { value: '{{33}}' },
alignment: { value: 'side' },
color: { value: '#1B1F24' },
auto: { value: '{{true}}' },
padding: { value: 'default' },
boxShadow: { value: '0px 0px 0px 0px #00000040' },
icon: { value: 'IconHome2' },
iconVisibility: { value: false },
},
},
};