mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
fixes for <Input/>:
- remove duplicated error messages for sync validators - don't propagate invalid values on change (uncontrolled components only) - more informative error message for numeric input with min/max info Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
27c67c3e2e
commit
36710e2b08
@ -8,7 +8,7 @@ import { action } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import type { UserStore } from "../../../common/user-store";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { Input, InputValidators } from "../input";
|
||||
import { Input } from "../input";
|
||||
import { Switch } from "../switch";
|
||||
import { Select, type SelectOption } from "../select";
|
||||
import type { ThemeStore } from "../../themes/store";
|
||||
@ -104,8 +104,8 @@ const NonInjectedTerminal = observer((
|
||||
theme="round-black"
|
||||
type="number"
|
||||
min={10}
|
||||
validators={InputValidators.isNumber}
|
||||
value={userStore.terminalConfig.fontSize.toString()}
|
||||
max={50}
|
||||
defaultValue={userStore.terminalConfig.fontSize.toString()}
|
||||
onChange={(value) => userStore.terminalConfig.fontSize = Number(value)}
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -14,7 +14,6 @@ import { Tooltip } from "../tooltip";
|
||||
import * as Validators from "./input_validators";
|
||||
import type { InputValidator } from "./input_validators";
|
||||
import isFunction from "lodash/isFunction";
|
||||
import isBoolean from "lodash/isBoolean";
|
||||
import uniqueId from "lodash/uniqueId";
|
||||
import { debounce } from "lodash";
|
||||
|
||||
@ -24,7 +23,10 @@ export { InputValidators };
|
||||
export type { InputValidator };
|
||||
|
||||
type InputElement = HTMLInputElement | HTMLTextAreaElement;
|
||||
type InputElementProps = InputHTMLAttributes<HTMLInputElement> & TextareaHTMLAttributes<HTMLTextAreaElement> & DOMAttributes<InputElement>;
|
||||
type InputElementProps =
|
||||
InputHTMLAttributes<HTMLInputElement>
|
||||
& TextareaHTMLAttributes<HTMLTextAreaElement>
|
||||
& DOMAttributes<InputElement>;
|
||||
|
||||
export interface IconDataFnArg {
|
||||
isDirty: boolean;
|
||||
@ -173,22 +175,18 @@ export class Input extends React.Component<InputProps, State> {
|
||||
error => this.getValidatorError(value, validator) || error,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (!validator.validate(value, this.props)) {
|
||||
errors.push(this.getValidatorError(value, validator));
|
||||
}
|
||||
}
|
||||
|
||||
const result = validator.validate(value, this.props);
|
||||
const isValid = validator.validate(value, this.props);
|
||||
|
||||
if (isBoolean(result) && !result) {
|
||||
if (isValid === false) {
|
||||
errors.push(this.getValidatorError(value, validator));
|
||||
} else if (result instanceof Promise) {
|
||||
} else if (isValid instanceof Promise) {
|
||||
if (!validationId) {
|
||||
this.validationId = validationId = uniqueId("validation_id_");
|
||||
}
|
||||
asyncValidators.push(
|
||||
result.then(
|
||||
isValid.then(
|
||||
() => null, // don't consider any valid result from promise since we interested in errors only
|
||||
error => this.getValidatorError(value, validator) || error,
|
||||
),
|
||||
@ -266,9 +264,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
|
||||
setDirtyOnChange = debounce(() => this.setDirty(), 500);
|
||||
|
||||
onChange(evt: React.ChangeEvent<any>) {
|
||||
this.props.onChange?.(evt.currentTarget.value, evt);
|
||||
this.validate();
|
||||
async onChange(evt: React.ChangeEvent<any>) {
|
||||
this.autoFitHeight();
|
||||
this.setDirtyOnChange();
|
||||
|
||||
@ -277,6 +273,17 @@ export class Input extends React.Component<InputProps, State> {
|
||||
if (this.isUncontrolled && this.showMaxLenIndicator) {
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
const newValue = evt.currentTarget.value;
|
||||
const eventCopy = { ...evt };
|
||||
|
||||
await this.validate(); // validate first
|
||||
|
||||
// don't propagate changes for invalid values
|
||||
// possible only with uncontrolled components (defaultValue={} must be used instead value={})
|
||||
if (!this.isUncontrolled || (this.isUncontrolled && this.state.valid)) {
|
||||
this.props.onChange?.(newValue, eventCopy);
|
||||
}
|
||||
}
|
||||
|
||||
onKeyDown(evt: React.KeyboardEvent<InputElement>) {
|
||||
@ -299,7 +306,7 @@ export class Input extends React.Component<InputProps, State> {
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
if(this.props.blurOnEnter){
|
||||
if (this.props.blurOnEnter) {
|
||||
//pressing enter indicates that the edit is complete, we can unfocus now
|
||||
this.blur();
|
||||
}
|
||||
@ -379,7 +386,6 @@ export class Input extends React.Component<InputProps, State> {
|
||||
multiLine, showValidationLine, validators, theme, maxRows, children, showErrorsAsTooltip,
|
||||
maxLength, rows, disabled, autoSelectOnFocus, iconLeft, iconRight, contentRight, id,
|
||||
dirty: _dirty, // excluded from passing to input-element
|
||||
defaultValue,
|
||||
trim,
|
||||
blurOnEnter,
|
||||
...inputProps
|
||||
|
||||
@ -8,7 +8,8 @@ import type { ReactNode } from "react";
|
||||
import fse from "fs-extra";
|
||||
import { TypedRegEx } from "typed-regex";
|
||||
|
||||
export class AsyncInputValidationError extends Error {}
|
||||
export class AsyncInputValidationError extends Error {
|
||||
}
|
||||
|
||||
export type InputValidator<IsAsync extends boolean> = {
|
||||
/**
|
||||
@ -32,7 +33,7 @@ export type InputValidator<IsAsync extends boolean> = {
|
||||
message?: undefined;
|
||||
debounce: number;
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
export function inputValidator<IsAsync extends boolean = false>(validator: InputValidator<IsAsync>): InputValidator<IsAsync> {
|
||||
return validator;
|
||||
@ -52,7 +53,14 @@ export const isEmail = inputValidator({
|
||||
|
||||
export const isNumber = inputValidator({
|
||||
condition: ({ type }) => type === "number",
|
||||
message: () => `Invalid number`,
|
||||
message(value, { min, max }) {
|
||||
const minMax: string = [
|
||||
typeof min === "number" ? `min: ${min}` : undefined,
|
||||
typeof max === "number" ? `max: ${max}` : undefined,
|
||||
].filter(Boolean).join(", ");
|
||||
|
||||
return `Invalid number${minMax ? ` (${minMax})` : ""}`;
|
||||
},
|
||||
validate: (value, { min, max }) => {
|
||||
const numVal = +value;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user