Documentazione · src/react/events · triggers · actions
Gli eventi
Un kernel solo, e due registri aperti: dieci cause, quattro conseguenze. Chi fa scattare qualcosa non sa cosa succederà dopo — ed è quello che li rende sostituibili.
Il kernel unificato
Tutti i comportamenti lato utente passano da un kernel solo, montato sul provider. La direzione uscente — un componente FA qualcosa — e quella entrante — un componente REAGISCE — vivono sullo stesso bus.
L’API è cinque cose: `dispatch` (un comando uno-a-uno che ritorna), `emit` (una notifica uno-a-molti), `subscribe` (ascolta), `use` (middleware), `registerEffect`/`runEffect` (implementazioni invocabili per nome).
Il middleware è la cucitura del dev: intercetta un evento e lo trasforma restituendolo, lo annulla restituendo `null`, o lo lascia passare. In sviluppo il kernel è raggiungibile su `window.__uimsKernel`.
events/UIMSEvents.tsx— il kernel: dispatch, emit, subscribe, middleware, effetti
Cause e conseguenze, come registri iniettabili
Un trigger è una CAUSA: sa come mettersi in ascolto di qualcosa e chiamare `fire`. Non sa cosa succederà dopo, e questa ignoranza è il punto: `fire(payload?)` non sa se seguirà un’animazione, un evento o una navigazione.
Un’azione è una CONSEGUENZA: riceve la configurazione e la esegue. Le quattro che il pacchetto porta sono `animate`, `emit`, `dispatch` e `run`. Prima erano una catena di `if` con `animate` privilegiato fra gli altri, perché guidava lo stato React del componente — il che costringeva a scegliere un solo motore di reattività escludendo gli altri.
Entrambi i registri sono oggetti: si estendono con `{ ...uimsTriggers, ...propri }` — e chi arriva dopo vince sui conflitti — e si POTANO, perché quello che arriva al provider È l’insieme attivo. Un progetto che non usa i trigger di viewport li può togliere.
Le chiavi sono quelle che il dato già nomina, quindi rinominarne una romperebbe contenuto già inserito. È il motivo per cui i nomi vecchi sopravvivono anche quando non sono i più belli.
triggers/types.ts— il contratto di un trigger: cosa riceve, cosa deve faretriggers/uimsTriggers.ts— i dieci trigger del pacchetto: viewport (entra, esce, progresso), click, change, submit, hover, mount, cambio di stato, evento sul bustriggers/viewportObserver.ts— un observer per nodo e opzioni, non uno per trigger: un blocco con tutti e tre ne pagherebbe treactions/types.ts— il contratto di un’azioneactions/uimsActions.ts— le quattro conseguenze: `animate`, `emit`, `dispatch`, `run`
Un evento ha un indirizzo
Il bus consegna per tipo, ma anche per destinatario. Tre nodi identici nella stessa pagina che ascoltano lo stesso tipo di evento non si svegliano tutti quando l’evento riguarda uno solo: chi emette dice a chi manda, chi ascolta dice cosa sente, e le due stringhe si confrontano.
La normalizzazione sta in un file solo, perché lo scope si scrive da due lati e finché la normalizzazione stava solo dal lato di chi emette le due stringhe non si incontravano mai. `global` significa senza indirizzo, `self` significa questo nodo, `#<id>` un nodo preciso.
Esiste un carattere jolly, `*`, che ascolta tutto. È di kernel e non viene offerto in admin: serve a chi fa da ponte — il provider dello stato, il wrapper dello swiper — non a chi configura un comportamento.
events/scope.ts— `resolveScope` e `deliversTo`: la regola di indirizzamento in un punto solo
Il ponte dispatch → emit
Dopo che un `dispatch` ha eseguito il suo handler, il kernel emette anche lo stesso messaggio agli iscritti. Il risultato è che una reazione configurata su `on:event(ui:close)` reagisce al comando `ui:close` senza nessuna configurazione in più: chi produce e chi consuma si saldano da soli.
L’esempio che si vede su questa pagina: il pulsante flottante in basso e la prima voce dell’indice emettono lo stesso `ui:scrollToTop`, e un handler condiviso riporta in cima. Nessuno dei due sa dell’altro.
Il payload e i suoi token
Ogni messaggio porta un payload opaco: il kernel non lo interpreta. I suoi valori-stringa però possono contenere token `{{ namespace.percorso }}` risolti al momento in cui l’evento parte, contro un contesto vivo — `{{event.*}}`, `{{query.*}}`, `{{node.*}}`, `{{now}}`.
Non c’è uno schema che dichiari da dove viene un valore: sta scritto nel valore stesso. Un token intero restituisce il valore vero, preservandone il tipo; un token dentro una frase produce una stringa. Senza token il payload passa intatto.
events/resolvePayload.ts— risolve i token dentro un payloadevents/resolveTokens.ts— il motore di interpolazione, uno per tutti i namespace
Gli handler che il pacchetto porta
Il pacchetto porta handler veri, non segnaposto, e il criterio di cosa merita di stare lì è netto: ci sta quello che lo STORE NON PUÒ FARE. Scorrere, mettere a fuoco, copiare, stampare sono effetti sul BROWSER — nessuna quantità di stato li produce.
Tutto ciò che si può esprimere come «una chiave cambia e qualcosa si ri-stila» non è un handler: è un reducer più un binding, e va scritto lì. Il criterio evita la deriva in cui il bus diventa il posto dove finisce ogni logica.
events/uimsEventHandlers.ts— gli handler del pacchetto: effetti sul browser, non sullo stato