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" import { Typography } from "../Typography" 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/Input/TextArea", component: FormTextAreaComponent, argTypes: { label: { control: "text", name: "Label", description: "Label text", table: { type: { summary: "string" }, order: 1, }, }, placeholder: { control: "text", name: "Placeholder", description: "Placeholder text", table: { type: { summary: "string" }, defaultValue: { summary: "undefined" }, order: 2, }, }, showDescription: { control: "boolean", name: "Show Description", description: "Show description", table: { type: { summary: "boolean" }, defaultValue: { summary: "true" }, order: 3, }, }, description: { control: "text", name: "Description", description: "Helper text (hidden when error is shown)", table: { type: { summary: "string" }, defaultValue: { summary: "undefined" }, order: 4, }, }, descriptionIcon: { control: "select", name: "Description Icon", options: ["info", "warning", "error"], description: "Description icon", table: { type: { summary: "string" }, defaultValue: { summary: "'info'" }, order: 5, }, }, required: { control: "boolean", name: "Required", description: "Required field", table: { type: { summary: "boolean" }, defaultValue: { summary: "false" }, order: 6, }, }, disabled: { control: "boolean", name: "Disabled", description: "Disabled state", table: { type: { summary: "boolean" }, defaultValue: { summary: "false" }, order: 7, }, }, readOnly: { control: "boolean", name: "Read Only", description: "Read-only state", table: { type: { summary: "boolean" }, defaultValue: { summary: "false" }, order: 8, }, }, showLabel: { control: "boolean", name: "Show Label", description: "Show label", table: { type: { summary: "boolean" }, defaultValue: { summary: "true" }, order: 9, }, }, errorMessage: { control: "text", name: "Error Message", description: "Error message", table: { type: { summary: "string" }, defaultValue: { summary: "undefined" }, order: 10, }, }, }, } export default meta type Story = StoryObj export const Default: Story = { args: { label: "Label", placeholder: "Placeholder", required: false, disabled: false, readOnly: false, showLabel: true, showDescription: true, errorMessage: undefined, }, } // ============================================================================ // TextArea Variations Showcase // ============================================================================ const showcaseSchema = z.object({ default: z.string().optional(), placeholder: z.string().optional(), withDescription: z.string().optional(), withDescriptionPlaceholder: z.string().optional(), filled: z.string().optional(), required: z.string().min(1, "This field is required"), disabled: z.string().optional(), disabledFilled: z.string().optional(), error: z.string().min(10, "Must be at least 10 characters"), errorFilled: z.string().min(10, "Invalid content"), descriptionInfo: z.string().optional(), descriptionWarning: z.string().optional(), }) type ShowcaseFormData = z.infer function TextAreaShowcase() { const methods = useForm({ resolver: zodResolver(showcaseSchema), defaultValues: { filled: "This is a sample text that fills the textarea with some content.", disabledFilled: "This textarea is disabled and cannot be edited.", error: "Short", errorFilled: "Invalid content", }, mode: "onChange", }) // Trigger validation for error examples on mount useEffect(() => { methods.trigger(["error", "errorFilled"]) }, [methods]) return ( {/* Basic States */} Basic States {/* Supporting Text Variations */} Supporting Text {/* Validation States */} Validation States ) } export const AllVariations: StoryObj = { render: () => , parameters: { layout: "fullscreen", }, }