mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-17 04:46:05 +00:00
form rerenders optimized
This commit is contained in:
@@ -1,26 +1,30 @@
|
||||
import type { JSONSchema } from "json-schema-to-ts";
|
||||
import type { JsonSchema } from "json-schema-library";
|
||||
import type { ChangeEvent, ComponentPropsWithoutRef } from "react";
|
||||
import * as Formy from "ui/components/form/Formy";
|
||||
import { useEvent } from "ui/hooks/use-event";
|
||||
import { ArrayField } from "./ArrayField";
|
||||
import { FieldWrapper } from "./FieldWrapper";
|
||||
import { useFieldContext } from "./Form";
|
||||
import { useDerivedFieldContext, useFormValue } from "./Form";
|
||||
import { ObjectField } from "./ObjectField";
|
||||
import { coerce, enumToOptions, isType, isTypeSchema } from "./utils";
|
||||
import { coerce, isType, isTypeSchema } from "./utils";
|
||||
|
||||
export type FieldProps = {
|
||||
name: string;
|
||||
schema?: Exclude<JSONSchema, boolean>;
|
||||
schema?: JsonSchema;
|
||||
onChange?: (e: ChangeEvent<any>) => void;
|
||||
label?: string | false;
|
||||
hidden?: boolean;
|
||||
};
|
||||
|
||||
export const Field = ({ name, schema: _schema, onChange, label: _label, hidden }: FieldProps) => {
|
||||
const { pointer, value, errors, setValue, required, ...ctx } = useFieldContext(name);
|
||||
const { pointer, setValue, required, ...ctx } = useDerivedFieldContext(name, _schema);
|
||||
const schema = _schema ?? ctx.schema;
|
||||
if (!isTypeSchema(schema)) return <Pre>{pointer} has no schema</Pre>;
|
||||
//console.log("field", name, schema);
|
||||
if (!isTypeSchema(schema))
|
||||
return (
|
||||
<Pre>
|
||||
[Field] {pointer} has no schema ({JSON.stringify(schema)})
|
||||
</Pre>
|
||||
);
|
||||
|
||||
if (isType(schema.type, "object")) {
|
||||
return <ObjectField path={name} schema={schema} />;
|
||||
@@ -31,39 +35,23 @@ export const Field = ({ name, schema: _schema, onChange, label: _label, hidden }
|
||||
}
|
||||
|
||||
const disabled = schema.readOnly ?? "const" in schema ?? false;
|
||||
//console.log("field", name, disabled, schema, ctx.schema, _schema);
|
||||
|
||||
const handleChange = useEvent((e: ChangeEvent<HTMLInputElement>) => {
|
||||
// don't remove for now, causes issues in anyOf
|
||||
/*const value = coerce(e.target.value, schema as any);
|
||||
setValue(pointer, value as any);*/
|
||||
|
||||
const value = coerce(e.target.value, schema as any, { required });
|
||||
//console.log("handleChange", pointer, e.target.value, { value }, ctx.options);
|
||||
if (typeof value === "undefined" && !required && ctx.options?.keepEmpty !== true) {
|
||||
ctx.deleteValue(pointer);
|
||||
} else {
|
||||
//console.log("setValue", pointer, value);
|
||||
setValue(pointer, value);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<FieldWrapper
|
||||
pointer={pointer}
|
||||
label={_label}
|
||||
required={required}
|
||||
errors={errors}
|
||||
schema={schema}
|
||||
debug={{ value }}
|
||||
hidden={hidden}
|
||||
>
|
||||
<FieldWrapper name={name} label={_label} required={required} schema={schema} hidden={hidden}>
|
||||
<FieldComponent
|
||||
schema={schema}
|
||||
name={pointer}
|
||||
name={name}
|
||||
required={required}
|
||||
disabled={disabled}
|
||||
value={value}
|
||||
onChange={onChange ?? handleChange}
|
||||
/>
|
||||
</FieldWrapper>
|
||||
@@ -71,19 +59,25 @@ export const Field = ({ name, schema: _schema, onChange, label: _label, hidden }
|
||||
};
|
||||
|
||||
export const Pre = ({ children }) => (
|
||||
<pre className="dark:bg-red-950 bg-red-100 rounded-md px-3 py-1.5">{children}</pre>
|
||||
<pre className="dark:bg-red-950 bg-red-100 rounded-md px-3 py-1.5 text-wrap whitespace-break-spaces break-all">
|
||||
{children}
|
||||
</pre>
|
||||
);
|
||||
|
||||
export const FieldComponent = ({
|
||||
schema,
|
||||
...props
|
||||
}: { schema: JSONSchema } & ComponentPropsWithoutRef<"input">) => {
|
||||
..._props
|
||||
}: { schema: JsonSchema } & ComponentPropsWithoutRef<"input">) => {
|
||||
const { value } = useFormValue(_props.name!);
|
||||
if (!isTypeSchema(schema)) return null;
|
||||
const props = {
|
||||
..._props,
|
||||
// allow override
|
||||
value: typeof _props.value !== "undefined" ? _props.value : value
|
||||
};
|
||||
|
||||
if (schema.enum) {
|
||||
return (
|
||||
<Formy.Select id={props.name} {...(props as any)} options={enumToOptions(schema.enum)} />
|
||||
);
|
||||
return <Formy.Select id={props.name} options={schema.enum} {...(props as any)} />;
|
||||
}
|
||||
|
||||
if (isType(schema.type, ["number", "integer"])) {
|
||||
@@ -91,7 +85,7 @@ export const FieldComponent = ({
|
||||
}
|
||||
|
||||
if (isType(schema.type, "boolean")) {
|
||||
return <Formy.Switch id={props.name} {...(props as any)} checked={props.value as any} />;
|
||||
return <Formy.Switch id={props.name} {...(props as any)} checked={value as any} />;
|
||||
}
|
||||
|
||||
return <Formy.Input id={props.name} {...props} value={props.value ?? ""} />;
|
||||
|
||||
Reference in New Issue
Block a user