From cb535460350bd510dd4b2b7d6bc3c6ec5f5bcdf1 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 10 May 2023 00:53:37 -0300 Subject: almost first document --- .../exchange-backoffice-ui/src/forms/useField.ts | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/exchange-backoffice-ui/src/forms/useField.ts (limited to 'packages/exchange-backoffice-ui/src/forms/useField.ts') diff --git a/packages/exchange-backoffice-ui/src/forms/useField.ts b/packages/exchange-backoffice-ui/src/forms/useField.ts new file mode 100644 index 000000000..6f7b84112 --- /dev/null +++ b/packages/exchange-backoffice-ui/src/forms/useField.ts @@ -0,0 +1,72 @@ +import { TargetedEvent, useContext, useState } from "preact/compat"; +import { FormContext, InputFieldState } from "./FormProvider.js"; + +export interface InputFieldHandler { + value: Type; + onChange: (s: Type) => void; + state: InputFieldState; + isDirty: boolean; +} + +export function useField(name: keyof T): InputFieldHandler { + const { + initialValue, + value: formValue, + computeFormState, + onUpdate, + } = useContext(FormContext); + type P = typeof name; + type V = T[P]; + const [isDirty, setDirty] = useState(false); + const formState = computeFormState ? computeFormState(formValue) : {}; + + const fieldValue = readField(formValue, String(name)) as V; + const fieldState = readField>( + formState, + String(name), + ); + + //default state + const state: InputFieldState = { + disabled: fieldState?.disabled ?? false, + readonly: fieldState?.readonly ?? false, + hidden: fieldState?.hidden ?? false, + error: fieldState?.error, + }; + + function onChange(value: V): void { + setDirty(true); + return onUpdate((prev: any) => { + return setValueDeeper(prev, String(name).split("."), value); + }); + } + + return { + value: fieldValue, + onChange, + isDirty, + state, + }; +} + +/** + * read the field of an object an support accessing it using '.' + * + * @param object + * @param name + * @returns + */ +function readField(object: any, name: string): T | undefined { + return name + .split(".") + .reduce((prev, current) => prev && prev[current], object); +} + +function setValueDeeper(object: any, names: string[], value: any): any { + if (names.length === 0) return value; + const [head, ...rest] = names; + if (object === undefined) { + return { [head]: setValueDeeper({}, rest, value) }; + } + return { ...object, [head]: setValueDeeper(object[head] ?? {}, rest, value) }; +} -- cgit v1.2.3