Campos de formulario v1¶
Declara campos con FormBuilder / FieldBuilder; el framework emite JSON Schema + UI schema y el widget form los renderiza en @cortex/panel-shadcn.
Pipeline¶
Emisión centralizada: framework/cortex_framework/forms/emit.py.
Tipos de campo¶
| Método | Tipo SPI | Uso |
|---|---|---|
.text() | string | Texto corto |
.textarea() | textarea | Texto largo |
.email() | email | Correo |
.password() | password | Contraseña |
.integer() | integer | Entero |
.number() | number | Decimal |
.money() | money | Monto (currency, default COP) |
.boolean() | boolean | Checkbox |
.toggle() | toggle | Interruptor |
.date() | date | Fecha |
.datetime() | datetime | Fecha y hora |
.time() | time | Hora |
.hidden() | hidden | Valor oculto (default) |
.select() | select | Lista cerrada con labels |
.radio() | radio | Opción única |
.checkbox_list() | checkbox_list | Múltiple → string[] |
.tags() | tags | Chips libres |
.color() | color | Color hex |
.file() | file | Archivo → URL (upload S3) |
.image() | image | Imagen con preview |
.relationship() | relationship | BelongsTo async (path, label_key, value_key) |
.repeater() | repeater | Array de sub-objetos |
.key_value() | key_value | Objeto clave-valor dinámico |
.rich_text() | rich_text | HTML (Tiptap) |
.markdown() | markdown | Markdown con preview |
.computed() | computed | Solo lectura, derivado en cliente |
Parámetros comunes: required=True, placeholder, helper_text, visible_when={"field": "x", "equals": value}.
Layouts¶
f.section("General", lambda b: b.text("name", "Nombre"))
.section("Avanzado", lambda b: b.text("code", "Código"), collapsed=True)
.columns(2, lambda b: b.text("a", "A").text("b", "B"))
.tabs({"General": lambda b: b.text("name", "Nombre"), "Extra": lambda b: b.text("sku", "SKU")})
Upload S3¶
Configura en el framework:
CORTEX_UPLOAD_BUCKETCORTEX_UPLOAD_REGION(defaultus-east-1)CORTEX_UPLOAD_PREFIX(defaultcortex)CORTEX_UPLOAD_PUBLIC_BASE_URL(URL pública opcional)
Endpoint: POST /api/v1/uploads → { "url", "key" }.
Ejemplo¶
.form(
lambda f: (
f.text("name", "Nombre", required=True)
.money("amount", "Monto")
.select("status", "Estado", options=(("open", "Abierto"), ("closed", "Cerrado")))
.repeater("lines", "Líneas", lambda b: b.text("desc", "Descripción").money("price", "Precio"))
)
)
Demo¶
Plugin reference registra form-demo con todos los tipos: GET /api/v1/forms/form-demo.