From fdbe623e1060efc4b074d213a96e8f5a2ab7498b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 20 Sep 2023 15:16:28 -0300 Subject: more ui stuff, moved forms to util --- packages/web-util/src/forms/InputArray.tsx | 183 +++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 packages/web-util/src/forms/InputArray.tsx (limited to 'packages/web-util/src/forms/InputArray.tsx') diff --git a/packages/web-util/src/forms/InputArray.tsx b/packages/web-util/src/forms/InputArray.tsx new file mode 100644 index 000000000..00379bed6 --- /dev/null +++ b/packages/web-util/src/forms/InputArray.tsx @@ -0,0 +1,183 @@ +import { Fragment, VNode, h } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import { FormProvider, InputArrayFieldState } from "./FormProvider.js"; +import { LabelWithTooltipMaybeRequired, UIFormProps } from "./InputLine.js"; +import { RenderAllFieldsByUiConfig, UIFormField } from "./forms.js"; +import { useField } from "./useField.js"; +import { TranslatedString } from "@gnu-taler/taler-util"; + +function Option({ + label, + disabled, + isFirst, + isLast, + isSelected, + onClick, +}: { + label: TranslatedString; + isFirst?: boolean; + isLast?: boolean; + isSelected?: boolean; + disabled?: boolean; + onClick: () => void; +}): VNode { + let clazz = "relative flex border p-4 focus:outline-none disabled:text-grey"; + if (isFirst) { + clazz += " rounded-tl-md rounded-tr-md "; + } + if (isLast) { + clazz += " rounded-bl-md rounded-br-md "; + } + if (isSelected) { + clazz += " z-10 border-indigo-200 bg-indigo-50 "; + } else { + clazz += " border-gray-200"; + } + if (disabled) { + clazz += + " cursor-not-allowed bg-gray-50 text-gray-500 ring-gray-200 text-gray"; + } else { + clazz += " cursor-pointer"; + } + return ( + + ); +} + +export function InputArray( + props: { + fields: UIFormField[]; + labelField: string; + } & UIFormProps, +): VNode { + const { fields, labelField, name, label, required, tooltip } = props; + const { value, onChange, state } = useField(name); + const list = (value ?? []) as Array>; + const [selectedIndex, setSelected] = useState(undefined); + const selected = + selectedIndex === undefined ? undefined : list[selectedIndex]; + + return ( +
+ + +
+ {list.map((v, idx) => { + return ( +
+ {selectedIndex !== undefined && ( + /** + * This form provider act as a substate of the parent form + * Consider creating an InnerFormProvider since not every feature is expected + */ + { + // current state is ignored + // the state is defined by the parent form + + // elements should be present in the state object since this is expected to be an array + //@ts-ignore + return state.elements[selectedIndex]; + }} + onSubmit={(v) => { + const newValue = [...list]; + newValue.splice(selectedIndex, 1, v); + onChange(newValue as T[K]); + setSelected(undefined); + }} + onUpdate={(v) => { + const newValue = [...list]; + newValue.splice(selectedIndex, 1, v); + onChange(newValue as T[K]); + }} + > +
+
+ +
+
+
+ )} + {selectedIndex !== undefined && ( +
+
+ {selected !== undefined && ( + + )} +
+
+ )} +
+ ); +} -- cgit v1.2.3