/** * FormGrid Component * * A reusable grid layout component that: * - Provides responsive grid layouts for form fields * - Handles different column configurations * - Supports gap spacing * - Maintains consistent alignment * * This component improves form layout and responsiveness. */ import React from 'react'; import { cn } from '@/lib/utils'; // ============================================================================= // TYPES // ============================================================================= export interface FormGridProps { // Grid configuration cols?: 1 | 2 | 3 | 4 | 6 | 12; sm?: 1 | 2 | 3 | 4 | 6 | 12; md?: 1 | 2 | 3 | 4 | 6 | 12; lg?: 1 | 2 | 3 | 4 | 6 | 12; xl?: 1 | 2 | 3 | 4 | 6 | 12; // Spacing gap?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; gapX?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; gapY?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; // Alignment align?: 'start' | 'center' | 'end' | 'stretch'; justify?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly'; // Styling className?: string; // Children children: React.ReactNode; } // ============================================================================= // COMPONENT // ============================================================================= export function FormGrid({ cols = 1, sm, md, lg, xl, gap = 'md', gapX, gapY, align = 'start', justify = 'start', className = '', children, }: FormGridProps) { // ============================================================================= // HELPER FUNCTIONS // ============================================================================= const getGridCols = (cols: number) => { return `grid-cols-${cols}`; }; const getResponsiveCols = () => { const classes = [getGridCols(cols)]; if (sm) classes.push(`sm:grid-cols-${sm}`); if (md) classes.push(`md:grid-cols-${md}`); if (lg) classes.push(`lg:grid-cols-${lg}`); if (xl) classes.push(`xl:grid-cols-${xl}`); return classes.join(' '); }; const getGap = (gap: 'xs' | 'sm' | 'md' | 'lg' | 'xl') => { switch (gap) { case 'xs': return 'gap-1'; case 'sm': return 'gap-2'; case 'lg': return 'gap-6'; case 'xl': return 'gap-8'; default: return 'gap-4'; } }; const getGapX = (gapX: 'xs' | 'sm' | 'md' | 'lg' | 'xl') => { switch (gapX) { case 'xs': return 'gap-x-1'; case 'sm': return 'gap-x-2'; case 'lg': return 'gap-x-6'; case 'xl': return 'gap-x-8'; default: return 'gap-x-4'; } }; const getGapY = (gapY: 'xs' | 'sm' | 'md' | 'lg' | 'xl') => { switch (gapY) { case 'xs': return 'gap-y-1'; case 'sm': return 'gap-y-2'; case 'lg': return 'gap-y-6'; case 'xl': return 'gap-y-8'; default: return 'gap-y-4'; } }; const getAlign = (align: 'start' | 'center' | 'end' | 'stretch') => { switch (align) { case 'center': return 'items-center'; case 'end': return 'items-end'; case 'stretch': return 'items-stretch'; default: return 'items-start'; } }; const getJustify = (justify: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly') => { switch (justify) { case 'center': return 'justify-center'; case 'end': return 'justify-end'; case 'between': return 'justify-between'; case 'around': return 'justify-around'; case 'evenly': return 'justify-evenly'; default: return 'justify-start'; } }; // ============================================================================= // MAIN RENDER // ============================================================================= const gridClasses = cn( 'grid', getResponsiveCols(), gapX ? getGapX(gapX) : gapY ? getGapY(gapY) : getGap(gap), getAlign(align), getJustify(justify), className ); return (