2019-11-13 07:00:25 +00:00
|
|
|
import React from "react";
|
|
|
|
|
import styled from "styled-components";
|
2021-02-08 07:30:01 +00:00
|
|
|
import {
|
|
|
|
|
getBorderCSSShorthand,
|
|
|
|
|
IntentColors,
|
|
|
|
|
labelStyle,
|
|
|
|
|
} from "constants/DefaultTheme";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
|
2019-10-30 10:23:20 +00:00
|
|
|
import {
|
|
|
|
|
Intent,
|
|
|
|
|
NumericInput,
|
|
|
|
|
IconName,
|
|
|
|
|
InputGroup,
|
|
|
|
|
Button,
|
2019-10-31 05:28:11 +00:00
|
|
|
Label,
|
2020-01-14 09:50:42 +00:00
|
|
|
Classes,
|
2020-01-21 12:48:42 +00:00
|
|
|
ControlGroup,
|
2020-02-06 07:01:25 +00:00
|
|
|
TextArea,
|
2019-10-30 10:23:20 +00:00
|
|
|
} from "@blueprintjs/core";
|
2021-07-15 12:50:01 +00:00
|
|
|
import { InputType, InputTypes } from "widgets/InputWidget";
|
2020-01-21 12:48:42 +00:00
|
|
|
import { WIDGET_PADDING } from "constants/WidgetConstants";
|
2020-02-06 07:01:25 +00:00
|
|
|
import { Colors } from "constants/Colors";
|
2020-03-06 09:45:21 +00:00
|
|
|
import ErrorTooltip from "components/editorComponents/ErrorTooltip";
|
|
|
|
|
import _ from "lodash";
|
2021-03-13 14:24:45 +00:00
|
|
|
import {
|
|
|
|
|
createMessage,
|
|
|
|
|
INPUT_WIDGET_DEFAULT_VALIDATION_ERROR,
|
|
|
|
|
} from "constants/messages";
|
2021-07-15 12:50:01 +00:00
|
|
|
import Dropdown, { DropdownOption } from "components/ads/Dropdown";
|
|
|
|
|
import { CurrencyTypeOptions, CurrencyOptionProps } from "constants/Currency";
|
|
|
|
|
import Icon, { IconSize } from "components/ads/Icon";
|
2019-10-30 10:23:20 +00:00
|
|
|
/**
|
|
|
|
|
* All design system component specific logic goes here.
|
2020-03-06 09:45:21 +00:00
|
|
|
* Ex. Blueprint has a separate numeric input and text input so switching between them goes here
|
2019-10-30 10:23:20 +00:00
|
|
|
* Ex. To set the icon as currency, blue print takes in a set of defined types
|
|
|
|
|
* All generic logic like max characters for phone numbers should be 10, should go in the widget
|
|
|
|
|
*/
|
|
|
|
|
|
2020-12-24 04:32:25 +00:00
|
|
|
const InputComponentWrapper = styled((props) => (
|
2020-03-13 07:24:03 +00:00
|
|
|
<ControlGroup {..._.omit(props, ["hasError", "numeric"])} />
|
2020-03-06 09:45:21 +00:00
|
|
|
))<{
|
2020-03-13 07:24:03 +00:00
|
|
|
numeric: boolean;
|
2020-03-06 09:45:21 +00:00
|
|
|
multiline: string;
|
|
|
|
|
hasError: boolean;
|
2021-07-15 12:50:01 +00:00
|
|
|
allowCurrencyChange?: boolean;
|
|
|
|
|
inputType: InputType;
|
2020-03-06 09:45:21 +00:00
|
|
|
}>`
|
2020-01-14 09:50:42 +00:00
|
|
|
&&&& {
|
2021-07-15 12:50:01 +00:00
|
|
|
.currency-type-filter {
|
|
|
|
|
width: 40px;
|
|
|
|
|
height: 32px;
|
|
|
|
|
position: absolute;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
left: 0;
|
|
|
|
|
z-index: 16;
|
|
|
|
|
svg {
|
|
|
|
|
path {
|
|
|
|
|
fill: ${(props) => props.theme.colors.icon?.hover};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-06 07:01:25 +00:00
|
|
|
.${Classes.INPUT} {
|
2021-07-15 12:50:01 +00:00
|
|
|
${(props) =>
|
|
|
|
|
props.inputType === InputTypes.CURRENCY &&
|
|
|
|
|
props.allowCurrencyChange &&
|
|
|
|
|
`
|
|
|
|
|
padding-left: 45px;`};
|
|
|
|
|
${(props) =>
|
|
|
|
|
props.inputType === InputTypes.CURRENCY &&
|
|
|
|
|
!props.allowCurrencyChange &&
|
|
|
|
|
`
|
|
|
|
|
padding-left: 35px;`};
|
2020-01-17 12:34:58 +00:00
|
|
|
box-shadow: none;
|
2020-03-06 09:45:21 +00:00
|
|
|
border: 1px solid;
|
|
|
|
|
border-color: ${({ hasError }) =>
|
|
|
|
|
hasError ? IntentColors.danger : Colors.GEYSER_LIGHT};
|
2021-02-08 07:30:01 +00:00
|
|
|
border-radius: 0;
|
2020-12-24 04:32:25 +00:00
|
|
|
height: ${(props) => (props.multiline === "true" ? "100%" : "inherit")};
|
2020-03-06 09:45:21 +00:00
|
|
|
width: 100%;
|
2020-12-24 04:32:25 +00:00
|
|
|
${(props) =>
|
2020-03-13 07:24:03 +00:00
|
|
|
props.numeric &&
|
|
|
|
|
`
|
|
|
|
|
border-top-right-radius: 0px;
|
|
|
|
|
border-bottom-right-radius: 0px;
|
|
|
|
|
border-right-width: 0px;
|
|
|
|
|
`}
|
2021-02-08 07:30:01 +00:00
|
|
|
transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
2020-02-06 07:01:25 +00:00
|
|
|
&:active {
|
2020-03-06 09:45:21 +00:00
|
|
|
border-color: ${({ hasError }) =>
|
|
|
|
|
hasError ? IntentColors.danger : Colors.HIT_GRAY};
|
2020-02-06 07:01:25 +00:00
|
|
|
}
|
|
|
|
|
&:focus {
|
2020-03-06 09:45:21 +00:00
|
|
|
border-color: ${({ hasError }) =>
|
|
|
|
|
hasError ? IntentColors.danger : Colors.MYSTIC};
|
2021-02-08 07:30:01 +00:00
|
|
|
|
|
|
|
|
&:focus {
|
|
|
|
|
border: ${(props) => getBorderCSSShorthand(props.theme.borders[2])};
|
|
|
|
|
border-color: #80bdff;
|
|
|
|
|
outline: 0;
|
|
|
|
|
box-shadow: 0 0 0 0.1rem rgba(0, 123, 255, 0.25);
|
|
|
|
|
}
|
2020-02-06 07:01:25 +00:00
|
|
|
}
|
2020-01-17 12:34:58 +00:00
|
|
|
}
|
2020-02-06 07:01:25 +00:00
|
|
|
.${Classes.INPUT_GROUP} {
|
2020-01-14 09:50:42 +00:00
|
|
|
display: block;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
2020-02-06 07:01:25 +00:00
|
|
|
.${Classes.CONTROL_GROUP} {
|
2020-01-14 09:50:42 +00:00
|
|
|
justify-content: flex-start;
|
|
|
|
|
}
|
2020-03-06 09:33:20 +00:00
|
|
|
height: 100%;
|
2020-01-21 12:48:42 +00:00
|
|
|
align-items: center;
|
|
|
|
|
label {
|
2020-01-28 08:21:22 +00:00
|
|
|
${labelStyle}
|
2020-01-21 12:48:42 +00:00
|
|
|
flex: 0 1 30%;
|
2020-02-06 07:01:25 +00:00
|
|
|
margin: 7px ${WIDGET_PADDING * 2}px 0 0;
|
2020-01-21 12:48:42 +00:00
|
|
|
text-align: right;
|
2020-02-06 07:01:25 +00:00
|
|
|
align-self: flex-start;
|
2020-03-06 09:45:21 +00:00
|
|
|
max-width: calc(30% - ${WIDGET_PADDING}px);
|
2020-01-21 12:48:42 +00:00
|
|
|
}
|
2019-11-13 07:00:25 +00:00
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
2021-07-15 12:50:01 +00:00
|
|
|
const DropdownTriggerIconWrapper = styled.div`
|
|
|
|
|
height: 19px;
|
|
|
|
|
padding: 9px 5px 9px 12px;
|
|
|
|
|
width: 40px;
|
|
|
|
|
height: 19px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
line-height: 19px;
|
|
|
|
|
letter-spacing: -0.24px;
|
|
|
|
|
color: #090707;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const CurrencyIconWrapper = styled.span`
|
|
|
|
|
height: 100%;
|
|
|
|
|
padding: 6px 4px 6px 12px;
|
|
|
|
|
width: 28px;
|
|
|
|
|
position: absolute;
|
|
|
|
|
left: 0;
|
|
|
|
|
z-index: 16;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
line-height: 19px;
|
|
|
|
|
letter-spacing: -0.24px;
|
|
|
|
|
color: #090707;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
interface CurrencyDropdownProps {
|
|
|
|
|
onCurrencyTypeChange: (code?: string) => void;
|
|
|
|
|
options: Array<DropdownOption>;
|
|
|
|
|
selected: DropdownOption;
|
|
|
|
|
allowCurrencyChange?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function CurrencyTypeDropdown(props: CurrencyDropdownProps) {
|
|
|
|
|
if (!props.allowCurrencyChange) {
|
|
|
|
|
return (
|
|
|
|
|
<CurrencyIconWrapper>
|
|
|
|
|
{getSelectedItem(props.selected.value).id}
|
|
|
|
|
</CurrencyIconWrapper>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
const dropdownTriggerIcon = (
|
|
|
|
|
<DropdownTriggerIconWrapper className="t--input-currency-change">
|
|
|
|
|
{getSelectedItem(props.selected.value).id}
|
|
|
|
|
<Icon name="downArrow" size={IconSize.XXS} />
|
|
|
|
|
</DropdownTriggerIconWrapper>
|
|
|
|
|
);
|
|
|
|
|
return (
|
|
|
|
|
<Dropdown
|
|
|
|
|
containerClassName="currency-type-filter"
|
|
|
|
|
dropdownHeight="195px"
|
|
|
|
|
dropdownTriggerIcon={dropdownTriggerIcon}
|
|
|
|
|
enableSearch
|
|
|
|
|
onSelect={props.onCurrencyTypeChange}
|
|
|
|
|
optionWidth="260px"
|
|
|
|
|
options={props.options}
|
|
|
|
|
searchPlaceholder="Search by currency or country"
|
|
|
|
|
selected={props.selected}
|
|
|
|
|
showLabelOnly
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getSelectedItem = (currencyCountryCode?: string): DropdownOption => {
|
|
|
|
|
let selectedCurrency: CurrencyOptionProps | undefined = currencyCountryCode
|
|
|
|
|
? CurrencyTypeOptions.find((item: CurrencyOptionProps) => {
|
|
|
|
|
return item.code === currencyCountryCode;
|
|
|
|
|
})
|
|
|
|
|
: undefined;
|
|
|
|
|
if (!selectedCurrency) {
|
|
|
|
|
selectedCurrency = {
|
|
|
|
|
code: "US",
|
|
|
|
|
currency: "USD",
|
|
|
|
|
currency_name: "US Dollar",
|
|
|
|
|
label: "United States",
|
|
|
|
|
phone: "1",
|
|
|
|
|
symbol_native: "$",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
label: `${selectedCurrency.currency} - ${selectedCurrency.currency_name}`,
|
|
|
|
|
searchText: selectedCurrency.label,
|
|
|
|
|
value: selectedCurrency.code,
|
|
|
|
|
id: selectedCurrency.symbol_native,
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const countryToFlag = (isoCode: string) => {
|
|
|
|
|
return typeof String.fromCodePoint !== "undefined"
|
|
|
|
|
? isoCode
|
|
|
|
|
.toUpperCase()
|
|
|
|
|
.replace(/./g, (char) =>
|
|
|
|
|
String.fromCodePoint(char.charCodeAt(0) + 127397),
|
|
|
|
|
)
|
|
|
|
|
: isoCode;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getCurrencyOptions = (): Array<DropdownOption> => {
|
|
|
|
|
return CurrencyTypeOptions.map((item: CurrencyOptionProps) => {
|
|
|
|
|
return {
|
|
|
|
|
leftElement: countryToFlag(item.code),
|
|
|
|
|
searchText: item.label,
|
|
|
|
|
label: `${item.currency} - ${item.currency_name}`,
|
|
|
|
|
value: item.code,
|
|
|
|
|
id: item.symbol_native,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2019-10-30 10:23:20 +00:00
|
|
|
class InputComponent extends React.Component<
|
|
|
|
|
InputComponentProps,
|
|
|
|
|
InputComponentState
|
|
|
|
|
> {
|
|
|
|
|
constructor(props: InputComponentProps) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = { showPassword: false };
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 09:45:21 +00:00
|
|
|
setFocusState = (isFocused: boolean) => {
|
|
|
|
|
this.props.onFocusChange(isFocused);
|
|
|
|
|
};
|
|
|
|
|
|
2020-02-06 07:01:25 +00:00
|
|
|
onTextChange = (
|
|
|
|
|
event:
|
|
|
|
|
| React.ChangeEvent<HTMLInputElement>
|
|
|
|
|
| React.ChangeEvent<HTMLTextAreaElement>,
|
|
|
|
|
) => {
|
2019-10-31 05:28:11 +00:00
|
|
|
this.props.onValueChange(event.target.value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onNumberChange = (valueAsNum: number, valueAsString: string) => {
|
2021-07-15 12:50:01 +00:00
|
|
|
if (this.props.inputType === InputTypes.CURRENCY) {
|
|
|
|
|
const fractionDigits = this.props.decimalsInCurrency || 0;
|
|
|
|
|
const currentIndexOfDecimal = valueAsString.indexOf(".");
|
|
|
|
|
const indexOfDecimal = valueAsString.length - fractionDigits - 1;
|
|
|
|
|
if (
|
|
|
|
|
valueAsString.includes(".") &&
|
|
|
|
|
currentIndexOfDecimal <= indexOfDecimal
|
|
|
|
|
) {
|
|
|
|
|
let value = valueAsString.split(",").join("");
|
|
|
|
|
if (value) {
|
|
|
|
|
if (currentIndexOfDecimal !== indexOfDecimal) {
|
|
|
|
|
value = value.substr(0, currentIndexOfDecimal + fractionDigits + 1);
|
|
|
|
|
}
|
|
|
|
|
const locale = navigator.languages?.[0] || "en-US";
|
|
|
|
|
const formatter = new Intl.NumberFormat(locale, {
|
|
|
|
|
style: "decimal",
|
|
|
|
|
minimumFractionDigits: fractionDigits,
|
|
|
|
|
});
|
|
|
|
|
const formattedValue = formatter.format(parseFloat(value));
|
|
|
|
|
this.props.onValueChange(formattedValue);
|
|
|
|
|
} else {
|
|
|
|
|
this.props.onValueChange("");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.props.onValueChange(valueAsString);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.props.onValueChange(valueAsString);
|
|
|
|
|
}
|
2019-10-31 05:28:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
isNumberInputType(inputType: InputType) {
|
|
|
|
|
return (
|
2019-11-05 05:09:50 +00:00
|
|
|
inputType === "INTEGER" ||
|
|
|
|
|
inputType === "NUMBER" ||
|
|
|
|
|
inputType === "CURRENCY"
|
2019-10-31 05:28:11 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getIcon(inputType: InputType) {
|
|
|
|
|
switch (inputType) {
|
|
|
|
|
case "PHONE_NUMBER":
|
|
|
|
|
return "phone";
|
|
|
|
|
case "SEARCH":
|
|
|
|
|
return "search";
|
|
|
|
|
case "EMAIL":
|
|
|
|
|
return "envelope";
|
|
|
|
|
default:
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getType(inputType: InputType) {
|
|
|
|
|
switch (inputType) {
|
|
|
|
|
case "PASSWORD":
|
2020-01-14 09:50:42 +00:00
|
|
|
return this.state.showPassword ? "text" : "password";
|
2019-10-31 05:28:11 +00:00
|
|
|
case "EMAIL":
|
|
|
|
|
return "email";
|
|
|
|
|
case "SEARCH":
|
|
|
|
|
return "search";
|
|
|
|
|
default:
|
|
|
|
|
return "text";
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-28 11:15:14 +00:00
|
|
|
onKeyDownTextArea = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
|
|
|
const isEnterKey = e.key === "Enter" || e.keyCode === 13;
|
|
|
|
|
const { disableNewLineOnPressEnterKey } = this.props;
|
|
|
|
|
if (isEnterKey && disableNewLineOnPressEnterKey && !e.shiftKey) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
if (typeof this.props.onKeyDown === "function") {
|
|
|
|
|
this.props.onKeyDown(e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
|
|
|
if (typeof this.props.onKeyDown === "function") {
|
|
|
|
|
this.props.onKeyDown(e);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-07-15 12:50:01 +00:00
|
|
|
private numericInputComponent = () => {
|
|
|
|
|
const minorStepSize =
|
|
|
|
|
this.props.inputType === InputTypes.CURRENCY
|
|
|
|
|
? this.props.decimalsInCurrency || 0
|
|
|
|
|
: 0;
|
|
|
|
|
return (
|
|
|
|
|
<NumericInput
|
|
|
|
|
allowNumericCharactersOnly
|
|
|
|
|
className={this.props.isLoading ? "bp3-skeleton" : Classes.FILL}
|
|
|
|
|
disabled={this.props.disabled}
|
|
|
|
|
intent={this.props.intent}
|
|
|
|
|
leftIcon={
|
|
|
|
|
this.props.inputType === "PHONE_NUMBER"
|
|
|
|
|
? "phone"
|
|
|
|
|
: this.props.inputType !== InputTypes.CURRENCY
|
|
|
|
|
? this.props.leftIcon
|
|
|
|
|
: this.props.inputType === InputTypes.CURRENCY && (
|
|
|
|
|
<CurrencyTypeDropdown
|
|
|
|
|
allowCurrencyChange={this.props.allowCurrencyChange}
|
|
|
|
|
onCurrencyTypeChange={this.props.onCurrencyTypeChange}
|
|
|
|
|
options={getCurrencyOptions()}
|
|
|
|
|
selected={getSelectedItem(this.props.currencyCountryCode)}
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
max={this.props.maxNum}
|
|
|
|
|
maxLength={this.props.maxChars}
|
|
|
|
|
min={this.props.minNum}
|
|
|
|
|
minorStepSize={
|
|
|
|
|
minorStepSize === 0 ? undefined : Math.pow(10, -1 * minorStepSize)
|
|
|
|
|
}
|
|
|
|
|
onBlur={() => this.setFocusState(false)}
|
|
|
|
|
onFocus={() => this.setFocusState(true)}
|
|
|
|
|
onKeyDown={this.onKeyDown}
|
|
|
|
|
onValueChange={this.onNumberChange}
|
|
|
|
|
placeholder={this.props.placeholder}
|
|
|
|
|
stepSize={minorStepSize === 0 ? this.props.stepSize : undefined}
|
|
|
|
|
type={this.props.inputType === "PHONE_NUMBER" ? "tel" : undefined}
|
|
|
|
|
value={this.props.value}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
};
|
2020-03-13 07:24:03 +00:00
|
|
|
private textAreaInputComponent = () => (
|
2020-02-06 07:01:25 +00:00
|
|
|
<TextArea
|
2021-04-28 10:28:39 +00:00
|
|
|
className={this.props.isLoading ? "bp3-skeleton" : ""}
|
2020-02-06 07:01:25 +00:00
|
|
|
disabled={this.props.disabled}
|
2021-04-28 10:28:39 +00:00
|
|
|
growVertically={false}
|
2020-02-06 07:01:25 +00:00
|
|
|
intent={this.props.intent}
|
2021-04-28 10:28:39 +00:00
|
|
|
maxLength={this.props.maxChars}
|
|
|
|
|
onBlur={() => this.setFocusState(false)}
|
2020-02-06 07:01:25 +00:00
|
|
|
onChange={this.onTextChange}
|
2020-03-06 09:45:21 +00:00
|
|
|
onFocus={() => this.setFocusState(true)}
|
2021-01-28 11:15:14 +00:00
|
|
|
onKeyDown={this.onKeyDownTextArea}
|
2021-04-28 10:28:39 +00:00
|
|
|
placeholder={this.props.placeholder}
|
2021-07-02 11:23:38 +00:00
|
|
|
style={{ resize: "none" }}
|
2021-04-28 10:28:39 +00:00
|
|
|
value={this.props.value}
|
2020-02-06 07:01:25 +00:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
private textInputComponent = (isTextArea: boolean) =>
|
|
|
|
|
isTextArea ? (
|
2020-03-13 07:24:03 +00:00
|
|
|
this.textAreaInputComponent()
|
2020-02-06 07:01:25 +00:00
|
|
|
) : (
|
|
|
|
|
<InputGroup
|
2021-04-28 10:28:39 +00:00
|
|
|
className={this.props.isLoading ? "bp3-skeleton" : ""}
|
2020-02-06 07:01:25 +00:00
|
|
|
disabled={this.props.disabled}
|
|
|
|
|
intent={this.props.intent}
|
2021-04-28 10:28:39 +00:00
|
|
|
maxLength={this.props.maxChars}
|
|
|
|
|
onBlur={() => this.setFocusState(false)}
|
2020-02-06 07:01:25 +00:00
|
|
|
onChange={this.onTextChange}
|
2021-04-28 10:28:39 +00:00
|
|
|
onFocus={() => this.setFocusState(true)}
|
|
|
|
|
onKeyDown={this.onKeyDown}
|
|
|
|
|
placeholder={this.props.placeholder}
|
2020-02-06 07:01:25 +00:00
|
|
|
rightElement={
|
|
|
|
|
this.props.inputType === "PASSWORD" ? (
|
|
|
|
|
<Button
|
|
|
|
|
icon={"lock"}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
this.setState({ showPassword: !this.state.showPassword });
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
undefined
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
type={this.getType(this.props.inputType)}
|
2021-04-28 10:28:39 +00:00
|
|
|
value={this.props.value}
|
2020-02-06 07:01:25 +00:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
private renderInputComponent = (inputType: InputType, isTextArea: boolean) =>
|
|
|
|
|
this.isNumberInputType(inputType)
|
|
|
|
|
? this.numericInputComponent()
|
|
|
|
|
: this.textInputComponent(isTextArea);
|
2019-10-31 05:28:11 +00:00
|
|
|
|
2019-10-30 10:23:20 +00:00
|
|
|
render() {
|
|
|
|
|
return (
|
2020-03-06 09:45:21 +00:00
|
|
|
<InputComponentWrapper
|
2021-07-15 12:50:01 +00:00
|
|
|
allowCurrencyChange={this.props.allowCurrencyChange}
|
2020-03-06 09:45:21 +00:00
|
|
|
fill
|
2021-04-28 10:28:39 +00:00
|
|
|
hasError={this.props.isInvalid}
|
2021-07-15 12:50:01 +00:00
|
|
|
inputType={this.props.inputType}
|
2020-03-06 09:45:21 +00:00
|
|
|
multiline={this.props.multiline.toString()}
|
2020-03-13 07:24:03 +00:00
|
|
|
numeric={this.isNumberInputType(this.props.inputType)}
|
2020-03-06 09:45:21 +00:00
|
|
|
>
|
2020-01-28 11:46:04 +00:00
|
|
|
{this.props.label && (
|
2020-01-31 11:13:16 +00:00
|
|
|
<Label
|
|
|
|
|
className={
|
|
|
|
|
this.props.isLoading
|
|
|
|
|
? Classes.SKELETON
|
|
|
|
|
: Classes.TEXT_OVERFLOW_ELLIPSIS
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{this.props.label}
|
2020-01-28 11:46:04 +00:00
|
|
|
</Label>
|
|
|
|
|
)}
|
2020-03-06 09:45:21 +00:00
|
|
|
<ErrorTooltip
|
|
|
|
|
isOpen={this.props.isInvalid && this.props.showError}
|
|
|
|
|
message={
|
2021-03-13 14:24:45 +00:00
|
|
|
this.props.errorMessage ||
|
|
|
|
|
createMessage(INPUT_WIDGET_DEFAULT_VALIDATION_ERROR)
|
2020-03-06 09:45:21 +00:00
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{this.renderInputComponent(
|
|
|
|
|
this.props.inputType,
|
|
|
|
|
this.props.multiline,
|
|
|
|
|
)}
|
|
|
|
|
</ErrorTooltip>
|
2019-11-13 07:00:25 +00:00
|
|
|
</InputComponentWrapper>
|
2019-10-30 10:23:20 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface InputComponentState {
|
|
|
|
|
showPassword?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface InputComponentProps extends ComponentProps {
|
2020-03-06 09:45:21 +00:00
|
|
|
value: string;
|
2019-10-31 05:28:11 +00:00
|
|
|
inputType: InputType;
|
2019-10-30 10:23:20 +00:00
|
|
|
disabled?: boolean;
|
|
|
|
|
intent?: Intent;
|
|
|
|
|
defaultValue?: string;
|
2021-07-15 12:50:01 +00:00
|
|
|
currencyCountryCode?: string;
|
|
|
|
|
noOfDecimals?: number;
|
|
|
|
|
allowCurrencyChange?: boolean;
|
|
|
|
|
decimalsInCurrency?: number;
|
2019-10-31 05:28:11 +00:00
|
|
|
label: string;
|
2019-10-30 10:23:20 +00:00
|
|
|
leftIcon?: IconName;
|
|
|
|
|
allowNumericCharactersOnly?: boolean;
|
|
|
|
|
fill?: boolean;
|
2019-10-31 05:28:11 +00:00
|
|
|
errorMessage?: string;
|
|
|
|
|
maxChars?: number;
|
2019-10-30 10:23:20 +00:00
|
|
|
maxNum?: number;
|
|
|
|
|
minNum?: number;
|
2019-10-31 05:28:11 +00:00
|
|
|
onValueChange: (valueAsString: string) => void;
|
2021-07-15 12:50:01 +00:00
|
|
|
onCurrencyTypeChange: (code?: string) => void;
|
2019-10-30 10:23:20 +00:00
|
|
|
stepSize?: number;
|
|
|
|
|
placeholder?: string;
|
2019-12-03 04:41:10 +00:00
|
|
|
isLoading: boolean;
|
2020-02-13 09:32:24 +00:00
|
|
|
multiline: boolean;
|
2020-03-06 09:45:21 +00:00
|
|
|
isInvalid: boolean;
|
|
|
|
|
showError: boolean;
|
|
|
|
|
onFocusChange: (state: boolean) => void;
|
2021-01-28 11:15:14 +00:00
|
|
|
disableNewLineOnPressEnterKey?: boolean;
|
|
|
|
|
onKeyDown?: (
|
|
|
|
|
e:
|
|
|
|
|
| React.KeyboardEvent<HTMLTextAreaElement>
|
|
|
|
|
| React.KeyboardEvent<HTMLInputElement>,
|
|
|
|
|
) => void;
|
2019-10-30 10:23:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default InputComponent;
|