Skip to content

Commit

Permalink
fix(input validation): improve prsitine state support
Browse files Browse the repository at this point in the history
fix #411
  • Loading branch information
morewings committed Aug 2, 2024
1 parent baafb2b commit 74dcc25
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 21 deletions.
16 changes: 10 additions & 6 deletions src/internal/inputs/useValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ const getMode = (validation: ValidationProps['validation']) => {

export const useValidation = <TEvent extends FormEvent, TElement extends HTMLInputElement>({
validation,
}: ValidationProps) => {
hasValidators,
}: ValidationProps & {hasValidators: boolean}) => {
const validatorFn = createValidatorFn(validation);
const mode = getMode(validation);

Expand All @@ -111,11 +112,14 @@ export const useValidation = <TEvent extends FormEvent, TElement extends HTMLInp
useHandleFormReset(setValidity);

// reportValidity gets invoked only if validation is set to custom validator fn
const reportValidity = useCallback((event: TEvent) => {
const isValid = (event.target as TElement).reportValidity();
const nextValidationState = isValid ? ValidationState.valid : ValidationState.error;
setValidity(nextValidationState);
}, []);
const reportValidity = useCallback(
(event: TEvent) => {
const isValid = (event.target as TElement).reportValidity();
const nextValidationState = isValid ? ValidationState.valid : ValidationState.error;
hasValidators && setValidity(nextValidationState);
},
[hasValidators]
);

const {createValidatorAsync, createValidatorSync, createValidatorExternal} = useValidatorFn({
validatorFn,
Expand Down
8 changes: 7 additions & 1 deletion src/lib/InputCheckbox/InputCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ export const InputCheckbox = forwardRef<HTMLInputElement, Props>(
ref
) => {
const id = useInternalId(idProp);
const {validateInteractive, validity, setValidity} = useValidation({validation});

const hasValidators = Boolean(validation) || Boolean(required);

const {validateInteractive, validity, setValidity} = useValidation({
validation,
hasValidators,
});

const inputRef = useInternalRef(ref);
useRevalidateOnFormChange(inputRef, validateInteractive, revalidateOnFormChange);
Expand Down
3 changes: 3 additions & 0 deletions src/lib/InputColor/InputColor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ export const InputColor = forwardRef<HTMLInputElement, Props>(
},
ref
) => {
const hasValidators = Boolean(validation);

const {validity, setValidity, validateTextual} = useValidation({
validation,
hasValidators,
});
const id = useInternalId(idProp);

Expand Down
7 changes: 6 additions & 1 deletion src/lib/InputDate/InputDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,15 @@ export const InputDate = forwardRef<HTMLInputElement, Props>(
},
ref
) => {
const hasValidators =
Boolean(validation) ||
typeof nativeProps.min === 'string' ||
typeof nativeProps.max === 'string';

const id = useInternalId(idProp);
const labelRef = useRef<HTMLLabelElement>(null);

const {validateTextual, validity, setValidity} = useValidation({validation});
const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});

const inputRef = useInternalRef(ref);

Expand Down
2 changes: 2 additions & 0 deletions src/lib/InputFile/InputFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ export const InputFile = forwardRef<HTMLInputElement, Props>(

const id = useInternalId(idProp);
const [filename, setFileName] = useState('');
const hasValidators = Boolean(validation);
const {validateTextual, validity, setValidity} = useValidation({
validation,
hasValidators,
});
const inputRef = useInternalRef(ref);
useExternalValidation({errorMessage, inputRef, setValidity, validation});
Expand Down
6 changes: 3 additions & 3 deletions src/lib/InputNumber/InputNumber.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ const meta = {
required: false,
readOnly: false,
disabled: false,
min: -100,
max: 100,
step: 10,
size: 9,
},
argTypes: {
value: {control: 'text'},
step: {control: 'number'},
min: {control: 'number'},
max: {control: 'number'},
defaultValue: {
table: {
disable: true,
Expand Down
14 changes: 12 additions & 2 deletions src/lib/InputNumber/InputNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,25 @@ export const InputNumber = forwardRef<HTMLInputElement, Props>(
onKeyUp = () => {},
defaultValue,
size = 10,
step = 1,
step,
revalidateOnFormChange,
errorMessage = ValidationState.error,
validation,
...nativeProps
},
ref
) => {
const {validateTextual, validity, setValidity} = useValidation({validation});
const hasValidators =
Boolean(validation) ||
Boolean(nativeProps.required) ||
typeof nativeProps.min === 'number' ||
typeof nativeProps.min === 'string' ||
typeof nativeProps.max === 'number' ||
typeof nativeProps.max === 'string' ||
typeof step === 'number' ||
typeof step === 'string';

const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});

const inputRef = useInternalRef(ref);
useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);
Expand Down
9 changes: 8 additions & 1 deletion src/lib/InputPassword/InputPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,14 @@ export const InputPassword = forwardRef<HTMLInputElement, Props>(
},
ref
) => {
const {validateTextual, validity, setValidity} = useValidation({validation});
const hasValidators =
Boolean(validation) ||
Boolean(nativeProps.required) ||
typeof nativeProps.maxLength === 'number' ||
typeof nativeProps.minLength === 'number' ||
typeof nativeProps.pattern === 'string';

const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});

const inputRef = useInternalRef(ref);
useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);
Expand Down
4 changes: 3 additions & 1 deletion src/lib/InputRange/InputRange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export const InputRange = forwardRef<HTMLInputElement, Props>(
},
ref
) => {
const {validateTextual, validity, setValidity} = useValidation({validation});
const hasValidators = Boolean(validation) || Boolean(nativeProps.required);

const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});

const inputRef = useInternalRef(ref);
useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);
Expand Down
12 changes: 10 additions & 2 deletions src/lib/InputText/InputText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export type Props = DataAttributes &
CallbackPropsTextual &
ValidationProps & {
/**
* Define a type of TextInput. Allows developer to optionally set one from supported
* Define a type of TextInput. Allows a developer to optionally set one from supported
* text-like input types instead of default 'text'.
* Non-text types such as `number` or `week` are not allowed.
* Non-text types such as `number` or `week` aren't allowed.
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types
*/
type?: 'text' | 'email' | 'password' | 'search' | 'tel' | 'url';
Expand Down Expand Up @@ -67,8 +67,16 @@ export const InputText = forwardRef<HTMLInputElement, Props>(
) => {
const inputRef = useInternalRef(ref);

const hasValidators =
Boolean(validation) ||
Boolean(required) ||
typeof nativeProps.maxLength === 'number' ||
typeof nativeProps.minLength === 'number' ||
typeof nativeProps.pattern === 'string';

const {validateTextual, validity, setValidity} = useValidation({
validation,
hasValidators,
});

useExternalValidation({errorMessage, inputRef, setValidity, validation});
Expand Down
7 changes: 6 additions & 1 deletion src/lib/InputTime/InputTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ export const InputTime = forwardRef<HTMLInputElement, Props>(
ref
) => {
const inputRef = useInternalRef(ref);
const {validity, setValidity, validateTextual} = useValidation({validation});
const hasValidators =
Boolean(validation) ||
typeof nativeProps.min === 'string' ||
typeof nativeProps.max === 'string';

const {validity, setValidity, validateTextual} = useValidation({validation, hasValidators});

useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);
useExternalValidation({errorMessage, inputRef, setValidity, validation});
Expand Down
4 changes: 3 additions & 1 deletion src/lib/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ export const Select = forwardRef<HTMLSelectElement, Props>(
[size]
);

const {validateTextual, validity, setValidity} = useValidation({validation});
const hasValidators = Boolean(validation);

const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});

const inputRef = useInternalRef(ref);
useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);
Expand Down
8 changes: 7 additions & 1 deletion src/lib/Textarea/Textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,13 @@ export const Textarea = forwardRef<HTMLTextAreaElement, Props>(
},
ref
) => {
const {validateTextual, validity, setValidity} = useValidation({validation});
const hasValidators =
Boolean(validation) ||
Boolean(nativeProps.required) ||
typeof nativeProps.maxLength === 'number' ||
typeof nativeProps.minLength === 'number';

const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});

const inputRef = useInternalRef(ref);
useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);
Expand Down
8 changes: 7 additions & 1 deletion templates/Input/TemplateName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ export const TemplateName = forwardRef<HTMLInputElement, Props>(
},
ref
) => {
const {validateTextual, validity, setValidity} = useValidation({validation});
const hasValidators =
Boolean(validation) ||
Boolean(nativeProps.required) ||
typeof nativeProps.maxLength === 'number' ||
typeof nativeProps.minLength === 'number' ||
typeof nativeProps.pattern === 'string';
const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});
const ValidationIcon = useValidationIcon(validity);
const handleChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
Expand Down

0 comments on commit 74dcc25

Please sign in to comment.