import { ui, rgb } from "@rezi-ui/core";
import { createNodeApp } from "@rezi-ui/node";
type FormState = {
email: string;
password: string;
errors: { email?: string; password?: string };
touched: { email: boolean; password: boolean };
};
function validateEmail(email: string): string | undefined {
if (!email) return "Email is required";
if (!email.includes("@")) return "Invalid email format";
return undefined;
}
function validatePassword(password: string): string | undefined {
if (!password) return "Password is required";
if (password.length < 8) return "Password must be at least 8 characters";
return undefined;
}
const app = createNodeApp<FormState>({
initialState: {
email: "",
password: "",
errors: {},
touched: { email: false, password: false },
},
});
function validateAll(s: FormState): FormState["errors"] {
return {
email: validateEmail(s.email),
password: validatePassword(s.password),
};
}
app.view((state) => {
const errors = state.errors;
const touched = state.touched;
const canSubmit =
!errors.email &&
!errors.password &&
state.email.length > 0 &&
state.password.length > 0;
return ui.page({ p: 1 }, [
ui.panel("Sign Up", [
ui.form([
ui.field({
label: "Email",
required: true,
error: touched.email ? errors.email : undefined,
children: ui.input({
id: "email",
value: state.email,
onInput: (value) =>
app.update((s) => {
const next = { ...s, email: value };
return { ...next, errors: validateAll(next) };
}),
onBlur: () =>
app.update((s) => ({
...s,
touched: { ...s.touched, email: true },
})),
}),
}),
ui.field({
label: "Password",
required: true,
hint: "At least 8 characters",
error: touched.password ? errors.password : undefined,
children: ui.input({
id: "password",
value: state.password,
onInput: (value) =>
app.update((s) => {
const next = { ...s, password: value };
return { ...next, errors: validateAll(next) };
}),
onBlur: () =>
app.update((s) => ({
...s,
touched: { ...s.touched, password: true },
})),
}),
}),
]),
ui.actions([
ui.button({
id: "submit",
label: "Create account",
intent: "primary",
disabled: !canSubmit,
onPress: () => {
// Handle form submission
console.log("Submit:", state);
},
}),
]),
!canSubmit &&
ui.text("Fix validation errors to enable submission.", {
style: { fg: rgb(255, 110, 110) },
}),
]),
]);
});
app.keys({
"ctrl+c": () => app.stop(),
q: () => app.stop(),
});
await app.start();