Gemelo React de innoboxrr-form-elements. Los mismos 37
componentes, con los mismos nombres: los controles de formulario y las piezas de
escritorio (DialogComponent, DrawerComponent, MenuComponent,
CommandPaletteComponent, ToastRegionComponent, ConfirmHostComponent y
SkeletonComponent).
Los nombres coinciden a propósito: larapack-generator emite el mismo
form_component del laraimport.json para Vue y para React, así que un nombre
distinto rompería esa simetría. Hay un test de paridad en cada repositorio que
falla si un paquete exporta algo que el otro no.
npm i innoboxrr-react-form-elements
Los estilos van una vez por aplicación:
import 'innoboxrr-react-form-elements/src/css/form-elements.css'
import '@yaireo/tagify/dist/tagify.css' // si usas TagsInputComponent
import 'react-phone-number-input/style.css' // si usas CountrySelectInputComponentimport { TextInputComponent, SelectInputComponent } from 'innoboxrr-react-form-elements'
<TextInputComponent
type="text"
name="title"
label="Título"
validators="required"
value={form.title}
onChange={(value) => setField('title', value)} />
<SelectInputComponent name="status" label="Estado" value={form.status} onChange={...}>
<option value="">Selecciona</option>
<option value="draft">Borrador</option>
</SelectInputComponent>| Vue | React |
|---|---|
v-model |
value + onChange(valor) |
:custom-class |
customClass |
min_length / max_length |
minLength / maxLength (se aceptan también los de guion bajo) |
slot por defecto de SelectInputComponent |
children |
v-format |
prop maskFormat |
@change de CountrySelectInputComponent |
onCountryChange({ phone, country, callingCode, national, isValid }) |
@submit / @selected de ModelSearchInputComponent |
onSubmit / onSelected |
install(app) |
no existe: React no tiene plugin de aplicación |
onChange recibe el valor, no el evento, igual que update:modelValue
recibe el valor y no el $event. Para el evento del DOM están onInput,
onFocus, onBlur, onEnter y onPaste.
Todos los controles funcionan también sin value: se gobiernan solos. Eso
permite montarlos en una prueba o en un formulario no controlado sin escribir
estado alrededor.
Sobre <dialog>, el atributo popover y Floating UI, con el mismo
comportamiento que la rama Vue. Lo que cambia es la forma de pasar las cosas:
| Vue | React |
|---|---|
v-model:open |
open + onOpenChange(abierto) |
slot footer / header con { close } |
prop footer / header: un nodo o una función ({ close }) => … |
slot trigger de MenuComponent |
renderTrigger({ toggle, open, loading, triggerProps }) |
@select |
onSelect(item) |
:save de ClickToEditComponent |
onSave(valor) |
import { DrawerComponent, ToastRegionComponent, ConfirmHostComponent } from 'innoboxrr-react-form-elements'
import { notifySuccess } from 'innoboxrr-form-core'
<DrawerComponent open={abierto} onOpenChange={setAbierto} title="Nuevo producto"
footer={({ close }) => <button type="button" onClick={close}>Cancelar</button>}>
<CreateForm onSubmit={(producto) => { notifySuccess('Producto creado'); setAbierto(false) }} />
</DrawerComponent>
// una vez, en la raíz
<ToastRegionComponent />
<ConfirmHostComponent />React no escribe el atributo autofocus en el DOM, así que lo que tiene que
recibir el foco al abrir un diálogo se marca con data-autofocus.
Cada componente envuelve el equivalente React de la librería que envuelve su gemelo Vue. Donde la librería es agnóstica, es literalmente la misma:
| Componente | Vue | React |
|---|---|---|
TextInputComponent (máscara) |
innoboxrr-maskjs/vue |
innoboxrr-maskjs — el mismo motor |
TagsInputComponent |
@yaireo/tagify |
@yaireo/tagify/react — la misma librería |
EditorInputComponent |
@tinymce/tinymce-vue |
@tinymce/tinymce-react — el envoltorio oficial hermano |
CodeMirrorComponent |
vue-codemirror |
@uiw/react-codemirror — el mismo CodeMirror 6 |
SelectSearchInputComponent |
vue-select |
react-select |
CountrySelectInputComponent |
vue-tel-input |
react-phone-number-input — el mismo libphonenumber-js |
DynamicGroupInputComponent |
vuedraggable |
@dnd-kit/sortable |
ColorPickerInputComponent |
lightvue (opcional) |
react-colorful |
Tres notas sobre esas elecciones:
@dnd-kites el sucesor dereact-beautiful-dnd, que está archivado. A diferencia de SortableJS trae reordenación por teclado, así que el asa de arrastre es un<button>alcanzable con tabulador. Un formulario que solo se reordena con el ratón no es accesible.react-phone-number-inputvalida conlibphonenumber-js, igual quevue-tel-input. Sabe cuántos dígitos tiene un número de cada país.react-colorfulpesa 2,8 kB y no tiene dependencias. La versión Vue cae a<input type="color">cuandolightvueno está, que abre el diálogo del sistema operativo y no se puede estilar ni probar.
<TextInputComponent
type="text"
name="phone"
label="Teléfono"
maskFormat={{ mask: '(___) ___-____', format: '(***) ***-****' }}
value={phone}
onChange={setPhone} />En format: * es un dígito, a una letra, A letra o dígito. Todo lo demás
es un literal. Ver innoboxrr-maskjs.
CodeMirrorComponent carga el lenguaje bajo demanda. language (javascript
por defecto, json, html o css) llega con import(), así que una
aplicación solo descarga el que usa: un editor de JSON ya no se lleva html, css
y javascript. Mientras llega, el editor funciona como texto plano. Un lenguaje
fuera de esa lista lo deja en texto plano.
theme es dark (por defecto) o light. one-dark va siempre en el bundle
porque lo importa @uiw/react-codemirror, no este paquete.
MultiCheckboxInputComponentderiva la selección del valor. La versión Vue la recalculaba condocument.querySelectorAll, así que dos grupos con el mismoidse pisaban.SelectSearchInputComponent,ColorPickerInputComponent,CodeMirrorComponentyEditorInputComponentpublican su valor en un<input type="hidden">con elnamey eldata-validators. Sus librerías no exponen un input donde ponerlos, y el validador del proyecto los lee del DOM.- Todos aceptan
id. Sin eso, pasar unidcambiaba el del control pero no elforde la etiqueta, y la etiqueta quedaba apuntando a la nada.
npm test
Documentación completa del ecosistema, en español y en inglés / Full ecosystem documentation, in Spanish and English: https://innoboxrr.github.io/docs/interfaz/form-elements