@desynth/web-components-react
v14.9.26-alpha.5
Published
React proxy for @desynth/web-components
Readme
@desynth/web-components-react
Wrappers React tipados para los Custom Elements de @desynth/web-components, generados por @stencil/react-output-target.
Requisitos e instalación
El paquete declara react >= 19.2.0 y react-dom >= 19.2.0 como peer dependencies. Los wrappers importan las clases y tipos del paquete core, por lo que debe instalarse también:
npm install @desynth/web-components-react @desynth/web-components react react-domConviene mantener @desynth/web-components-react y @desynth/web-components en versiones compatibles, especialmente en versiones alpha.
Uso
Todos los wrappers se exportan desde la entrada principal:
import {
DesynthButton,
DesynthDataTable,
} from '@desynth/web-components-react';
export function Example() {
return (
<>
<DesynthButton buttonText="Guardar" variant="solid" />
<DesynthDataTable
columns={JSON.stringify([{ key: 'name', label: 'Nombre' }])}
rows={JSON.stringify([{ id: '1', name: 'Ada' }])}
emptyText="Sin resultados"
/>
</>
);
}Las exportaciones usan nombres PascalCase derivados de las clases generadas: DesynthButton, DesynthTextInput, HorizontalCards y HtmlEditor, entre otras.
Registro de Custom Elements
No llames a defineCustomElements() para usar estos wrappers. Cada wrapper generado recibe su propia función defineCustomElement desde @desynth/web-components/dist/<tag>.js y registra ese elemento al cargarse.
El loader global solo es necesario si, además de los wrappers React, la aplicación renderiza etiquetas Custom Element directamente y quiere registrarlas en bloque:
import { defineCustomElements } from '@desynth/web-components/loader';
defineCustomElements();No mezcles ambos mecanismos por rutina: los registros individuales ya comprueban si el elemento existe y el loader global añade trabajo innecesario cuando toda la UI usa wrappers.
Propiedades y nombres
En JSX se usan los nombres de propiedad de Stencil en camelCase, no los atributos HTML en kebab-case:
| Web Component | React |
| --- | --- |
| button-text | buttonText |
| empty-text | emptyText |
| preview-url | previewUrl |
| button-id | buttonId |
Las propiedades booleanas reciben booleanos reales:
<DesynthButton disabled={isSaving} full buttonText="Guardar" />Los tipos de cada wrapper proceden del paquete core y están incluidos en dist/components.d.ts.
Datos JSON
Varias propiedades complejas del core están declaradas como string y el componente ejecuta JSON.parse internamente. En esos casos hay que serializar arrays y objetos también desde React; pasar el objeto directamente contradice la API generada.
import { DesynthDataTable } from '@desynth/web-components-react';
type Row = {
id: string;
name: string;
status: 'active' | 'paused';
};
const columns = [
{ key: 'name', label: 'Nombre' },
{ key: 'status', label: 'Estado' },
];
const rows: Row[] = [
{ id: 'usr-1', name: 'Ada', status: 'active' },
];
export function UsersTable() {
return (
<DesynthDataTable
columns={JSON.stringify(columns)}
rows={JSON.stringify(rows)}
badges={JSON.stringify({
status: { active: '#18864b', paused: '#8a6400' },
})}
actions={JSON.stringify([
{ key: 'open', label: 'Abrir' },
])}
onHandleAction={(event) => {
const { rowId, action } = event.detail;
console.log(rowId, action);
}}
/>
);
}No todas las propiedades con datos son JSON. Revisa el tipo exportado o la referencia del componente core antes de serializar.
Eventos
Los eventos de Stencil se convierten en props React con prefijo on y PascalCase:
| Evento DOM | Prop React |
| --- | --- |
| handleClick | onHandleClick |
| handleChange | onHandleChange |
| handleAction | onHandleAction |
| htmlChanged | onHtmlChanged |
El callback recibe un CustomEvent tipado; la carga útil está en event.detail.
import { DesynthTextInput } from '@desynth/web-components-react';
export function Search() {
return (
<DesynthTextInput
inputId="search"
inputName="Buscar"
onHandleInput={(event) => {
console.log(event.detail.value);
}}
/>
);
}Usa el nombre exacto expuesto por el wrapper. No lo sustituyas por onClick o onChange salvo que la API tipada del componente lo declare.
Slots y children
El contenido hijo se proyecta al slot por defecto. Para un slot con nombre, añade slot al nodo hijo:
import {
DesynthBookCard,
DesynthButton,
} from '@desynth/web-components-react';
export function Book() {
return (
<DesynthBookCard
title="Diseño de sistemas"
chapters={JSON.stringify(['Introducción', 'Arquitectura'])}
>
<div slot="actions">
<DesynthButton buttonText="Leer" size="xs" />
</div>
</DesynthBookCard>
);
}Los nombres de slot disponibles dependen del componente core; no existe una lista universal.
SSR y React Server Components
El archivo generado comienza con 'use client'. Los wrappers registran Custom Elements y están destinados al navegador:
- impórtalos y renderízalos desde componentes cliente;
- en Next.js App Router, coloca el uso detrás de un archivo con
'use client'; - no dependas de que el Shadow DOM esté renderizado en el HTML del servidor;
- si el bundler evalúa módulos DOM durante SSR, carga el componente cliente de forma dinámica con SSR desactivado.
Ejemplo para Next.js:
'use client';
import { DesynthButton } from '@desynth/web-components-react';
export function SaveButton() {
return <DesynthButton buttonText="Guardar" />;
}El paquete core genera una salida dist/hydrate, pero este paquete React no configura por sí mismo una integración SSR o de hidratación para el framework.
Tokens
Carga el tema CSS una sola vez desde la hoja global de la aplicación:
@import '@desynth/style-tokens/dist/assets/css/variables-all.css';El CSS de tokens llega como dependencia transitiva del core, pero su importación es explícita. Consulta el README de @desynth/web-components para las variantes de tema publicadas.
Desarrollo local y sincronización
src/components.ts es generado: no debe editarse a mano. El flujo local correcto, desde la raíz del monorepo, es:
npm run build --workspace=@desynth/web-components
npm run build --workspace=@desynth/web-components-reactEl build de Stencil ejecuta el React output target y vuelve a generar packages/components-react/src; después, el script del wrapper ejecuta TypeScript y sincroniza dist/. Si solo se compila este paquete sin regenerar primero el core, los proxies pueden quedar desalineados con el catálogo actual.
El paquete React publica únicamente dist/ y su script disponible es:
npm run build # equivalente a: npm run tscNo hay script de tests definido en este paquete.
Licencia
MPL-2.0 según el manifiesto del paquete.
