ui: improve form field components, add support for custom fields, export components

Enhanced `FieldLabel` to support tooltips and additional props. Refactored form field components for better customizability and ensured compatibility with new `CustomField`. Updated `onChange` handlers to include context for improved flexibility. Added exports for UI components.
This commit is contained in:
dswbx
2025-09-18 10:03:16 +02:00
parent d6f2500be2
commit 15c32c0e6d
8 changed files with 87 additions and 36 deletions

View File

@@ -1,3 +1,4 @@
import { Tooltip } from "@mantine/core";
import clsx from "clsx";
import { getBrowser } from "core/utils";
import type { Field } from "data/fields";
@@ -6,6 +7,7 @@ import {
type ComponentPropsWithoutRef,
type ElementType,
forwardRef,
Fragment,
useEffect,
useImperativeHandle,
useRef,
@@ -66,17 +68,22 @@ export const ErrorMessage: React.FC<React.ComponentProps<"div">> = ({ className,
<div {...props} className={twMerge("text-sm text-red-500", className)} />
);
export const FieldLabel: React.FC<React.ComponentProps<"label"> & { field: Field }> = ({
field,
...props
}) => {
export const FieldLabel: React.FC<
React.ComponentProps<"label"> & { field: Field; label?: string }
> = ({ field, label, ...props }) => {
const desc = field.getDescription();
const Wrapper = desc
? (p) => <Tooltip position="right" label={desc} {...p} />
: (p) => <Fragment {...p} />;
return (
<Label {...props} title={desc} className="flex flex-row gap-1 items-center">
{field.getLabel()}
{field.isRequired() && <span className="font-medium opacity-30">*</span>}
{desc && <TbInfoCircle className="opacity-50" />}
</Label>
<Wrapper>
<Label {...props} className="flex flex-row gap-1 items-center self-start">
{label ?? field.getLabel()}
{field.isRequired() && <span className="font-medium opacity-30">*</span>}
{desc && <TbInfoCircle className="opacity-50" />}
</Label>
</Wrapper>
);
};
@@ -103,6 +110,12 @@ export const TypeAwareInput = forwardRef<HTMLInputElement, React.ComponentProps<
if (props.type === "password") {
return <Password {...props} ref={ref} />;
}
if ("data-type" in props) {
if (props["data-type"] === "textarea") {
// @ts-ignore
return <Textarea {...props} ref={ref} />;
}
}
return <Input {...props} ref={ref} />;
},