mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Display hint to user on how to add items in an EditableList (#3475)
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
239bfec99c
commit
07532b1552
@ -53,11 +53,9 @@ export class EditableList<T> extends React.Component<Props<T>> {
|
||||
|
||||
@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<T> extends React.Component<Props<T>> {
|
||||
onSubmit={this.onSubmit}
|
||||
validators={validators}
|
||||
placeholder={placeholder}
|
||||
iconRight={({ isDirty }) => isDirty ? <Icon material="keyboard_return" size={16} /> : null}
|
||||
/>
|
||||
</div>
|
||||
<div className="el-contents">
|
||||
|
||||
@ -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<InputElement> & TextareaHTMLAttributes<InputElement> & DOMAttributes<InputElement>;
|
||||
|
||||
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<InputElementProps, "onChange" | "onSubmit"> & {
|
||||
theme?: "round-black" | "round";
|
||||
className?: string;
|
||||
@ -53,8 +64,8 @@ export type InputProps = Omit<InputElementProps, "onChange" | "onSubmit"> & {
|
||||
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<TooltipProps, "targetId">; // 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<InputElement>): void;
|
||||
@ -75,7 +86,6 @@ const defaultProps: Partial<InputProps> = {
|
||||
maxRows: 10000,
|
||||
showValidationLine: true,
|
||||
validators: [],
|
||||
defaultValue: "",
|
||||
};
|
||||
|
||||
export class Input extends React.Component<InputProps, State> {
|
||||
@ -105,7 +115,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
}
|
||||
|
||||
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<InputProps, State> {
|
||||
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<InputProps, State> {
|
||||
this.input = elem;
|
||||
}
|
||||
|
||||
private renderIcon(iconData: IconData) {
|
||||
if (typeof iconData === "string") {
|
||||
return <Icon material={iconData} />;
|
||||
}
|
||||
|
||||
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<InputProps, State> {
|
||||
<div id={componentId} className={className}>
|
||||
{tooltipError}
|
||||
<label className="input-area flex gaps align-center" id="">
|
||||
{isString(iconLeft) ? <Icon material={iconLeft}/> : iconLeft}
|
||||
{this.renderIcon(iconLeft)}
|
||||
{multiLine ? <textarea {...inputProps as any} /> : <input {...inputProps as any} />}
|
||||
{isString(iconRight) ? <Icon material={iconRight}/> : iconRight}
|
||||
{this.renderIcon(iconRight)}
|
||||
{contentRight}
|
||||
</label>
|
||||
<div className="input-info flex gaps">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user