WoodyLabBuild with UIMS

Documentazione · src/react

Il render

Ottantaquattro file: l’area più grande del pacchetto. Prende i descrittori e li disegna, e non sa da dove viene il dato.

Il renderer riceve descrittori, non blocchi

Quello che arriva a LayoutRenderer non è un blocco: è ciò che un resolver ha fatto di un blocco. Il nome della prop parla di layout, il tipo dice quale delle due cose è — e il tipo è quello che conta.

La distinzione conta perché il renderer non deve prendere decisioni: non cerca componenti, non risolve viewMode, non legge il database. Riceve Component, ui, slots, data e li mette insieme. Tutto il pensiero è già avvenuto sul server.

react/LayoutRenderer.tsx

percorre i descrittori e li disegna

Come si usa, dal consumer

const resolved = await Promise.all(layout.map((b) => UIMS.resolve(b)))
return <LayoutRenderer resolvedLayout={resolved} />

Cosa fa con un descrittore

if (block.Component) {
  const { Component, slots, ...props } = block
  return <Component slots={slots} {...props} />
}
react/index.ts

la porta pubblica: componenti, provider, stato, eventi, tipi

react/type.ts

UIMSComponentProps, più i tipi degli slot ri-esportati dal motore

Il registro dei componenti

uimsComponents è una mappa da nome a componente: { Box, Card, Section, … }. Un viewMode nomina il componente per stringa, e la stringa viene cercata qui.

È il punto di estensione più diretto del pacchetto: il consumer costruisce la propria mappa come { ...uimsComponents, ...suoi } e da quel momento un viewMode può nominare un componente che il pacchetto non conosce. Non serve nessuna registrazione, nessun decoratore: è un oggetto.

È anche il motivo per cui la minificazione del dist/ non tocca mai i nomi delle proprietà. Rinominare le chiavi di questa mappa significherebbe che nessun viewMode risolve più — e in repo non se ne accorgerebbe nessuno, perché in repo si consuma dai sorgenti.

react/uimsComponents.ts

la mappa nome → componente

Il primitivo comune

Quasi tutti i componenti disegnano attraverso lo stesso primitivo: prende il tag dal viewMode, le classi già risolte, gli attributi, e ci mette dentro gli slot. È il posto in cui un comportamento trasversale si aggiunge una volta per tutti.

Se il descrittore porta uno stato dichiarato, il primitivo delega al nodo reattivo — quello che sa sottoscrivere le chiavi e applicare le classi delle animazioni. Se non lo porta, non succede niente: nessun costo per i blocchi che con lo stato non c’entrano.

react/components/UIMSPrimitive.tsx

tag, classi, attributi, slot: il disegno comune

react/components/UIMSReactive.tsx

il nodo reattivo: sottoscrive le sue chiavi, applica trigger e conseguenze

react/components/UIMSWrapperRoot.tsx

la radice per i componenti che hanno bisogno di un wrapper client

react/components/uiStateTypes.ts

i tipi dello stato dichiarato su un’istanza

Il confine server/client

Quarantaquattro file del pacchetto portano 'use client'. Non è una scelta di comodo: sono i punti in cui serve davvero il browser — un observer, un listener, uno stato locale. Tutto il resto resta componente server, e non attraversa la rete.

Il modo in cui un componente interattivo è fatto è ricorrente: una parte server che riceve il descrittore e una parte client (…ClientWrapper) che porta lo stato. La divisione permette di tenere fuori dal bundle tutto ciò che non è interazione.

La direttiva è anche l’unica cosa che la minificazione del dist/ deve preservare a ogni costo: terser la toglie di default, e senza di lei un componente client verrebbe renderizzato sul server. Lo script di build fallisce se ne sparisce una.

Le tre sottocartelle

Il resto dell’area è diviso per cosa fa: state tiene lo store e i suoi hook, events il bus, triggers e actions i due registri aperti che collegano una causa a una conseguenza. Ognuna ha la sua pagina.

react/components/

sessanta file: i componenti, i wrapper client, i form, l’admin

react/state/

nove file: lo store, le slice, i reducer, gli effetti di pagina

react/events/

cinque file: il kernel, gli handler, i token, l’indirizzamento

react/triggers/

tre file: il registro delle cause

react/actions/

due file: il registro delle conseguenze

react/utils/motion.ts

rispetta prefers-reduced-motion in un punto solo