From d89bfe83f6d7d68b7a3171fcffb5db3309a45f4d Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 21:12:01 +0000 Subject: [PATCH 1/2] feat: integrate @lambdacurry/forms library with comprehensive examples - Add @lambdacurry/forms and related dependencies to package.json files - Add lambda-curry-forms.mdc cursor rule with comprehensive guidelines - Update AddTodo component to use forms library with Zod validation - Update TodoItem component with forms-powered editing functionality - Create advanced create-todo route demonstrating all form components: - TextField (single-line and multiline) - RadioGroup for priority selection - DatePicker for due dates - Checkbox for urgent flag - FormError for server-side error handling - Add navigation link to advanced form from home page - Include comprehensive documentation in FORMS_INTEGRATION.md - Demonstrate type-safe forms with progressive enhancement - Show server-side validation with getValidatedFormData - Maintain accessibility compliance (WCAG 2.1 AA) This integration provides a complete example of modern form handling in React Router 7 applications using Lambda Curry's forms library. --- .cursorrules/lambda-curry-forms.mdc | 273 +++++++++++++++++++++ FORMS_INTEGRATION.md | 214 ++++++++++++++++ apps/todo-app/app/components/add-todo.tsx | 61 +++-- apps/todo-app/app/components/todo-item.tsx | 80 +++--- apps/todo-app/app/routes.ts | 3 +- apps/todo-app/app/routes/create-todo.tsx | 253 +++++++++++++++++++ apps/todo-app/app/routes/home.tsx | 24 +- apps/todo-app/package.json | 6 +- package.json | 8 +- 9 files changed, 855 insertions(+), 67 deletions(-) create mode 100644 .cursorrules/lambda-curry-forms.mdc create mode 100644 FORMS_INTEGRATION.md create mode 100644 apps/todo-app/app/routes/create-todo.tsx diff --git a/.cursorrules/lambda-curry-forms.mdc b/.cursorrules/lambda-curry-forms.mdc new file mode 100644 index 0000000..2d4dd53 --- /dev/null +++ b/.cursorrules/lambda-curry-forms.mdc @@ -0,0 +1,273 @@ +--- +description: Guidelines for using @lambdacurry/forms library with Remix Hook Form and Zod validation +globs: app/**/*.tsx, app/**/*.ts, components/**/*.tsx, components/**/*.ts +alwaysApply: true +--- + +**Summary:** +This document provides essential guidelines for using `@lambdacurry/forms` with `remix-hook-form` and Zod v4. Key benefits include progressive enhancement, type safety, consistent UI, and WCAG 2.1 AA accessibility compliance. Always prefer `remix-hook-form` over other form libraries in Remix applications. + +**Reference Documentation:** https://raw.githubusercontent.com/lambda-curry/forms/refs/heads/main/llms.txt + +## Core Architecture & Setup + +**@lambdacurry/forms** provides form-aware wrapper components that automatically integrate with React Router and Remix Hook Form context, eliminating boilerplate while maintaining full customization. + +### Essential Imports & Setup +```typescript +import { zodResolver } from '@hookform/resolvers/zod'; +import { RemixFormProvider, useRemixForm, getValidatedFormData } from 'remix-hook-form'; +import { z } from 'zod'; +import { useFetcher, type ActionFunctionArgs } from 'react-router'; +import { TextField, Checkbox, RadioGroup, DatePicker, FormError } from '@lambdacurry/forms'; +import { Button } from '@lambdacurry/forms/ui'; +``` + +### Zod Schema Patterns +```typescript +const formSchema = z.object({ + email: z.string().email('Invalid email address'), + password: z.string().min(8, 'Password must be at least 8 characters'), + terms: z.boolean().refine(val => val === true, 'You must accept terms'), +}); + +type FormData = z.infer; +``` + +## Standard Form Implementation Pattern + +### Complete Login Form Example with FormError +```typescript +const LoginForm = () => { + const fetcher = useFetcher<{ + message?: string; + errors?: Record + }>(); + + const methods = useRemixForm({ + resolver: zodResolver(formSchema), + defaultValues: { email: '', password: '' }, + fetcher, + submitConfig: { action: '/login', method: 'post' }, + }); + + const isSubmitting = fetcher.state === 'submitting'; + + return ( + + + + + + + {/* Place FormError before the submit button for critical errors */} + + + + + + ); +}; +``` + +### Server Action Handler with FormError Support +```typescript +export const action = async ({ request }: ActionFunctionArgs) => { + const { data, errors } = await getValidatedFormData( + request, + zodResolver(formSchema) + ); + + if (errors) return { errors }; + + try { + const user = await authenticateUser(data.email, data.password); + return { message: 'Login successful!' }; + } catch (error) { + // Multiple error types - field-level and form-level + return { + errors: { + email: { message: 'Account may be suspended' }, + _form: { message: 'Invalid credentials. Please try again.' } + } + }; + } +}; +``` + +## Advanced Patterns + +### Conditional Fields +```typescript +const watchAccountType = methods.watch('accountType'); + +{watchAccountType === 'business' && ( + +)} +``` + +## Available Form Components + +### TextField Component +```typescript + +``` + +### Checkbox Component +```typescript + +``` + +### RadioGroup Component +```typescript +// Pattern 1: Using options prop + + +// Pattern 2: Using RadioGroupItem children + + + + +``` + +### Other Components +```typescript +