{"version":3,"file":"Form.cjs","names":[],"sources":["../../../src/components/Form/Form.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { CSSProperties, FormHTMLAttributes, HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Form.module.css\";\n\nexport type FormLayout = \"stack\" | \"inline\" | \"grid\";\nexport type FormActionsAlign = \"start\" | \"center\" | \"end\" | \"between\";\n\ninterface LayoutProps {\n    /** Field arrangement. `stack` stacks fields vertically, `inline` lines them up in a wrapping row, `grid` arranges them in `columns` equal-width tracks. Default `stack`. */\n    layout?: FormLayout;\n    /** Number of columns when `layout=\"grid\"`, or a custom `grid-template-columns` value. Default `2`. */\n    columns?: number | string;\n    /** Gap between fields. Numbers map to a multiple of the 4px scale (default `4` → 16px). */\n    gap?: number | string;\n}\n\nfunction resolveGap(gap: number | string | undefined, fallback: number): string {\n    if (gap === undefined) return `${fallback * 4}px`;\n    return typeof gap === \"number\" ? `${gap * 4}px` : gap;\n}\n\nfunction resolveColumns(columns: number | string | undefined): string {\n    if (columns === undefined) return \"repeat(2, minmax(0, 1fr))\";\n    return typeof columns === \"number\" ? `repeat(${columns}, minmax(0, 1fr))` : columns;\n}\n\nexport interface FormProps extends FormHTMLAttributes<HTMLFormElement>, LayoutProps {}\n\n/**\n * Form wrapper with a built-in layout variant. Replaces ad-hoc `<form>` +\n * `<Stack>` / `<Grid>` boilerplate; pair with [[FormRow]], [[FormSection]],\n * and [[FormActions]] for richer layouts.\n *\n * @example\n * <Form layout=\"grid\" columns={2} gap={4} onSubmit={form.handleSubmit(save)}>\n *     <Input label=\"Nome\" {...form.register(\"name\")} />\n *     <Input label=\"Email\" {...form.register(\"email\")} />\n *     <FormActions align=\"end\">\n *         <Button type=\"submit\">Salvar</Button>\n *     </FormActions>\n * </Form>\n */\nexport const Form = forwardRef<HTMLFormElement, FormProps>(function Form(\n    { layout = \"stack\", columns, gap, className, style, children, ...props },\n    ref,\n) {\n    const finalStyle: CSSProperties = {\n        gap: resolveGap(gap, 4),\n        ...(layout === \"grid\" ? { gridTemplateColumns: resolveColumns(columns) } : null),\n        ...style,\n    };\n    return (\n        <form\n            ref={ref}\n            className={cn(styles.form, styles[layout], className)}\n            style={finalStyle}\n            {...props}\n        >\n            {children}\n        </form>\n    );\n});\n\nexport interface FormSectionProps extends Omit<HTMLAttributes<HTMLElement>, \"title\">, LayoutProps {\n    title?: ReactNode;\n    description?: ReactNode;\n}\n\n/**\n * Visually grouped subset of fields with an optional title and description.\n * Has its own `layout`/`columns`/`gap` so subsets can stack while the parent\n * grids (or vice versa).\n *\n * @example\n * <FormSection title=\"Endereço\" description=\"Usado para entrega\" layout=\"grid\" columns={3}>\n *     <Input label=\"CEP\" />\n *     <Input label=\"Rua\" />\n *     <Input label=\"Número\" />\n * </FormSection>\n */\nexport function FormSection({\n    title,\n    description,\n    layout = \"stack\",\n    columns,\n    gap,\n    className,\n    style,\n    children,\n    ...props\n}: FormSectionProps) {\n    const bodyStyle: CSSProperties = {\n        gap: resolveGap(gap, 4),\n        ...(layout === \"grid\" ? { gridTemplateColumns: resolveColumns(columns) } : null),\n    };\n    return (\n        <section className={cn(styles.section, className)} style={style} {...props}>\n            {(title || description) && (\n                <header className={styles.sectionHeader}>\n                    {title && <h3 className={styles.sectionTitle}>{title}</h3>}\n                    {description && <p className={styles.sectionDescription}>{description}</p>}\n                </header>\n            )}\n            <div className={cn(styles.sectionBody, styles[layout])} style={bodyStyle}>\n                {children}\n            </div>\n        </section>\n    );\n}\n\nexport interface FormRowProps extends HTMLAttributes<HTMLDivElement> {\n    /** Gap between row items. Numbers map to a multiple of the 4px scale (default `3` → 12px). */\n    gap?: number | string;\n}\n\n/**\n * Forces a horizontal row regardless of parent layout — useful for grouping\n * two short fields side-by-side inside an otherwise stacked form (e.g. CEP +\n * city, expiry month + year).\n *\n * @example\n * <Form layout=\"stack\">\n *     <FormRow>\n *         <Input label=\"CEP\" />\n *         <Input label=\"Cidade\" />\n *     </FormRow>\n *     <Input label=\"Endereço completo\" />\n * </Form>\n */\nexport function FormRow({ gap, className, style, children, ...props }: FormRowProps) {\n    const finalStyle: CSSProperties = { gap: resolveGap(gap, 3), ...style };\n    return (\n        <div className={cn(styles.row, className)} style={finalStyle} {...props}>\n            {children}\n        </div>\n    );\n}\n\nexport interface FormActionsProps extends HTMLAttributes<HTMLDivElement> {\n    /** Horizontal alignment of buttons. Default `end`. */\n    align?: FormActionsAlign;\n    /** Gap between buttons. Numbers map to a multiple of the 4px scale (default `2` → 8px). */\n    gap?: number | string;\n}\n\n/**\n * Footer button row for a form. Use inside (or after) [[Form]] / [[FormSection]].\n *\n * @example\n * <FormActions align=\"end\">\n *     <Button variant=\"ghost\" onClick={onCancel}>Cancelar</Button>\n *     <Button type=\"submit\" loading={form.formState.isSubmitting}>Salvar</Button>\n * </FormActions>\n */\nexport function FormActions({\n    align = \"end\",\n    gap,\n    className,\n    style,\n    children,\n    ...props\n}: FormActionsProps) {\n    const finalStyle: CSSProperties = { gap: resolveGap(gap, 2), ...style };\n    return (\n        <div className={cn(styles.actions, styles[align], className)} style={finalStyle} {...props}>\n            {children}\n        </div>\n    );\n}\n"],"mappings":"2HAiBA,SAAS,EAAW,EAAkC,EAA0B,CAE5E,OADI,IAAQ,IAAA,GAAkB,GAAG,EAAW,EAAE,IACvC,OAAO,GAAQ,SAAW,GAAG,EAAM,EAAE,IAAM,CACtD,CAEA,SAAS,EAAe,EAA8C,CAElE,OADI,IAAY,IAAA,GAAkB,4BAC3B,OAAO,GAAY,SAAW,UAAU,EAAQ,mBAAqB,CAChF,CAkBA,IAAa,GAAA,EAAO,EAAA,WAAA,CAAuC,SACvD,CAAE,SAAS,QAAS,UAAS,MAAK,YAAW,QAAO,WAAU,GAAG,GACjE,EACF,CACE,IAAM,EAA4B,CAC9B,IAAK,EAAW,EAAK,CAAC,EACtB,GAAI,IAAW,OAAS,CAAE,oBAAqB,EAAe,CAAO,CAAE,EAAI,KAC3E,GAAG,CACP,EACA,OACI,EAAA,EAAA,IAAA,CAAC,OAAD,CACS,MACL,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,EAAA,QAAO,GAAS,CAAS,EACpD,MAAO,EACP,GAAI,EAEH,UACC,CAAA,CAEd,CAAC,EAmBD,SAAgB,EAAY,CACxB,QACA,cACA,SAAS,QACT,UACA,MACA,YACA,QACA,WACA,GAAG,GACc,CACjB,IAAM,EAA2B,CAC7B,IAAK,EAAW,EAAK,CAAC,EACtB,GAAI,IAAW,OAAS,CAAE,oBAAqB,EAAe,CAAO,CAAE,EAAI,IAC/E,EACA,OACI,EAAA,EAAA,KAAA,CAAC,UAAD,CAAS,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAS,EAAU,QAAO,GAAI,EAArE,SAAA,EACM,GAAS,KACP,EAAA,EAAA,KAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,cAA1B,SAAA,CACK,IAAS,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAA,QAAO,aAAe,SAAA,CAAU,CAAA,EACxD,IAAe,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,mBAAqB,SAAA,CAAe,CAAA,CACrE,CAEZ,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,YAAa,EAAA,QAAO,EAAO,EAAG,MAAO,EAC1D,UACA,CAAA,CACA,GAEjB,CAqBA,SAAgB,EAAQ,CAAE,MAAK,YAAW,QAAO,WAAU,GAAG,GAAuB,CACjF,IAAM,EAA4B,CAAE,IAAK,EAAW,EAAK,CAAC,EAAG,GAAG,CAAM,EACtE,OACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,IAAK,CAAS,EAAG,MAAO,EAAY,GAAI,EAC7D,UACA,CAAA,CAEb,CAkBA,SAAgB,EAAY,CACxB,QAAQ,MACR,MACA,YACA,QACA,WACA,GAAG,GACc,CACjB,IAAM,EAA4B,CAAE,IAAK,EAAW,EAAK,CAAC,EAAG,GAAG,CAAM,EACtE,OACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,EAAA,QAAO,GAAQ,CAAS,EAAG,MAAO,EAAY,GAAI,EAChF,UACA,CAAA,CAEb"}