import { zodResolver } from "@hookform/resolvers/zod"
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { useEffect } from "react"
import { FormProvider, useForm } from "react-hook-form"
import { z } from "zod"
import { FormTextArea } from "../Form/FormTextArea"
import type { MaterialIconProps } from "../Icons/MaterialIcon"
interface FormTextAreaStoryProps {
label?: string
placeholder?: string
description?: string
descriptionIcon?: MaterialIconProps["icon"]
disabled?: boolean
readOnly?: boolean
required?: boolean
showLabel?: boolean
showDescription?: boolean
showDescriptionIcon?: boolean
filled?: boolean
defaultValue?: string
errorMessage?: string
name?: string
}
function FormTextAreaComponent({
label,
placeholder,
description,
descriptionIcon = "info",
disabled = false,
readOnly = false,
required = false,
showLabel = true,
showDescription = true,
showDescriptionIcon = true,
filled = false,
defaultValue = "",
errorMessage,
name = "textarea",
}: FormTextAreaStoryProps) {
const schema = z.object({
[name]: errorMessage
? z.string().min(1, errorMessage)
: required
? z.string().min(1, "This field is required")
: z.string().optional(),
})
const methods = useForm<{ [key: string]: string }>({
resolver: zodResolver(schema),
defaultValues: {
[name]: filled ? defaultValue : "",
},
mode: "onChange",
})
useEffect(() => {
if (errorMessage) {
// Set error manually if errorMessage is provided
methods.setError(name, {
type: "manual",
message: errorMessage,
})
// Trigger validation to show the error immediately
methods.trigger(name)
} else {
// Clear errors if errorMessage is removed
methods.clearErrors(name)
}
}, [errorMessage, methods, name])
return (
)
}
const meta: Meta = {
title: "Core Components/TextArea",
component: FormTextAreaComponent,
argTypes: {
label: {
control: "text",
description: "The label text displayed above the textarea field",
table: {
type: { summary: "string" },
},
},
placeholder: {
control: "text",
description: "Placeholder text shown when textarea is empty",
table: {
type: { summary: "string" },
defaultValue: { summary: "undefined" },
},
},
description: {
control: "text",
description: "Supporting text displayed below the textarea",
table: {
type: { summary: "string" },
defaultValue: { summary: "undefined" },
},
},
disabled: {
control: "boolean",
description: "Whether the textarea is disabled",
table: {
type: { summary: "boolean" },
defaultValue: { summary: "false" },
},
},
readOnly: {
control: "boolean",
description: "Whether the textarea is read-only",
table: {
type: { summary: "boolean" },
defaultValue: { summary: "false" },
},
},
required: {
control: "boolean",
description: "Whether the textarea is required",
table: {
type: { summary: "boolean" },
defaultValue: { summary: "false" },
},
},
showLabel: {
control: "boolean",
description: "Whether to show the label",
table: {
type: { summary: "boolean" },
defaultValue: { summary: "true" },
},
},
showDescription: {
control: "boolean",
description: "Whether to show the description/supporting text",
table: {
type: { summary: "boolean" },
defaultValue: { summary: "true" },
},
},
defaultValue: {
control: "text",
description: "Default value when filled is true",
table: {
type: { summary: "string" },
defaultValue: { summary: "" },
},
},
errorMessage: {
control: "text",
description: "Error message to display (triggers error state)",
table: {
type: { summary: "string" },
defaultValue: { summary: "undefined" },
},
},
},
}
export default meta
type Story = StoryObj
export const Default: Story = {
args: {
label: "Label",
placeholder: "Placeholder",
description: "Supporting text",
disabled: false,
readOnly: false,
required: false,
showLabel: true,
showDescription: true,
defaultValue: "",
errorMessage: undefined,
},
}