/v1.0

FormModal

Modal que renderiza un DynamicForm dentro de una tarjeta Paper. Admite obtener datos iniciales desde una API (fetchPath), enviar mediante métodos HTTP configurables (saveMethod), y callbacks según el modo para creación, edición y edición a nivel de campo. Los errores se muestran mediante un Toast en línea. El formulario se monta de forma diferida hasta que la animación de apertura del modal finaliza.

Props

| Prop | Tipo | Requerido | Por defecto | Descripción | |------|------|-----------|-------------|-------------| | isOpen | boolean | Sí | — | Controla si el modal está visible. | | onClose | (reason: 'cancel' \| 'success' \| 'error' \| 'custom') => void | Sí | — | Se llama cuando el modal se cierra. Recibe una cadena de razón. | | fields | Field[] | Sí | — | Definiciones de campos del formulario. Cada campo tiene type, name y opcionalmente label, config, value. | | backdropStyle | React.CSSProperties | No | — | Estilos en línea para el backdrop del modal. | | windowStyle | React.CSSProperties | No | — | Estilos en línea fusionados en la ventana del modal. | | closeButtonStyle | React.CSSProperties | No | — | Estilos para el botón de cierre. | | closeIcon | string | No | — | Nombre del ícono del botón de cierre. | | closeIconPaths | any[] | No | — | Rutas de ícono personalizadas para el botón de cierre. | | closeIconSize | number | No | — | Tamaño del ícono del botón de cierre. | | zIndex | number | No | — | z-index CSS del overlay del modal. | | id | string | No | — | id HTML del elemento modal. | | fullScreen | boolean | No | — | Cuando es true, el modal ocupa toda la pantalla. | | formTitle | string | No | — | Título mostrado en la tarjeta del formulario. | | data | Record<string, any> | No | — | Valores iniciales de los campos. Si data.formatted_id existe, se muestra encima de la tarjeta. | | fetchPath | string | No | — | Ruta de API para precargar datos del formulario antes de renderizarlo. | | savePath | string | No | — | Ruta de API para enviar el formulario. | | onSave | (formData: Record<string, any>) => void | No | — | Se llama en lugar de una petición API cuando savePath no está definido. | | onCreateSuccess | (formData: Record<string, any>) => void | No | — | Se llama tras un envío de creación exitoso. | | onCreateError | (error: any) => void | No | — | Se llama tras un envío de creación fallido. | | onEditSuccess | (formData: Record<string, any>) => void | No | — | Se llama tras un envío de edición exitoso. | | onEditError | (error: any) => void | No | — | Se llama tras un envío de edición fallido. | | onFieldEditSuccess | (field: any, fieldValue: any, formData: Record<string, any>) => void | No | — | Se llama tras una edición de campo individual exitosa. | | onFieldEditError | (field: any, error: any) => void | No | — | Se llama tras una edición de campo individual fallida. | | extraData | Record<string, any> | No | — | Campos adicionales fusionados en el payload de envío. | | mode | "create" \| "edit" \| "globalEdit" \| "readOnly" \| "submit" \| "view" | No | — | Modo del formulario pasado a DynamicForm. | | apiBaseUrl | string | No | urls.apiBase | URL base del cliente HTTP. | | saveMethod | 'POST' \| 'PUT' \| 'PATCH' | No | 'POST' | Método HTTP para el envío del formulario. | | useAuthToken | boolean | No | — | Cuando es true, usa el cliente HTTP autenticado. | | formWidth | number \| string | No | 700 | Ancho máximo de la tarjeta del formulario. | | formContainerStyle | React.CSSProperties | No | — | Estilos para el contenedor del formulario. | | formHeaderStyle | React.CSSProperties | No | — | Estilos para la sección de encabezado del formulario. | | formBodyStyle | React.CSSProperties | No | — | Estilos para la sección del cuerpo del formulario. | | formTitleStyle | React.CSSProperties | No | — | Estilos para el título del formulario. | | fieldContainerStyle | React.CSSProperties | No | — | Estilos para el contenedor de cada campo. | | fieldLabelStyle | React.CSSProperties | No | — | Estilos para las etiquetas de los campos. | | fieldDescriptionStyle | React.CSSProperties | No | — | Estilos para las descripciones de los campos. | | fieldHeaderStyle | React.CSSProperties | No | — | Estilos para el encabezado de cada campo. | | fieldBodyStyle | React.CSSProperties | No | — | Estilos para el cuerpo de cada campo. | | className | string | No | — | Clase CSS aplicada al formulario. | | sendButtonType | "clear" \| "outline" \| "solid" | No | — | Variante visual del botón de envío. | | sendButtonSize | "xs" \| "sm" \| "md" \| "lg" \| "xl" | No | — | Tamaño del botón de envío. | | sendButtonColor | string | No | — | Color del botón de envío. | | sendButtonTitle | string | No | — | Etiqueta del botón de envío. | | sendButtonIcon | string | No | — | Nombre del ícono del botón de envío. | | sendButtonIconPaths | any[] | No | — | Rutas de ícono personalizadas para el botón de envío. | | sendButtonIconSize | number | No | — | Tamaño del ícono del botón de envío. | | sendButtonStyle | React.CSSProperties | No | — | Estilos en línea para el botón de envío. | | sendButtonTitleStyle | React.CSSProperties | No | — | Estilos en línea para la etiqueta del botón de envío. |

Uso

Básico

import React from 'react';
import FormModal from '@/components/modals/FormModal';

export default function Example() {
  const [open, setOpen] = React.useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Edit Product</button>
      <FormModal
        isOpen={open}
        onClose={(reason) => {
          console.log('Closed:', reason);
          setOpen(false);
        }}
        formTitle="Edit Product"
        fields={[
          { type: 'text', name: 'name', label: 'Name' },
          { type: 'number', name: 'price', label: 'Price' },
        ]}
        data={{ name: 'Blue T-Shirt', price: 29.99 }}
        savePath="/v1/products/123"
        saveMethod="PATCH"
        mode="edit"
        useAuthToken
        onEditSuccess={(data) => console.log('Updated:', data)}
      />
    </>
  );
}