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.
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} />
}la porta pubblica: componenti, provider, stato, eventi, tipi
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.
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.
tag, classi, attributi, slot: il disegno comune
il nodo reattivo: sottoscrive le sue chiavi, applica trigger e conseguenze
la radice per i componenti che hanno bisogno di un wrapper client
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.
sessanta file: i componenti, i wrapper client, i form, l’admin
nove file: lo store, le slice, i reducer, gli effetti di pagina
cinque file: il kernel, gli handler, i token, l’indirizzamento
tre file: il registro delle cause
due file: il registro delle conseguenze
rispetta prefers-reduced-motion in un punto solo
Continua
Altro in «Il render · src/react»
Lo statoGli eventiTutte le diciassette pagineindice