diff --git a/src/renderer/components/editable-list/editable-list.tsx b/src/renderer/components/editable-list/editable-list.tsx index 61bf70bb70..3a16263ff4 100644 --- a/src/renderer/components/editable-list/editable-list.tsx +++ b/src/renderer/components/editable-list/editable-list.tsx @@ -53,11 +53,9 @@ export class EditableList extends React.Component> { @boundMethod onSubmit(val: string, evt: React.KeyboardEvent) { - const { add } = this.props; - if (val) { evt.preventDefault(); - add(val); + this.props.add(val); } } @@ -72,6 +70,7 @@ export class EditableList extends React.Component> { onSubmit={this.onSubmit} validators={validators} placeholder={placeholder} + iconRight={({ isDirty }) => isDirty ? : null} />
diff --git a/src/renderer/components/input/input.tsx b/src/renderer/components/input/input.tsx index 062d61f2c6..e1d39d9835 100644 --- a/src/renderer/components/input/input.tsx +++ b/src/renderer/components/input/input.tsx @@ -27,7 +27,6 @@ import { Icon } from "../icon"; import { Tooltip, TooltipProps } from "../tooltip"; import * as Validators from "./input_validators"; import type { InputValidator } from "./input_validators"; -import isString from "lodash/isString"; import isFunction from "lodash/isFunction"; import isBoolean from "lodash/isBoolean"; import uniqueId from "lodash/uniqueId"; @@ -41,6 +40,18 @@ export type { InputValidator }; type InputElement = HTMLInputElement | HTMLTextAreaElement; type InputElementProps = InputHTMLAttributes & TextareaHTMLAttributes & DOMAttributes; +export interface IconDataFnArg { + isDirty: boolean; +} + +/** + * One of the folloing: + * - A material icon name + * - A react node + * - Or a function that produces a react node + */ +export type IconData = string | React.ReactNode | ((opt: IconDataFnArg) => React.ReactNode); + export type InputProps = Omit & { theme?: "round-black" | "round"; className?: string; @@ -53,8 +64,8 @@ export type InputProps = Omit & { dirty?: boolean; // show validation errors even if the field wasn't touched yet showValidationLine?: boolean; // show animated validation line for async validators showErrorsAsTooltip?: boolean | Omit; // show validation errors as a tooltip :hover (instead of block below) - iconLeft?: string | React.ReactNode; // material-icon name in case of string-type - iconRight?: string | React.ReactNode; + iconLeft?: IconData; + iconRight?: IconData; contentRight?: string | React.ReactNode; // Any component of string goes after iconRight validators?: InputValidator | InputValidator[]; onChange?(value: string, evt: React.ChangeEvent): void; @@ -75,7 +86,6 @@ const defaultProps: Partial = { maxRows: 10000, showValidationLine: true, validators: [], - defaultValue: "", }; export class Input extends React.Component { @@ -105,7 +115,7 @@ export class Input extends React.Component { } getValue(): string { - const { trim, value, defaultValue } = this.props; + const { trim, value, defaultValue = "" } = this.props; const rawValue = value ?? this.input?.value ?? defaultValue; return trim ? rawValue.trim() : rawValue; @@ -262,6 +272,10 @@ export class Input extends React.Component { this.props.onSubmit?.(this.getValue(), evt); this.setDirtyOnChange.cancel(); this.setState({ submitted: true }); + + if (this.input && typeof this.props.value !== "string") { + this.input.value = ""; + } } else { this.setDirty(); } @@ -323,6 +337,20 @@ export class Input extends React.Component { this.input = elem; } + private renderIcon(iconData: IconData) { + if (typeof iconData === "string") { + return ; + } + + if (typeof iconData === "function") { + return iconData({ + isDirty: Boolean(this.getValue()), + }); + } + + return iconData; + } + render() { const { multiLine, showValidationLine, validators, theme, maxRows, children, showErrorsAsTooltip, @@ -383,9 +411,9 @@ export class Input extends React.Component {
{tooltipError}