WoodyLab
WoodyLabBuild with UIMS

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 fare
  • triggers/uimsTriggers.ts — i dieci trigger del pacchetto: viewport (entra, esce, progresso), click, change, submit, hover, mount, cambio di stato, evento sul bus
  • triggers/viewportObserver.ts — un observer per nodo e opzioni, non uno per trigger: un blocco con tutti e tre ne pagherebbe tre
  • actions/types.ts — il contratto di un’azione
  • actions/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 payload
  • events/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
Login