tutu/src/material/TextField.tsx
2024-07-14 20:28:44 +08:00

80 lines
1.9 KiB
TypeScript

import {
Component,
createEffect,
createSignal,
createUniqueId,
onMount,
Show,
} from "solid-js";
import formStyles from "./form.module.css";
export type TextFieldProps = {
label?: string;
helperText?: string;
type?: "text" | "password";
onChange?: (value: string) => void;
onInput?: (value: string) => void;
inputId?: string;
error?: boolean;
required?: boolean;
name?: string;
};
const TextField: Component<TextFieldProps> = (props) => {
let input: HTMLInputElement;
let field: HTMLDivElement;
const [hasContent, setHasContent] = createSignal(false);
const altInputId = createUniqueId();
createEffect(() => {
if (hasContent()) {
field.classList.add("float-label");
} else {
field.classList.remove("float-label");
}
});
onMount(() => {
setHasContent(input.value.length > 0);
});
const onInputChange = (e: { currentTarget: HTMLInputElement }) => {
const value = (e.currentTarget as HTMLInputElement).value;
setHasContent(value.length > 0);
props.onInput?.(value);
};
const inputId = () => props.inputId ?? altInputId;
const fieldClass = () => {
const cls = [formStyles.textfield];
if (typeof props.helperText !== "undefined") {
cls.push(formStyles.withHelperText);
}
if (props.error) {
cls.push(formStyles.error);
}
return cls.join(" ");
};
return (
<div ref={field!} class={fieldClass()}>
<label for={inputId()}>{props.label}</label>
<input
ref={input!}
id={inputId()}
type={props.type ?? "text"}
onInput={onInputChange}
onChange={(e) => props.onChange?.(e.currentTarget.value)}
placeholder=""
required={props.required}
name={props.name}
/>
<Show when={typeof props.helperText !== "undefined"}>
<span class={formStyles.helperText}>{props.helperText}</span>
</Show>
</div>
);
};
export default TextField;