nej-react-components/Parts/Input.tsx
2025-06-23 10:38:00 +02:00

184 lines
5.4 KiB
TypeScript

import React from "react";
import tw from "twin.macro";
import { useField as useFormikField, useFormikContext, FieldHookConfig } from "formik";
import { IMaskInput, IMaskInputProps, IMaskMixinProps } from 'react-imask';
//const useFormikField = null;
//const useFormikContext = ()=>{};
export function useField(props) {
let getField = useFormikField;
const context = useFormikContext();
if (!context) {
getField = (propsOrFieldName: FieldHookConfig<any>) => {
return [props, null, null];
}
}
return getField(props);
}
export default function Input(
props: React.InputHTMLAttributes<HTMLInputElement> & FieldHookConfig<any> & {
label?: React.ComponentPropsWithoutRef<"label">;
title?: string;
children?: React.ReactNode;
className?: string;
}
) {
/*name, id*/
let { children, ...otherProps } = props;
const [field, meta, helpers] = useField(otherProps);
return (
<div css={[props.title && tw`my-1`, tw`relative`]} className={props.className}>
{props.title && (
<label
{...props.label}
htmlFor={props.id ?? props.name ?? props.title}
css={[tw`block text-secondary text-sm font-bold mb-2`, props.label?.css]}
>
{/*htmlFor={id ?? name ?? title}*/}
{props.title}
</label>
)}
{/*name={name || title} id={id || name || title}*/}
<input
id={props.id ?? props.name ?? props.title}
{...otherProps as any}
{...field}
tw="bg-primary appearance-none border-2 border-secondary rounded w-full py-2 px-4 text-primary leading-tight focus:outline-none focus:bg-secondary focus:border-accent transition duration-150 "
/>
{props.children}
{meta?.touched && meta.error ? (
<div tw="text-[#c23c3c]">{meta.error}</div>
) : null}
</div>
);
}
export function MaskedInput(
props: Omit<IMaskInputProps<HTMLInputElement>, "validate" | "label"> & FieldHookConfig<any> & {
definitions: { [k: string]: RegExp };
label?: React.ComponentPropsWithoutRef<"label">;
title?: string;
children?: React.ReactNode;
className?: string;
}
) {
/*name, id*/
let { children, validate, ...otherProps } = props;
const [field, meta, helpers] = useField({ ...otherProps, validate });
return (
<div css={[props.title && tw`my-1`, tw`relative`]} className={props.className}>
{props.title && (
<label
{...props.label}
//htmlFor={props.id ?? props.name ?? props.title}
css={[tw`block text-secondary text-sm font-bold mb-2`, props.label?.css]}
>
{/*htmlFor={id ?? name ?? title}*/}
{props.title}
</label>
)}
{/*name={name || title} id={id || name || title}*/}
<IMaskInput
//id={props.id ?? props.name ?? props.title}
{...otherProps as any}
value={field.value}
unmask="typed"
onAccept={
(value, mask) => field.onChange({ target: { value, name: field.name } })
}
onBlur={field.onBlur}
tw="bg-primary appearance-none border-2 border-secondary rounded w-full py-2 px-4 text-primary leading-tight focus:outline-none focus:bg-secondary focus:border-accent transition duration-150 "
/>
{props.children}
{meta?.touched && meta.error ? (
<div tw="text-[#c23c3c]">{meta.error}</div>
) : null}
</div>
);
}
export function TextArea({
title,
children = null,
label = null,
...props
}) {
const [field, meta, helpers] = useField(props);
return (
<div css={[title && tw`my-1`]} >
{title && (
<label
{...label}
css={[tw`block text-secondary text-sm font-bold mb-2`, label?.css]}
>
{title}
</label>
)}
<textarea
{...props}
{...field}
tw="bg-primary appearance-none border-2 border-secondary rounded w-full py-2 px-4 text-primary leading-tight focus:outline-none focus:bg-secondary focus:border-accent transition duration-150 "
/>
{children}
{meta?.touched && meta.error ? (
<div tw="text-[#c23c3c]">{meta.error}</div>
) : null}
</div>
);
}
/**
* Renders a checkbox input with optional label and error message.
*
* @param {Object} props - The properties for the CheckBox component.
* @param {string} props.label - The label for the checkbox.
* @param {string} props.title - The title for the checkbox.
* @param {string} props.className - The class name for the container div.
* @param {ReactNode} props.children - The children components.
* @param {Object} props... - Additional properties for the checkbox input.
* @return {ReactElement} The rendered CheckBox component.
*/
export function CheckBox({
label,
title,
children,
...props
}) {
const [field, meta, helpers] = useField(props);
return (
<div tw="my-1 flex text-secondary">
<input
checked={field.value}
{...props}
{...field}
type="checkbox"
tw="checked:bg-accent w-6 h-6 rounded-full bg-secondary border-secondary border-4 appearance-none cursor-pointer "
/>
{title != null ? (
<label
{...label}
css={[tw`block font-bold px-2`, label?.css]}
>
{title}
</label>
) : null}
{children}
{meta?.touched && meta.error ? (
<div tw="text-[#c23c3c]">{meta.error}</div>
) : null}
</div>
);
}