import React from "react"; import styled from "styled-components"; import { IntentColors, labelStyle } from "constants/DefaultTheme"; import { ComponentProps } from "components/designSystems/appsmith/BaseComponent"; import { Intent, NumericInput, IconName, InputGroup, Button, Label, Classes, ControlGroup, TextArea, } from "@blueprintjs/core"; import { InputType } from "widgets/InputWidget"; import { WIDGET_PADDING } from "constants/WidgetConstants"; import { Colors } from "constants/Colors"; import ErrorTooltip from "components/editorComponents/ErrorTooltip"; import _ from "lodash"; import { INPUT_WIDGET_DEFAULT_VALIDATION_ERROR } from "constants/messages"; /** * All design system component specific logic goes here. * Ex. Blueprint has a separate numeric input and text input so switching between them goes here * 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 */ const InputComponentWrapper = styled((props) => ( ))<{ numeric: boolean; multiline: string; hasError: boolean; }>` &&&& { .${Classes.INPUT} { box-shadow: none; border: 1px solid; border-color: ${({ hasError }) => hasError ? IntentColors.danger : Colors.GEYSER_LIGHT}; border-radius: ${(props) => props.theme.radii[1]}px; height: ${(props) => (props.multiline === "true" ? "100%" : "inherit")}; width: 100%; ${(props) => props.numeric && ` border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-right-width: 0px; `} &:active { border-color: ${({ hasError }) => hasError ? IntentColors.danger : Colors.HIT_GRAY}; } &:focus { border-color: ${({ hasError }) => hasError ? IntentColors.danger : Colors.MYSTIC}; } } .${Classes.INPUT_GROUP} { display: block; margin: 0; } .${Classes.CONTROL_GROUP} { justify-content: flex-start; } height: 100%; align-items: center; label { ${labelStyle} flex: 0 1 30%; margin: 7px ${WIDGET_PADDING * 2}px 0 0; text-align: right; align-self: flex-start; max-width: calc(30% - ${WIDGET_PADDING}px); } } `; class InputComponent extends React.Component< InputComponentProps, InputComponentState > { constructor(props: InputComponentProps) { super(props); this.state = { showPassword: false }; } setFocusState = (isFocused: boolean) => { this.props.onFocusChange(isFocused); }; onTextChange = ( event: | React.ChangeEvent | React.ChangeEvent, ) => { this.props.onValueChange(event.target.value); }; onNumberChange = (valueAsNum: number, valueAsString: string) => { this.props.onValueChange(valueAsString); }; isNumberInputType(inputType: InputType) { return ( inputType === "INTEGER" || inputType === "NUMBER" || inputType === "CURRENCY" ); } 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": return this.state.showPassword ? "text" : "password"; case "EMAIL": return "email"; case "SEARCH": return "search"; default: return "text"; } } onKeyDownTextArea = (e: React.KeyboardEvent) => { 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) => { if (typeof this.props.onKeyDown === "function") { this.props.onKeyDown(e); } }; private numericInputComponent = () => ( this.setFocusState(true)} onBlur={() => this.setFocusState(false)} onKeyDown={this.onKeyDown} /> ); private textAreaInputComponent = () => (