mirror of
https://github.com/wassname/talk.git
synced 2026-08-03 13:20:59 +08:00
chore: form standardization (#2425)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { noop } from "lodash";
|
||||
import React from "react";
|
||||
|
||||
export type SubmitHook = (
|
||||
data: any,
|
||||
export type SubmitHook<T = any> = (
|
||||
data: T,
|
||||
actions: {
|
||||
// Callback will be called after all validations has passed and
|
||||
// the submit has not been cancelled.
|
||||
@@ -11,8 +11,8 @@ export type SubmitHook = (
|
||||
}
|
||||
) => Promise<any> | any;
|
||||
export type RemoveSubmitHook = () => void;
|
||||
export type AddSubmitHook = (hook: SubmitHook) => RemoveSubmitHook;
|
||||
export type SubmitHookContext = AddSubmitHook;
|
||||
export type AddSubmitHook<T = any> = (hook: SubmitHook<T>) => RemoveSubmitHook;
|
||||
export type SubmitHookContext<T = any> = AddSubmitHook<T>;
|
||||
|
||||
const { Provider, Consumer } = React.createContext<SubmitHookContext>(
|
||||
() => noop
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
|
||||
import { FieldMeta, hasError } from "coral-framework/lib/form/helpers";
|
||||
import { Omit } from "coral-framework/types";
|
||||
import { ValidationMessage as UIValidationMessage } from "coral-ui/components";
|
||||
import { ValidationMessageProps } from "coral-ui/components/ValidationMessage";
|
||||
|
||||
interface Props extends Omit<ValidationMessageProps, "children"> {
|
||||
meta: FieldMeta;
|
||||
}
|
||||
|
||||
const ValidationMessage: FunctionComponent<Props> = ({ meta, ...rest }) =>
|
||||
hasError(meta) ? (
|
||||
<UIValidationMessage {...rest}>
|
||||
{meta.error || meta.submitError}
|
||||
</UIValidationMessage>
|
||||
) : null;
|
||||
|
||||
export default ValidationMessage;
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as FormInitializer } from "./FormInitializer";
|
||||
export { default as ValidationMessage } from "./ValidationMessage";
|
||||
@@ -1,5 +1,6 @@
|
||||
import { FormApi } from "final-form";
|
||||
import { ReactNode } from "react";
|
||||
import { FieldRenderProps } from "react-final-form";
|
||||
|
||||
type ErrorsObject<T> = { [K in keyof T]?: ReactNode };
|
||||
|
||||
@@ -65,3 +66,14 @@ export const formatStringList = (v: string[] | null) => {
|
||||
}
|
||||
return v.join(", ");
|
||||
};
|
||||
|
||||
export type FieldMeta = Pick<
|
||||
FieldRenderProps["meta"],
|
||||
"touched" | "error" | "submitError"
|
||||
>;
|
||||
|
||||
export const hasError = ({ touched, error, submitError }: FieldMeta) =>
|
||||
touched && (error || submitError);
|
||||
|
||||
export const colorFromMeta = (meta: FieldMeta) =>
|
||||
hasError(meta) ? "error" : "regular";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export * from "./components";
|
||||
export * from "./helpers";
|
||||
export * from "./SubmitHookContext";
|
||||
export { default as withSubmitHookContext } from "./withSubmitHookContext";
|
||||
export { default as SubmitHookHandler } from "./SubmitHookHandler";
|
||||
export { default as FormInitializer } from "./FormInitializer";
|
||||
|
||||
@@ -201,6 +201,42 @@ export const validateWholeNumberBetween = (min: number, max: number) =>
|
||||
*/
|
||||
export const validatePercentage = (min: number, max: number) =>
|
||||
createValidator(
|
||||
v => v === null || (!Number.isNaN(v) && v >= min && v <= max),
|
||||
v =>
|
||||
v === null ||
|
||||
(typeof v === "number" && !Number.isNaN(v) && v >= min && v <= max),
|
||||
|
||||
NOT_A_WHOLE_NUMBER_BETWEEN(min * 100, max * 100)
|
||||
);
|
||||
|
||||
/**
|
||||
* Condition represents a given check that can be performed for the purpose of
|
||||
* filtering a validation operation.
|
||||
*/
|
||||
export type Condition<T = any, V = any> = (value: T, values: V) => boolean;
|
||||
|
||||
/**
|
||||
* composeValidatorsWhen is the same as composeValidators except it will only
|
||||
* apply the validators if the condition is true.
|
||||
*/
|
||||
export function composeValidatorsWhen<T = any, V = any>(
|
||||
condition: Condition<T, V>,
|
||||
...validators: Array<Validator<T, V>>
|
||||
): Validator<T, V> {
|
||||
return validateWhen(condition, composeValidators(...validators));
|
||||
}
|
||||
|
||||
/**
|
||||
* validate will simply wrap a single validator with a condition check first.
|
||||
*/
|
||||
export function validateWhen<T = any, V = any>(
|
||||
condition: Condition<T, V>,
|
||||
validator: Validator<T, V>
|
||||
): Validator<T, V> {
|
||||
return (value, values) => {
|
||||
if (condition(value, values)) {
|
||||
return validator(value, values);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user