2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
3> Use this file to discover all available pages before exploring further.3> Use this file to discover all available pages before exploring further.
4 4
5# Disegnare nell'interfaccia con un mod5# Disegna nell'interfaccia con un mod
6 6
7> Disegnare riquadri, una banda sopra il prompt, pulsanti e campi di testo da un mod di Claude Code, gestire pressioni e input, e mantenere lo stato tra i ridisegni e le sessioni.7> Disegna riquadri, una fascia sopra il prompt, pulsanti e campi di testo da un mod di Claude Code, gestisci pressioni e input e mantieni lo stato tra i ridisegni e le sessioni.
8 8
9Un mod può disegnare la propria interfaccia in Claude Code e modificare parti dell'interfaccia che Claude Code disegna già. Ogni luogo in cui un mod può disegnare è chiamato [sito di rendering](/docs/it/plugins/mods/reference#render-sites), come un riquadro, la banda sopra il prompt, o lo spinner. Claude Code genera l'evento [`ui.render`](/docs/it/plugins/mods/reference#interface) ogni volta che sta per disegnare un sito di rendering, e il tuo hook per quell'evento restituisce cosa disegnare lì.9Un mod può disegnare la propria interfaccia in Claude Code e modificare parti dell'interfaccia che Claude Code già disegna. Ogni posizione in cui un mod può disegnare è chiamata [punto di rendering](/docs/it/plugins/mods/reference#render-sites), ad esempio un riquadro, la fascia sopra il prompt o lo spinner. Claude Code attiva l'evento [`ui.render`](/docs/it/plugins/mods/reference#interface) ogni volta che sta per disegnare un punto di rendering, e il tuo hook per quell'evento restituisce cosa disegnare lì.
10 10
11Questa mappa mostra dove un mod può disegnare in una sessione terminale:11Questa mappa mostra dove un mod può disegnare in una sessione del terminale:
12 12
13<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5fda26b6609c62b68c6f9e528c1590ea" className="dark:hidden" alt="Mappa di una sessione terminale di Claude Code. Un mod può aggiungere un riquadro come barra laterale sulla destra, un toast in alto a destra della trascrizione, una riga di log nella trascrizione, una banda sopra il prompt, e una riga di stato sotto il prompt. Un mod può ridisegnare messaggi, righe di chiamate di strumenti, e lo spinner. Il prompt è proprio di Claude Code." width="600" height="336" data-path="images/mods-screen-map.svg" />13<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5fda26b6609c62b68c6f9e528c1590ea" className="dark:hidden" alt="Mappa di una sessione del terminale di Claude Code. Un mod può aggiungere un riquadro come barra laterale a destra, un toast in alto a destra della trascrizione, una riga di log nella trascrizione, una fascia sopra il prompt e una riga di stato sotto il prompt. Un mod può ridisegnare i messaggi, le righe delle chiamate agli strumenti e lo spinner. Il prompt appartiene a Claude Code." width="600" height="336" data-path="images/mods-screen-map.svg" />
14 14
15<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map-dark.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5b4161581a1bd2c0450b0c8b57bc1225" className="hidden dark:block" alt="Mappa di una sessione terminale di Claude Code. Un mod può aggiungere un riquadro come barra laterale sulla destra, un toast in alto a destra della trascrizione, una riga di log nella trascrizione, una banda sopra il prompt, e una riga di stato sotto il prompt. Un mod può ridisegnare messaggi, righe di chiamate di strumenti, e lo spinner. Il prompt è proprio di Claude Code." width="600" height="336" data-path="images/mods-screen-map-dark.svg" />15<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map-dark.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5b4161581a1bd2c0450b0c8b57bc1225" className="hidden dark:block" alt="Mappa di una sessione del terminale di Claude Code. Un mod può aggiungere un riquadro come barra laterale a destra, un toast in alto a destra della trascrizione, una riga di log nella trascrizione, una fascia sopra il prompt e una riga di stato sotto il prompt. Un mod può ridisegnare i messaggi, le righe delle chiamate agli strumenti e lo spinner. Il prompt appartiene a Claude Code." width="600" height="336" data-path="images/mods-screen-map-dark.svg" />
16 16
17In un terminale più stretto, il riquadro si trova sopra il prompt invece che accanto alla trascrizione.17In un terminale più stretto, il riquadro si trova sopra il prompt anziché accanto alla trascrizione.
18 18
19Costruisci il tuo [primo mod](/docs/it/plugins/mods/create) prima di iniziare qui. Inizia con l'esempio pratico, che costruisce un riquadro con due schede e un contatore, quindi leggi la sezione per ogni parte che desideri modificare.19Crea il tuo [primo mod](/docs/it/plugins/mods/create) prima di iniziare da qui. Comincia con l'esempio pratico, che crea un riquadro con due schede e un contatore, poi leggi la sezione relativa a ciascun elemento che vuoi modificare.
20 20
21<Note>21<Note>
22 Per cercare una proprietà o un limite, consulta il [riferimento](/docs/it/plugins/mods/reference#render-sites).22 Per consultare una singola prop o un limite, vedi il [riferimento](/docs/it/plugins/mods/reference#render-sites).
23</Note>23</Note>
24 24
25<h2 id="build-a-pane-with-tabs">25<h2 id="build-a-pane-with-tabs">
26 Costruire un riquadro con schede26 Crea un pannello con schede
27</h2>27</h2>
28 28
29In questa sezione costruisci un mod che aggiunge un comando `/hello-tabs` e il comando apre un riquadro. Un riquadro è una barra laterale accanto alla trascrizione in un terminale fullscreen ampio, o una regione incorniciata sopra il prompt altrimenti. Questo riquadro mostra due schede, e la seconda scheda ha un pulsante che aggiunge uno a un contatore. Il conteggio è ancora lì dopo aver riavviato Claude Code.29In questa sezione crei un mod che aggiunge un comando `/hello-tabs`, e il comando apre un pannello. Un pannello è una barra laterale accanto alla trascrizione in un terminale ampio a schermo intero, oppure un'area incorniciata sopra il prompt negli altri casi. Questo pannello mostra due schede, e la seconda scheda ha un pulsante che aggiunge uno a un contatore. Il conteggio è ancora lì dopo che riavvii Claude Code.
30 30
31Il mod finito assomiglia a questo. La registrazione apre il riquadro, passa alla seconda scheda, preme il pulsante alcune volte e ritorna alla prima scheda:31Il mod finito ha questo aspetto. La registrazione apre il pannello, passa alla seconda scheda, preme il pulsante alcune volte e torna alla prima scheda:
32 32
33<Frame>33<Frame>
34 <video autoPlay muted loop playsInline controls className="w-full dark:hidden" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-hello-tabs-light.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=49d520094d87b5b44bfe50fa49677f06" aria-label="Il comando /hello-tabs viene digitato al prompt di Claude Code e un riquadro incorniciato si apre sopra di esso, con '1: One' e '2: Two' nella parte superiore e il testo 'This is the first tab.' La seconda scheda mostra un pulsante 'Add one' accanto a 'Count: 1', e il conteggio sale a 3. Il riquadro ritorna quindi alla prima scheda." data-path="images/mods-hello-tabs-light.mp4" />34 <video autoPlay muted loop playsInline controls className="w-full dark:hidden" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-hello-tabs-light.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=49d520094d87b5b44bfe50fa49677f06" aria-label="Il comando /hello-tabs viene digitato nel prompt di Claude Code e sopra di esso si apre un pannello incorniciato, con '1: One' e '2: Two' nella parte superiore e il testo 'This is the first tab.' La seconda scheda mostra un pulsante 'Add one' accanto a 'Count: 1', e il conteggio sale a 3. Il pannello torna poi alla prima scheda." data-path="images/mods-hello-tabs-light.mp4" />
35 35
36 <video autoPlay muted loop playsInline controls className="w-full hidden dark:block" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-hello-tabs-dark.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=ff7a14d713d6e5d3b0000efa8522ea4b" aria-label="Il comando /hello-tabs viene digitato al prompt di Claude Code e un riquadro incorniciato si apre sopra di esso, con '1: One' e '2: Two' nella parte superiore e il testo 'This is the first tab.' La seconda scheda mostra un pulsante 'Add one' accanto a 'Count: 1', e il conteggio sale a 3. Il riquadro ritorna quindi alla prima scheda." data-path="images/mods-hello-tabs-dark.mp4" />36 <video autoPlay muted loop playsInline controls className="w-full hidden dark:block" src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-hello-tabs-dark.mp4?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=ff7a14d713d6e5d3b0000efa8522ea4b" aria-label="Il comando /hello-tabs viene digitato nel prompt di Claude Code e sopra di esso si apre un pannello incorniciato, con '1: One' e '2: Two' nella parte superiore e il testo 'This is the first tab.' La seconda scheda mostra un pulsante 'Add one' accanto a 'Count: 1', e il conteggio sale a 3. Il pannello torna poi alla prima scheda." data-path="images/mods-hello-tabs-dark.mp4" />
37</Frame>37</Frame>
38 38
39Claude Code non ha un elemento schede integrato, quindi le schede sono due pulsanti in una riga. Il mod tiene traccia di quale è attivo e disegna il contenuto di quella scheda sotto la riga.39Le schede sono due pulsanti in fila. Il mod tiene traccia di quale sia attiva e disegna il contenuto di quella scheda sotto la fila.
40 40
41<Steps>41<Steps>
42 <Step title="Creare il plugin">42 <Step title="Crea il plugin">
43 Un mod è un plugin con un manifesto, un `hooks.json` che punta al tuo codice, e il file di codice. [Creare un mod](/docs/it/plugins/mods/create#write-a-mod-yourself) spiega ognuno. Crea una directory denominata `hello-tabs` con directory `.claude-plugin` e `hooks` al suo interno, quindi salva i primi due file.43 Un mod è un plugin con un manifest, un `hooks.json` che punta al tuo codice, e il file di codice. [Crea un mod](/docs/it/plugins/mods/create#write-a-mod-yourself) spiega ciascuno di essi. Crea una directory chiamata `hello-tabs` con le directory `.claude-plugin` e `hooks` al suo interno, poi salva i primi due file.
44 44
45 Salva il manifesto come `hello-tabs/.claude-plugin/plugin.json`:45 Salva il manifest come `hello-tabs/.claude-plugin/plugin.json`:
46 46
47 ```json hello-tabs/.claude-plugin/plugin.json theme={null}47 ```json hello-tabs/.claude-plugin/plugin.json theme={null}
48 {48 {
53 }53 }
54 ```54 ```
55 55
56 Nomina il tuo punto di ingresso in `hello-tabs/hooks/hooks.json`:56 Indica il tuo punto di ingresso in `hello-tabs/hooks/hooks.json`:
57 57
58 ```json hello-tabs/hooks/hooks.json theme={null}58 ```json hello-tabs/hooks/hooks.json theme={null}
59 {59 {
62 ```62 ```
63 </Step>63 </Step>
64 64
65 <Step title="Scrivere il codice">65 <Step title="Scrivi il codice">
66 Il codice fa tre lavori, uno in ogni hook:66 Questo elenco indica cosa fa ciascun hook, nell'ordine in cui compaiono nel codice:
67 67
68 * Aggiunge il comando `/hello-tabs`68 * Aggiunge il comando `/hello-tabs` e carica il conteggio salvato da una sessione precedente
69 * Apre il riquadro quando esegui quel comando69 * Apre il pannello quando esegui quel comando
70 * Disegna il contenuto del riquadro: la riga di schede e il corpo della scheda aperta70 * Disegna il contenuto del pannello: la fila di schede e il corpo della scheda aperta
71 71
72 Due variabili a livello di modulo, `tab` e `count`, mantengono lo stato del riquadro.72 Due variabili a livello di modulo, `tab` e `count`, contengono lo stato del pannello.
73 73
74 Salva questo come `hello-tabs/hooks/register.js`:74 Salva questo come `hello-tabs/hooks/register.js`:
75 75
76 ```javascript hello-tabs/hooks/register.js theme={null}76 ```javascript hello-tabs/hooks/register.js theme={null}
77 // L'id del riquadro, utilizzato per aprire il riquadro e per riconoscerlo durante il disegno77 // The pane's id, used to open the pane and to recognize it when drawing
78 const PANE = 'hello-tabs'78 const PANE = 'hello-tabs'
79 79
80 // Cosa mostra il riquadro: quale scheda è aperta e il valore del contatore80 // What the pane shows: which tab is open, and the counter's value
81 let tab = 'one'81 let tab = 'one'
82 let count = 082 let count = 0
83 83
84 export function register(on) {84 export function register(on) {
85 // Viene eseguito prima del tuo primo prompt, e di nuovo dopo un ricaricamento85 // Runs before your first prompt, and again after a reload
86 on('session.start', async ($, e, next) => {86 on('session.start', async ($, e, next) => {
87 await $.command.register({ name: 'hello-tabs', description: 'Open the hello-tabs pane' })87 await $.command.register({ name: 'hello-tabs', description: 'Open the hello-tabs pane' })
88 // Carica il conteggio che una sessione precedente ha salvato, se ce n'è uno88 // Load the count an earlier session saved, if there is one
89 const saved = await $.store.get('count')89 const saved = await $.store.get('count')
90 if (typeof saved === 'number') count = saved90 if (typeof saved === 'number') count = saved
91 return next(e)91 return next(e)
92 })92 })
93 93
94 // Viene eseguito quando digiti /hello-tabs94 // Runs when you type /hello-tabs
95 on('command.run', { command: 'hello-tabs' }, async ($) => {95 on('command.run', { command: 'hello-tabs' }, async ($) => {
96 // Apri il riquadro, dagli la tastiera, e lascia che Esc lo chiuda96 // Open the pane, give it the keyboard, and let Esc close it
97 await $.ui.open({ id: PANE, title: 'Hello tabs', focus: true, closeOnEscape: true })97 await $.ui.open({ id: PANE, title: 'Hello tabs', focus: true, closeOnEscape: true })
98 // Non stampare nulla nella trascrizione98 // Print nothing in the transcript
99 return {}99 return {}
100 })100 })
101 101
102 // Viene eseguito ogni volta che Claude Code disegna un riquadro102 // Runs each time Claude Code draws a pane
103 on('ui.render', { component: 'Pane' }, async ($, e, next) => {103 on('ui.render', { component: 'Pane' }, async ($, e, next) => {
104 // Lascia in pace i riquadri degli altri mod104 // Leave other mods' panes alone
105 if (e.requestId !== PANE) return next(e)105 if (e.requestId !== PANE) return next(e)
106 // Ottieni gli elementi che questa app può disegnare106 // Get the elements this app can draw
107 const { Box, Text, Button } = $.ui.resolve(e)107 const { Box, Text, Button } = $.ui.resolve(e)
108 // Chiedi a Claude Code di eseguire di nuovo questo hook108 // Ask Claude Code to run this hook again
109 const redraw = () => $.ui.invalidate('ui.render')109 const redraw = () => $.ui.invalidate('ui.render')
110 110
111 // Una scheda: un pulsante che passa a quella scheda quando viene premuto111 // One tab: a button that switches to its tab when pressed
112 const tabButton = (name, label, hotkey) =>112 const tabButton = (name, label, hotkey) =>
113 Button({113 Button({
114 key: 'tab-' + name,114 key: 'tab-' + name,
115 label,115 label,
116 hotkey,116 hotkey,
117 plain: true,117 plain: true,
118 // Attenua la scheda che non è aperta118 // Dim the tab that isn't open
119 dimColor: tab !== name,119 dimColor: tab !== name,
120 onPress: () => {120 onPress: () => {
121 tab = name121 tab = name
123 },123 },
124 })124 })
125 125
126 // Cosa va sotto le schede, a seconda di quale è aperta126 // What goes under the tabs, depending on which one is open
127 const body =127 const body =
128 tab === 'one'128 tab === 'one'
129 ? [Text({ children: ['This is the first tab.'] })]129 ? [Text({ children: ['This is the first tab.'] })]
139 onPress: async () => {139 onPress: async () => {
140 count += 1140 count += 1
141 redraw()141 redraw()
142 // Salva il conteggio in modo che sia lì dopo un riavvio142 // Save the count so it's there after a restart
143 await $.store.set('count', count)143 await $.store.set('count', count)
144 },144 },
145 }),145 }),
148 }),148 }),
149 ]149 ]
150 150
151 // L'intero riquadro: la riga di schede, una riga vuota, quindi il corpo151 // The whole pane: the row of tabs, a blank line, then the body
152 return Box({152 return Box({
153 flexDirection: 'column',153 flexDirection: 'column',
154 children: [154 children: [
165 }165 }
166 ```166 ```
167 167
168 Ogni hook fa anche qualcosa che il codice non rende evidente:168 Ogni hook fa anche qualcosa che il codice non rende esplicito:
169 169
170 * **[`session.start`](/docs/it/plugins/mods/reference#session)** legge anche il conteggio salvato da [`$.store`](#keep-state), un archivio chiave-valore che persiste tra le sessioni.170 * **[`session.start`](/docs/it/plugins/mods/reference#session)** legge anche il conteggio salvato da [`$.store`](#keep-state), un archivio chiave-valore che persiste tra le sessioni.
171 * **[`command.run`](/docs/it/plugins/mods/api#add-a-command)** dice solo a Claude Code che il riquadro esiste. Aprire un riquadro non disegna nulla di per sé: Claude Code quindi genera `ui.render` per chiedere cosa metterci.171 * **[`command.run`](/docs/it/plugins/mods/api#add-a-command)** comunica soltanto a Claude Code che il pannello esiste. Aprire un pannello di per sé non disegna nulla: Claude Code attiva poi `ui.render` per chiedere cosa inserirvi.
172 * **`ui.render`** restituisce l'albero degli elementi, un `Box` che contiene altri box, testo e pulsanti, e lo costruisce di nuovo da `tab` e `count` ogni volta che viene eseguito.172 * **`ui.render`** restituisce l'albero degli elementi, un `Box` che contiene altri box, testo e pulsanti, e lo ricostruisce a partire da `tab` e `count` ogni volta che viene eseguito.
173 173
174 Premere un pulsante esegue il suo callback `onPress`, che cambia una variabile e chiama `redraw`. Claude Code quindi esegue di nuovo l'hook `ui.render`, e l'hook costruisce un nuovo albero dai nuovi valori. Ogni disegno interattivo utilizza quel ciclo di rendering: un callback cambia lo stato, e l'hook esegue il rendering di nuovo dal nuovo stato.174 Premere un pulsante esegue la sua callback `onPress`, che modifica una variabile e chiama `redraw`. Claude Code esegue quindi di nuovo l'hook `ui.render`, e l'hook costruisce un nuovo albero a partire dai nuovi valori. Ogni disegno interattivo usa questo ciclo di rendering: una callback modifica lo stato, e l'hook esegue di nuovo il rendering a partire dal nuovo stato.
175 </Step>175 </Step>
176 176
177 <Step title="Aprire il riquadro">177 <Step title="Apri il pannello">
178 Nella tua shell, avvia Claude Code con `claude --plugin-dir ./hello-tabs`. Al prompt di Claude Code, esegui `/hello-tabs`. Un riquadro si apre con `1: One` e `2: Two` nella parte superiore. Premi `2`, quindi premi `a`, la scorciatoia da tastiera per **Add one**, alcune volte. Il conteggio aumenta.178 Nella tua shell, avvia Claude Code con `claude --plugin-dir ./hello-tabs`. Nel prompt di Claude Code, esegui `/hello-tabs`. Si apre un pannello con `1: One` e `2: Two` nella parte superiore. Premi `2`, poi premi `a`, il tasto di scelta rapida per **Add one**, alcune volte. Il conteggio sale.
179 </Step>179 </Step>
180 180
181 <Step title="Verificare che il conteggio sia stato salvato">181 <Step title="Verifica che il conteggio sia stato salvato">
182 Premi Esc per chiudere il riquadro, quindi esci dalla sessione. Nella tua shell, avvia di nuovo Claude Code con lo stesso comando `claude --plugin-dir ./hello-tabs`, e al prompt di Claude Code esegui `/hello-tabs`. Il conteggio è dove l'hai lasciato.182 Premi Esc per chiudere il pannello, poi esci dalla sessione. Nella tua shell, avvia di nuovo Claude Code con lo stesso comando `claude --plugin-dir ./hello-tabs`, e nel prompt di Claude Code esegui `/hello-tabs`. Il conteggio è dove l'avevi lasciato.
183 183
184 Per cancellare il conteggio, fai in modo che il mod chiami `$.store.delete('count')`. [Mantenere lo stato](#keep-state) spiega quanto tempo dura ogni tipo di valore.184 Per azzerare il conteggio, fai chiamare al mod `$.store.delete('count')`. [Mantieni lo stato](#keep-state) spiega quanto dura ciascun tipo di valore.
185 </Step>185 </Step>
186</Steps>186</Steps>
187 187
188<h2 id="pick-where-to-draw">188<h2 id="pick-where-to-draw">
189 Scegliere dove disegnare189 Scegli dove disegnare
190</h2>190</h2>
191 191
192Un hook `ui.render` viene eseguito per ogni sito di rendering a meno che non lo restringi a quello che desideri disegnare. Per scegliere il sito di rendering, passa un filtro, chiamato [matcher](/docs/it/plugins/mods/events#filter-which-events-a-hook-handles), come secondo argomento a `on`. `{ component: 'Pane' }` esegue l'hook solo per i riquadri. Nell'hook, `e.component` nomina il sito, `e.surface` dice quale app sta disegnando, e `e.props` contiene i dati propri del sito. Per un riquadro, `e.requestId` è l'`id` con cui l'hai aperto.192Un hook `ui.render` viene eseguito per ogni punto di rendering, a meno che tu non lo limiti a quello in cui vuoi disegnare. Per scegliere il punto di rendering, passa un filtro, chiamato [matcher](/docs/it/plugins/mods/events#filter-which-events-a-hook-handles), come secondo argomento di `on`. `{ component: 'Pane' }` esegue l'hook solo per i pannelli. Nell'hook, `e.component` indica il punto, `e.surface` indica quale app sta disegnando e `e.props` contiene i dati propri del punto. Per un pannello, `e.requestId` è l'`id` con cui lo hai aperto.
193 193
194Due siti sono vuoti finché un mod non li riempie, il riquadro e la banda. Seleziona una scheda per vedere cosa è ognuno e come disegnare in esso:194Il pannello e la banda sono vuoti finché un mod non li riempie. Seleziona una scheda per vedere cos'è ciascuno e come disegnarci:
195 195
196<Tabs>196<Tabs>
197 <Tab title="Pane">197 <Tab title="Pannello">
198 Un riquadro è una barra laterale accanto alla trascrizione in un terminale fullscreen ampio, o una regione incorniciata sopra il prompt altrimenti. Con più riquadri aperti, ognuno ottiene una scheda che mostra il suo titolo.198 Un pannello è una barra laterale accanto alla trascrizione in un terminale a schermo intero ampio, oppure, negli altri casi, un'area incorniciata sopra il prompt. Con più pannelli aperti, ognuno ha una scheda che ne mostra il titolo.
199 199
200 Un riquadro appare quando il tuo mod chiama `$.ui.open` con un `id` che scegli, come in `$.ui.open({ id: 'hello-tabs' })`. [Aprire un riquadro al momento giusto](#open-a-pane-at-the-right-time) copre gli altri campi e quando un riquadro aspetta un terminale più ampio.200 Un pannello compare quando il tuo mod chiama `$.ui.open` con un `id` a tua scelta, come in `$.ui.open({ id: 'hello-tabs' })`. [Apri un pannello al momento giusto](#open-a-pane-at-the-right-time) descrive gli altri campi e quando un pannello attende un terminale più ampio.
201 201
202 Per disegnare nel tuo riquadro, filtra su `{ component: 'Pane' }` e verifica che `e.requestId` sia il tuo `id`.202 Per disegnare nel tuo pannello, filtra su `{ component: 'Pane' }` e verifica che `e.requestId` sia il tuo `id`.
203 </Tab>203 </Tab>
204 204
205 <Tab title="Band above the prompt">205 <Tab title="Banda sopra il prompt">
206 La banda è una striscia direttamente sopra l'input del prompt. È sempre lì, e ogni mod la condivide.206 La banda è una striscia direttamente sopra l'input del prompt. È sempre presente e tutti i mod la condividono.
207 207
208 Il tuo hook restituisce un albero per mostrare qualcosa nella banda, o `next(e)` per non mostrare nulla. Un albero sostituisce quello che i mod [dopo il tuo](/docs/it/plugins/mods/events#the-order-mods-run-in) disegnano lì. Per mantenere il loro, metti il risultato di `await next(e)` tra i figli di un [`Box`](#build-a-tree-from-elements) nel tuo albero.208 Il tuo hook restituisce un albero per mostrare qualcosa nella banda, oppure `next(e)` per non mostrare nulla. Un albero sostituisce ciò che i mod [eseguiti dopo il tuo](/docs/it/plugins/mods/events#the-order-mods-run-in) disegnano lì. Per mantenere il loro contenuto, inserisci il risultato di `await next(e)` tra i figli di un [`Box`](#build-a-tree-from-elements) nel tuo albero.
209 209
210 Per disegnare nella banda, filtra su `{ component: 'AbovePrompt' }`.210 Per disegnare nella banda, filtra su `{ component: 'AbovePrompt' }`.
211 </Tab>211 </Tab>
212</Tabs>212</Tabs>
213 213
214<h3 id="change-what-claude-code-already-draws">214<h3 id="change-what-claude-code-already-draws">
215 Modificare quello che Claude Code disegna già215 Modifica ciò che Claude Code già disegna
216</h3>216</h3>
217 217
218Claude Code disegna la maggior parte della sua interfaccia da solo: messaggi, righe di chiamate di strumenti, lo spinner, e altro. Ognuna di quelle parti è un sito di rendering anche, quindi un mod può ridisegnarlo o sostituirlo. Per modificarne uno, filtra il tuo hook `ui.render` sul suo nome da questa tabella:218Claude Code disegna da sé la maggior parte della propria interfaccia: messaggi, righe delle chiamate agli strumenti, lo spinner e altro. Ognuna di queste parti è anch'essa un punto di rendering, quindi un mod può cambiarne lo stile o sostituirla. Per modificarne una, filtra il tuo hook `ui.render` sul suo nome preso da questa tabella:
219 219
220| Sito | Cosa è |220| Punto | Cos'è |
221| :- | :- |221| :- | :- |
222| `UserMessage`, `AssistantMessage` | Un messaggio nella trascrizione |222| `UserMessage`, `AssistantMessage` | Un messaggio nella trascrizione |
223| `ToolUse`, `ToolResult`, `ToolGroup` | La riga di una chiamata di strumento, il suo risultato, e un'esecuzione piegata di chiamate |223| `ToolUse`, `ToolResult`, `ToolGroup` | La riga di una chiamata a uno strumento, il suo risultato e un gruppo compresso di chiamate |
224| `CommandOutput` | La riga che un comando ha stampato |224| `CommandOutput` | La riga stampata da un comando |
225| `AskUserQuestion` | La finestra di dialogo che Claude apre per farti una domanda |225| `AskUserQuestion` | La finestra di dialogo che Claude apre per farti una domanda |
226| `Spinner`, `ToolProgress`, `TurnDuration` | Righe di stato per un turno: la riga che si anima mentre Claude lavora, la riga di progresso dal vivo di uno strumento in esecuzione, e la riga che chiude un turno |226| `Spinner`, `ToolProgress`, `TurnDuration` | Righe di stato di un turno: la riga animata mentre Claude lavora, la riga di avanzamento in tempo reale di uno strumento in esecuzione e la riga che chiude un turno |
227| `InfoNotice`, `SessionMode`, `PromptHint` | Righe di stato sotto il logo, le etichette della modalità nel piè di pagina, e la riga di suggerimento sotto il prompt |227| `InfoNotice`, `SessionMode`, `PromptHint` | Le righe di stato sotto il logo, le etichette della modalità nel piè di pagina e la riga di suggerimento sotto il prompt |
228 228
229In un sito che Claude Code disegna già, il tuo hook ha tre scelte: modificare un dettaglio, sostituire il disegno, o lasciarlo in pace. Seleziona una scheda per vedere ognuno applicato allo spinner. Gli esempi leggono una variabile `calls` che un altro hook conta, come nel [mod del tutorial](/docs/it/plugins/mods/create#write-a-mod-yourself).229In un punto che Claude Code già disegna, il tuo hook può modificare un dettaglio, sostituire il disegno o lasciarlo com'è. Seleziona una scheda per vedere ciascuna opzione applicata allo spinner. Gli esempi leggono una variabile `calls` che un altro hook incrementa, come nel [mod del tutorial](/docs/it/plugins/mods/create#write-a-mod-yourself).
230 230
231<Tabs>231<Tabs>
232 <Tab title="Change a detail">232 <Tab title="Modifica un dettaglio">
233 Per mantenere il disegno di Claude Code e modificare una parte di esso, passa a `next` una copia dell'evento con `props` modificati. Questo hook cambia il testo dopo la parola dello spinner:233 Per mantenere il disegno di Claude Code e modificarne una parte, passa a `next` una copia dell'evento con `props` modificate. Questo hook modifica il testo dopo la parola dello spinner:
234 234
235 ```javascript theme={null}235 ```javascript theme={null}
236 on('ui.render', { component: 'Spinner' }, async ($, e, next) => {236 on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
237 // Mantieni lo spinner di Claude Code, e cambia il testo dopo la sua parola237 // Keep Claude Code's spinner, and change the text after its word
238 return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })238 return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
239 })239 })
240 ```240 ```
246 ```246 ```
247 </Tab>247 </Tab>
248 248
249 <Tab title="Replace the drawing">249 <Tab title="Sostituisci il disegno">
250 Per disegnare qualcosa di tuo al posto del sito, restituisci un albero e non chiamare `next`. Questo hook disegna una riga di testo dove sarebbe lo spinner:250 Per disegnare qualcosa di tuo al posto del punto, restituisci un albero e non chiamare `next`. Questo hook disegna una riga di testo dove si troverebbe lo spinner:
251 251
252 ```javascript theme={null}252 ```javascript theme={null}
253 on('ui.render', { component: 'Spinner' }, async ($, e) => {253 on('ui.render', { component: 'Spinner' }, async ($, e) => {
254 const { Text } = $.ui.resolve(e)254 const { Text } = $.ui.resolve(e)
255 // Nessuna chiamata a next, quindi questa riga viene disegnata al posto dello spinner255 // No call to next, so this line is drawn in the spinner's place
256 return Text({ children: ['Claude has made ' + calls + ' tool calls'] })256 return Text({ children: ['Claude has made ' + calls + ' tool calls'] })
257 })257 })
258 ```258 ```
259 259
260 Mentre Claude lavora, la tua riga si mostra e lo spinner di Claude Code non lo fa:260 Mentre Claude lavora, viene mostrata la tua riga e non lo spinner di Claude Code:
261 261
262 ```text theme={null}262 ```text theme={null}
263 Claude has made 2 tool calls263 Claude has made 2 tool calls
264 ```264 ```
265 </Tab>265 </Tab>
266 266
267 <Tab title="Leave it alone">267 <Tab title="Lascialo com'è">
268 Per lasciare il sito come Claude Code lo disegna, restituisci `next(e)`. Un hook spesso lo fa per alcuni eventi e non per altri. Questo hook lascia lo spinner in pace finché non c'è una chiamata da contare:268 Per lasciare il punto così come lo disegna Claude Code, restituisci `next(e)`. Spesso un hook lo fa per alcuni eventi e non per altri. Questo hook lascia lo spinner com'è finché non c'è una chiamata da contare:
269 269
270 ```javascript theme={null}270 ```javascript theme={null}
271 on('ui.render', { component: 'Spinner' }, async ($, e, next) => {271 on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
272 // Niente da mostrare ancora, quindi passa l'evento invariato272 // Nothing to show yet, so pass the event on unchanged
273 if (calls === 0) return next(e)273 if (calls === 0) return next(e)
274 return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })274 return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
275 })275 })
276 ```276 ```
277 277
278 Prima della prima chiamata di strumento, lo spinner appare come farebbe senza il mod:278 Prima della prima chiamata a uno strumento, lo spinner appare come senza il mod:
279 279
280 ```text theme={null}280 ```text theme={null}
281 Thinking…281 Thinking…
283 </Tab>283 </Tab>
284</Tabs>284</Tabs>
285 285
286Il prompt di autorizzazione non è un sito di rendering, quindi un mod non può modificare quello che mostra. La finestra di dialogo della domanda, `AskUserQuestion`, è uno, quindi un mod può modificare quello.286In questi punti, `next(e)` restituisce un riferimento al disegno di Claude Code, `{ type: 'engine', ref }`, a meno che un mod eseguito dopo il tuo non abbia restituito un proprio albero. Per modificare il contenuto di quel disegno, passa a `next` una copia dell'evento con prop diverse, come fa la scheda **Modifica un dettaglio**. Puoi restituire il riferimento così com'è, oppure inserirlo in un `Box` accanto a elementi tuoi:
287 287
288Il terminale e l'app Desktop non generano tutti gli stessi siti. `Pane`, `AbovePrompt`, `Spinner`, e i siti della trascrizione funzionano in entrambi. Poche altre righe di stato vengono generate solo nel terminale. La [tabella dei siti di rendering](/docs/it/plugins/mods/reference#render-sites) elenca dove viene generato ognuno.288```javascript theme={null}
289on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
290 const { Box, Text } = $.ui.resolve(e)
291 const theirs = await next(e)
292 return Box({ flexDirection: 'column', children: [theirs, Text({ children: ['under the spinner'] })] })
293})
294```
295
296Mentre Claude lavora, lo spinner si anima come prima e `under the spinner` compare sotto di esso.
297
298La richiesta di permesso non è un punto di rendering, quindi un mod non può modificare ciò che mostra. La finestra di dialogo delle domande, `AskUserQuestion`, lo è, quindi un mod può modificarla. Un albero per la finestra di dialogo deve contenere il riferimento esattamente una volta, con i tuoi elementi sopra di esso. In caso contrario, Claude Code disegna la propria finestra di dialogo.
299
300Il terminale e l'app Desktop non generano tutti gli stessi punti. `Pane`, `AbovePrompt`, `Spinner` e i punti della trascrizione funzionano in entrambi. Alcune altre righe di stato vengono generate solo nel terminale. La [tabella dei punti di rendering](/docs/it/plugins/mods/reference#render-sites) indica dove viene generato ciascuno.
289 301
290<h3 id="open-a-pane-at-the-right-time">302<h3 id="open-a-pane-at-the-right-time">
291 Aprire un riquadro al momento giusto303 Apri un pannello al momento giusto
292</h3>304</h3>
293 305
294Un riquadro appare solo quando il tuo mod lo apre. Come e quando lo apri decide se prende il focus della tastiera, quanto spazio chiede, e se appare affatto in un terminale stretto.306Un pannello compare solo quando il tuo mod lo apre. Come e quando lo apri determina se riceve il focus della tastiera, quanto spazio richiede e se viene mostrato o meno in un terminale stretto.
295 307
296Per aprire un riquadro, chiama [`$.ui.open`](/docs/it/plugins/mods/reference#mods-api-methods) con un `id` che scegli. L'`id` è il nome del riquadro: il tuo hook `ui.render` lo controlla, e lo passi di nuovo per chiudere il riquadro.308Per aprire un pannello, chiama [`$.ui.open`](/docs/it/plugins/mods/reference#mods-api-methods) con un `id` a tua scelta. L'`id` è il nome del pannello: il tuo hook `ui.render` lo verifica, e lo passi di nuovo per chiudere il pannello.
297 309
298```javascript theme={null}310```javascript theme={null}
299await $.ui.open({ id: 'hello-tabs', title: 'Hello tabs', focus: true })311await $.ui.open({ id: 'hello-tabs', title: 'Hello tabs', focus: true })
300```312```
301 313
302Per chiudere il riquadro, chiama `$.ui.close` con l'`id` con cui l'hai aperto:314Per chiudere il pannello, chiama `$.ui.close` con l'`id` con cui lo hai aperto:
303 315
304```javascript theme={null}316```javascript theme={null}
305await $.ui.close({ id: 'hello-tabs' })317await $.ui.close({ id: 'hello-tabs' })
306```318```
307 319
308Oltre a `id`, `$.ui.open` accetta questi campi opzionali:320Oltre a `id`, `$.ui.open` accetta questi campi facoltativi:
309 321
310| Campo | Cosa fa |322| Campo | Cosa fa |
311| :- | :- |323| :- | :- |
312| `title` | L'etichetta della scheda del riquadro quando più di un riquadro è aperto |324| `title` | L'etichetta della scheda del pannello quando è aperto più di un pannello |
313| `focus` | Richiede il [focus della tastiera](#know-which-keys-your-mod-can-receive) |325| `focus` | Richiede il [focus della tastiera](#know-which-keys-your-mod-can-receive) |
314| `closeOnEscape` | Fa chiudere il riquadro da Esc |326| `closeOnEscape` | Fa sì che Esc chiuda il pannello |
315| `holdToasts` | Tiene i toast, i piccoli avvisi da [`$.ui.toast`](/docs/it/plugins/mods/api#show-something-without-starting-a-turn), finché il riquadro non si chiude |327| `holdToasts` | Trattiene i toast, i piccoli avvisi di [`$.ui.toast`](/docs/it/plugins/mods/api#show-something-without-starting-a-turn), finché il pannello non si chiude |
316| `rows` | L'altezza da chiedere quando il riquadro si trova sopra il prompt. L'impostazione predefinita è un terzo dello spazio. |328| `rows` | L'altezza da richiedere quando il pannello si trova sopra il prompt. Il valore predefinito è un terzo dello spazio. |
317| `columns` | La larghezza da chiedere quando il riquadro si trova accanto alla trascrizione |329| `columns` | La larghezza da richiedere quando il pannello si trova accanto alla trascrizione |
318 330
319`focus`, `closeOnEscape`, e `holdToasts` sono opzionali e accettano solo `true`. Per lasciare uno fuori, omettilo. Passare `false` genera un errore come `ui.open: focus is true or left out`. Per impostarne uno condizionalmente, aggiungi il campo solo quando la condizione è vera. Questa chiamata chiede il focus della tastiera solo quando `items` non è vuoto:331`focus`, `closeOnEscape` e `holdToasts` sono facoltativi e accettano solo `true`. Per non usarne uno, omettilo. Passare `false` genera un errore come `ui.open: focus is true or left out`. Per impostarne uno in modo condizionale, aggiungi il campo solo quando la condizione è soddisfatta. Questa chiamata richiede il focus della tastiera solo quando `items` non è vuoto:
320 332
321```javascript theme={null}333```javascript theme={null}
322const pane = { id: 'hello-tabs', title: 'Hello tabs' }334const pane = { id: 'hello-tabs', title: 'Hello tabs' }
323await $.ui.open(items.length > 0 ? { ...pane, focus: true } : pane)335await $.ui.open(items.length > 0 ? { ...pane, focus: true } : pane)
324```336```
325 337
326Per lasciare che un comando apra il riquadro mentre Claude sta lavorando, aggiungi `immediate: true` quando [registri il comando](/docs/it/plugins/mods/api#add-a-command). Senza di esso, un comando digitato durante un turno aspetta che il turno finisca.338Per consentire a un comando di aprire il pannello mentre Claude sta lavorando, aggiungi `immediate: true` quando [registri il comando](/docs/it/plugins/mods/api#add-a-command). Senza di esso, un comando digitato durante un turno attende la fine del turno.
327 339
328<h4 id="when-a-pane-waits-for-a-wider-terminal">340<h4 id="when-a-pane-waits-for-a-wider-terminal">
329 Quando un riquadro aspetta un terminale più ampio341 Quando un pannello attende un terminale più ampio
330</h4>342</h4>
331 343
332Un riquadro che il tuo mod apre senza essere chiesto non appare in un terminale stretto, quindi non può prendere il controllo di uno schermo piccolo. Se appare dipende da cosa l'ha aperto:344Un pannello che il tuo mod apre senza che gli sia stato chiesto non compare in un terminale stretto, così non può occupare uno schermo piccolo. Se compare o meno dipende da cosa lo ha aperto:
333 345
334* **Aperto da qualcosa che l'utente ha fatto**, come un comando che ha eseguito o un pulsante che ha premuto, il riquadro appare a qualsiasi larghezza346* **Aperto da un'azione dell'utente**, come un comando eseguito o un pulsante premuto, il pannello compare a qualsiasi larghezza
335* **Aperto dal tuo mod che agisce da solo**, come da un timer o un hook [`turn.start`](/docs/it/plugins/mods/events#follow-a-turn), il riquadro appare solo in un terminale di almeno 144 colonne di larghezza. Dopo che l'utente ha aperto quel riquadro una volta da solo, 110 colonne sono sufficienti.347* **Aperto dal tuo mod di propria iniziativa**, ad esempio da un timer o da un hook [`turn.start`](/docs/it/plugins/mods/events#follow-a-turn), il pannello compare solo in un terminale largo almeno 144 colonne. Dopo che l'utente ha aperto quel pannello almeno una volta di persona, bastano 110 colonne.
336 348
337Quando il riquadro appare, `$.ui.open` si risolve in `{ isPlaced: true }`. Quando il riquadro è in attesa, `isPlaced` è `false` e `reason` è una stringa che dice perché. Un riquadro in attesa appare quando l'utente lo apre o allarga il terminale. Per dire che qualcosa è disponibile senza aprire un riquadro, chiama `$.ui.toast('Your message')`, che mostra un piccolo avviso che scompare dopo pochi secondi.349Quando il pannello compare, `$.ui.open` si risolve in `{ isPlaced: true }`. Quando il pannello è in attesa, `isPlaced` è `false` e `reason` è una stringa che ne spiega il motivo. Un pannello in attesa compare quando l'utente lo apre o allarga il terminale. Per segnalare che qualcosa è disponibile senza aprire un pannello, chiama `$.ui.toast('Your message')`, che mostra una notifica toast.
338 350
339<h2 id="build-a-tree-from-elements">351<h2 id="build-a-tree-from-elements">
340 Costruire un albero da elementi352 Creare un albero a partire dagli elementi
341</h2>353</h2>
342 354
343Quello che un hook `ui.render` restituisce è un albero di elementi: una descrizione di cosa disegnare, fatta di box, testo e controlli annidati l'uno dentro l'altro. Descrivi il disegno, e Claude Code lo renderizza nel terminale o nell'app Desktop.355Ciò che un hook `ui.render` restituisce è un albero di elementi: una descrizione di cosa disegnare, composta da box, testo e controlli annidati l'uno nell'altro. Tu descrivi il disegno e Claude Code lo renderizza nel terminale o nell'app Desktop.
344 356
345Per ottenere gli elementi, chiama `$.ui.resolve(e)` nel tuo hook, come in `const { Box, Text, Button } = $.ui.resolve(e)`. Ogni elemento è una funzione. Passi le proprietà, e metti gli elementi e le stringhe che vanno dentro di esso in `children`.357Per ottenere gli elementi, chiama `$.ui.resolve(e)` nel tuo hook, come in `const { Box, Text, Button } = $.ui.resolve(e)`. Ogni elemento è una funzione. Le passi delle prop e inserisci in `children` gli elementi e le stringhe che vanno al suo interno.
346 358
347La maggior parte dei disegni usa quattro elementi. Seleziona una scheda per vedere ognuno e come il terminale lo disegna:359Seleziona una scheda per vedere ciascuno degli elementi più comuni e come il terminale lo disegna:
348 360
349<Tabs>361<Tabs>
350 <Tab title="Text">362 <Tab title="Text">
351 `Text` disegna una stringa, con stile opzionale come `bold` e `color`:363 `Text` disegna una stringa, con uno stile facoltativo come `bold` e `color`:
352 364
353 ```javascript theme={null}365 ```javascript theme={null}
354 Text({ children: ['This is the first tab.'] })366 Text({ children: ['This is the first tab.'] })
360 </Tab>372 </Tab>
361 373
362 <Tab title="Box">374 <Tab title="Box">
363 `Box` arrangia quello che è dentro di esso, in una riga o una colonna. Questo mette un pulsante e una riga di testo uno accanto all'altro, due colonne a parte:375 `Box` dispone ciò che contiene, in una riga o in una colonna. Questo mette un pulsante e una riga di testo uno accanto all'altro, a due colonne di distanza:
364 376
365 ```javascript theme={null}377 ```javascript theme={null}
366 Box({378 Box({
379 </Tab>391 </Tab>
380 392
381 <Tab title="Button">393 <Tab title="Button">
382 `Button` è un controllo che l'utente può premere. Esegue il tuo callback `onPress`. Con `plain: true` non ha parentesi e mostra la sua scorciatoia da tastiera:394 `Button` è un controllo che l'utente può premere. Esegue la tua callback `onPress`. Con `plain: true` non ha parentesi quadre e mostra il suo tasto di scelta rapida:
383 395
384 ```javascript theme={null}396 ```javascript theme={null}
385 Button({ key: 'more', label: 'Add one', onPress: addOne })397 Button({ key: 'more', label: 'Add one', onPress: addOne })
393 </Tab>405 </Tab>
394 406
395 <Tab title="Input">407 <Tab title="Input">
396 `Input` è un campo di testo. Esegue il tuo callback `onSubmit` con il testo quando l'utente preme Invio:408 `Input` è un campo di testo. Esegue la tua callback `onSubmit` con il testo quando l'utente preme Invio:
397 409
398 ```javascript theme={null}410 ```javascript theme={null}
399 Input({411 Input({
407 ```419 ```
408 420
409 ```text theme={null}421 ```text theme={null}
410 Note: Type a note and press Enter ⏎ add422 Note: Type a note and press Enter
411 ```423 ```
412 </Tab>424 </Tab>
413</Tabs>425</Tabs>
414 426
415Questa tabella elenca ogni elemento:427La [galleria dell'interfaccia](/docs/it/plugins/mods/gallery) contiene esempi e screenshot della maggior parte degli elementi. Questa tabella elenca tutti gli elementi:
416 428
417| Elemento | Cosa disegna | Dove |429| Elemento | Cosa disegna | Dove |
418| :- | :- | :- |430| :- | :- | :- |
419| `Box` | Un contenitore flex. Accetta proprietà di layout come `flexDirection`, `columnGap`, `padding`, `borderStyle`, e `width`. | Ovunque |431| `Box` | Un contenitore flex. Accetta prop di layout come `flexDirection`, `columnGap`, `padding`, `borderStyle` e `width`. | Ovunque |
420| `Text` | Testo stilizzato. Accetta `color`, `bold`, `dimColor`, `italic`, e `wrap`. Un `color` è una chiave di tema o un colore come `'red'`. Un `wrap` è `'wrap'`, `'truncate'`, `'truncate-start'`, `'truncate-middle'`, o `'truncate-end'`. | Ovunque |432| `Text` | Testo con stile. Accetta `color`, `bold`, `dimColor`, `italic` e `wrap`. Un `color` è una chiave del tema o un colore come `'red'`. Un `wrap` è `'wrap'`, `'truncate'`, `'truncate-start'`, `'truncate-middle'` o `'truncate-end'`. | Ovunque |
421| `Button` | Un controllo che chiama `onPress` | Ovunque |433| `Button` | Un controllo che chiama `onPress` | Ovunque |
422| `Link`, `Code`, `Markdown` | Un link con `href` e un `label` opzionale, un blocco di codice, e testo formattato come le risposte di Claude. `Markdown` accetta il suo contenuto in una proprietà `text`, non in `children`, e ha bisogno di una `key` quando passi `onLinkPress`. | Ovunque |434| `Link`, `Code`, `Markdown` | Un link con `href` e un `label` facoltativo, un blocco di codice e testo formattato come le risposte di Claude. `Markdown` riceve il suo contenuto nella prop `text`, non in `children`, e richiede una `key` quando passi `onLinkPress`. | Ovunque |
423| `Input`, `Select` | Un campo di testo e un selettore | Terminale, Desktop |435| `Input`, `Select` | Un campo di testo e un menu a discesa | Terminale, Desktop |
424| `Svg` | Un documento SVG | Desktop |436| `Svg` | Un documento SVG | Desktop |
425| `Client` | Una regione disegnata da un secondo file tuo, per animazione e input del puntatore. Quel file non ottiene l'API dei mod. Raggiunge i tuoi hook solo postando dati, che arrivano come evento `ui.message`. | Terminale, Desktop |437| `Client` | Un'area disegnata da un secondo file tuo, per animazioni e input del puntatore. Quel file non riceve alcuna API dei mod. Raggiunge i tuoi hook solo inviando dati, che arrivano come evento `ui.message`. | Terminale, Desktop |
426| `Raster`, `Image` | Una [griglia di celle colorate](#draw-a-grid-of-colored-cells), e un'immagine | Terminale |438| `Raster`, `Image` | Una [griglia di celle colorate](#draw-a-grid-of-colored-cells) e un'immagine | Terminale |
427 439
428Se il tuo modulo è un file `.tsx` o `.jsx`, puoi scrivere l'albero come JSX. Destruttura gli elementi da `$.ui.resolve(e)` per primo, perché un modulo di hook non ha globali di elementi.440Se il tuo modulo è un file `.tsx` o `.jsx`, puoi scrivere l'albero in JSX. Prima destruttura gli elementi da `$.ui.resolve(e)`.
429 441
430Se un albero usa un elemento che l'app non ha, una proprietà che un elemento non accetta, o un figlio dove nessuno va, Claude Code disegna la sua versione del sito.442Se un albero usa un elemento che l'app non ha, una prop che un elemento non accetta o un figlio dove non è previsto, Claude Code disegna la propria versione di quel punto.
431 443
432In una sessione avviata con `--plugin-dir`, una riga di trascrizione lo dice, come `ui.render (Pane) refused: Text prop "bogusProp" is not allowed; the engine drew its own`. Il [log di debug](/docs/it/plugins/mods/troubleshoot#read-the-debug-log) lo registra come `ui.render (Pane): a hook returned a tree that does not validate` con la stessa ragione. Nient'altro appare nella sessione, quindi quando un disegno non si mostra, controlla quella riga o il log.444In una sessione avviata con `--plugin-dir`, una riga della trascrizione lo segnala, ad esempio `ui.render (Pane) refused: Text prop "bogusProp" is not allowed; the engine drew its own`. Il [log di debug](/docs/it/plugins/mods/troubleshoot#read-the-debug-log) lo registra come `ui.render (Pane): a hook returned a tree that does not validate` con lo stesso motivo. Nient'altro compare nella sessione, quindi quando un disegno non viene visualizzato, controlla quella riga o il log.
433 445
434<h3 id="draw-a-grid-of-colored-cells">446<h3 id="draw-a-grid-of-colored-cells">
435 Disegnare una griglia di celle colorate447 Disegnare una griglia di celle colorate
436</h3>448</h3>
437 449
438Per una mappa di calore, una sparkline, o una tavola di gioco nel terminale, disegna un `Raster` e non un `Box` per ogni cella. Un `Raster` accetta una `key`, la sua dimensione in `columns` e `rows`, e `cells`, che compatta ogni cella in una stringa. Ogni cella è tre numeri: il punto di codice del carattere, il suo colore, e il colore di sfondo. Un colore è un numero esadecimale con due cifre ciascuno per rosso, verde e blu, come `0xc62828` per un rosso, o `0x01000000` per il default del terminale.450Per una mappa di calore, una sparkline o un tabellone di gioco nel terminale, disegna un unico `Raster` e non un `Box` per ogni cella. Un `Raster` accetta una `key`, le sue dimensioni in `columns` e `rows`, e `cells`, una stringa base64 che racchiude tutte le celle. Ogni cella è composta da tre numeri: il code point del carattere, il suo colore e il suo colore di sfondo. Un colore è un valore RGB a 24 bit in esadecimale, come `0xc62828` per un rosso. Il valore `0x01000000`, uno sopra quell'intervallo, indica il colore predefinito del terminale.
439 451
440L'app Desktop non ha `Raster`, quindi controlla `e.surface` e disegna testo lì. Questo corpo del riquadro disegna una mappa di calore tre per due:452L'app Desktop non ha `Raster`, quindi controlla `e.surface` e lì disegna del testo. Questo corpo del pannello disegna una mappa di calore tre per due:
441 453
442```javascript theme={null}454```javascript theme={null}
443// Il valore che significa "usa il colore predefinito del terminale"455// The value that means "use the terminal's default color"
444const DEFAULT_COLOR = 0x01000000456const DEFAULT_COLOR = 0x01000000
445 457
446// Compatta righe di coppie [carattere, colore] nella stringa che un Raster accetta458// Pack rows of [character, color] pairs into the one string a Raster takes
447// Una cella è tre numeri: il punto di codice del carattere, il suo colore, e lo sfondo459// One cell is three numbers: the character's code point, its color, and its background
448function cellsOf(rows) {460function cellsOf(rows) {
449 const numbers = rows.flat().flatMap(([char, color]) => [char.codePointAt(0), color, DEFAULT_COLOR])461 const numbers = rows.flat().flatMap(([char, color]) => [char.codePointAt(0), color, DEFAULT_COLOR])
450 return new Uint8Array(Uint32Array.from(numbers).buffer).toBase64()462 return new Uint8Array(Uint32Array.from(numbers).buffer).toBase64()
451}463}
452 464
453on('ui.render', { component: 'Pane' }, async ($, e, next) => {465on('ui.render', { component: 'Pane' }, async ($, e, next) => {
454 // Disegna solo nel riquadro aperto con l'id 'heat'466 // Draw only in the pane opened with the id 'heat'
455 if (e.requestId !== 'heat') return next(e)467 if (e.requestId !== 'heat') return next(e)
456 const { Box, Text, Raster } = $.ui.resolve(e)468 const { Box, Text, Raster } = $.ui.resolve(e)
457 // Due righe di tre celle, ognuna un carattere di blocco e il suo colore469 // Two rows of three cells, each a block character and its color
458 const rows = [470 const rows = [
459 [['█', 0x2e7d32], ['█', 0xf9a825], ['█', 0xc62828]],471 [['█', 0x2e7d32], ['█', 0xf9a825], ['█', 0xc62828]],
460 [['█', 0x2e7d32], ['█', 0x2e7d32], ['█', 0xf9a825]],472 [['█', 0x2e7d32], ['█', 0x2e7d32], ['█', 0xf9a825]],
469})481})
470```482```
471 483
472Nel terminale, il riquadro mostra la griglia:484Nel terminale, il pannello mostra la griglia:
473 485
474<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-heat-map.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=b91bcce3bad74bc851149133d4acc5d5" alt="Un riquadro nel terminale che contiene una piccola griglia di blocchi colorati, due righe di tre. La riga superiore è verde, ambra e rossa. La riga inferiore è verde, verde e ambra." width="360" height="132" data-path="images/mods-heat-map.svg" />486<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-heat-map.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=b91bcce3bad74bc851149133d4acc5d5" alt="Un pannello nel terminale che contiene una piccola griglia di blocchi colorati, due righe da tre. La riga superiore è verde, ambra e rossa. La riga inferiore è verde, verde e ambra." width="360" height="132" data-path="images/mods-heat-map.svg" />
475 487
476L'array `rows` è la parte che cambieresti, e `cellsOf` lo trasforma nella stringa compatta. L'hook disegna solo in un riquadro il cui `id` è `heat`, quindi aprine uno con `$.ui.open({ id: 'heat' })` da un comando, come l'esempio [`hello-tabs`](#build-a-pane-with-tabs) apre il suo riquadro.488L'array `rows` è la parte da modificare, e `cellsOf` lo trasforma nella stringa compatta. L'hook disegna solo in un pannello il cui `id` è `heat`, quindi aprine uno con `$.ui.open({ id: 'heat' })` da un comando, come l'[esempio `hello-tabs`](#build-a-pane-with-tabs) apre il suo pannello.
477 489
478Ogni carattere deve essere largo una cella. Per animare un `Raster` che è già sullo schermo, chiama `$.ui.blit` con l'`id` del riquadro come `requestId`, la `key` del `Raster`, la stessa dimensione, e celle nuove. Per questo esempio, è `$.ui.blit({ requestId: 'heat', key: 'grid', columns: 3, rows: 2, cells: cellsOf(newRows) })`. Ridipinge solo quell'elemento senza eseguire di nuovo il tuo hook `ui.render`.490Ogni carattere deve essere largo una cella. Per animare un `Raster` già presente sullo schermo, chiama `$.ui.blit` con l'`id` del pannello come `requestId`, la `key` del `Raster`, le stesse dimensioni e le nuove celle. Per questo esempio, è `$.ui.blit({ requestId: 'heat', key: 'grid', columns: 3, rows: 2, cells: cellsOf(newRows) })`. Ridisegna solo quell'elemento senza eseguire di nuovo il tuo hook `ui.render`.
479 491
480<h2 id="respond-to-presses-and-typing">492<h2 id="respond-to-presses-and-typing">
481 Rispondere a pressioni e digitazione493 Rispondere a pressioni e digitazione
482</h2>494</h2>
483 495
484Quando l'utente preme un pulsante, digita in un campo, o sceglie da un elenco che il tuo mod ha disegnato, Claude Code chiama la funzione che hai dato a quel controllo, e viene eseguita nel tuo modulo. Ogni controllo accetta i suoi callback:496Quando l'utente preme un pulsante, digita in un campo o sceglie da un elenco disegnato dal tuo mod, Claude Code chiama la callback di quel controllo, che viene eseguita nel tuo modulo. Ogni controllo accetta le proprie callback:
485 497
486* **`Button`**: accetta `onPress(e)`, dove `e.surface` è l'app da cui viene la pressione498* **`Button`**: accetta `onPress(e)`, dove `e.surface` è l'app da cui proviene la pressione
487* **`Input`**: accetta `onSubmit(value)` e `onInput(value)`499* **`Input`**: accetta `onSubmit(value)` e `onInput(value)`
488* **`Select`**: accetta `onSelect(value)` con le sue scelte in `options`, un elenco di almeno una scelta con valori unici, come `[{ value: 'sm', label: 'Small' }, { value: 'lg', label: 'Large' }]`500* **`Select`**: accetta `onSelect(value)` con le sue scelte in `options`, un elenco di almeno una scelta con valori univoci, come `[{ value: 'sm', label: 'Small' }, { value: 'lg', label: 'Large' }]`
489 501
490Un test preme o digita in un controllo per la sua `key`, quindi dagli uno. Ogni uso di un controllo genera anche [`ui.press`, `ui.input`, o `ui.select`](/docs/it/plugins/mods/reference#interface) con la `key` in `e.element`, e un altro mod può agganciare quegli eventi. Il suo hook viene eseguito prima del tuo callback, quindi vede quello che l'utente digita nel tuo `Input` e può cambiarlo o rispondere al posto del tuo callback. L'API dei mod non ha un metodo che preme il pulsante di un altro mod.502Un test preme o digita in un controllo tramite la sua `key`, quindi assegnane una a ciascun controllo. Ogni uso di un controllo attiva anche [`ui.press`, `ui.input` o `ui.select`](/docs/it/plugins/mods/reference#interface) con la `key` in `e.element`, e un altro mod può gestire quegli eventi. Il suo hook viene eseguito prima della tua callback, quindi vede ciò che l'utente digita nel tuo `Input` e può modificarlo o rispondere al posto della tua callback. L'API dei mod non ha alcun metodo che prema il pulsante di un altro mod.
491 503
492<h3 id="know-which-keys-your-mod-can-receive">504<h3 id="know-which-keys-your-mod-can-receive">
493 Focus della tastiera e scorciatoie da tastiera505 Focus della tastiera e tasti di scelta rapida
494</h3>506</h3>
495 507
496Il tuo mod non legge mai la tastiera da solo. L'utente preme un tasto, Claude Code decide quale dei tuoi controlli è per esso, e il callback di quel controllo viene eseguito. A parte una [scorciatoia da tastiera con cifra sulla banda](/docs/it/plugins/mods/reference#elements), questo accade solo mentre il tuo riquadro o banda ha il focus della tastiera. Il resto del tempo, i tasti vanno al prompt.508Il tuo mod non legge mai direttamente la tastiera. L'utente preme un tasto, Claude Code decide a quale dei tuoi controlli è destinato e viene eseguita la callback di quel controllo. A parte un [tasto di scelta rapida numerico sulla banda](/docs/it/plugins/mods/reference#elements), questo accade solo mentre il tuo pannello o la tua banda ha il focus della tastiera. Il resto del tempo, i tasti vanno al prompt.
497 509
498<h4 id="how-a-pane-gets-keyboard-focus">510<h4 id="how-a-pane-gets-keyboard-focus">
499 Come un riquadro ottiene il focus della tastiera511 Come un pannello ottiene il focus della tastiera
500</h4>512</h4>
501 513
502Un riquadro ottiene il focus della tastiera in uno di tre modi:514Un pannello ottiene il focus della tastiera quando:
503 515
504* Il tuo mod lo apre con `focus: true` da un comando o una pressione516* Il tuo mod lo apre con `focus: true` da un comando o da una pressione
505* L'utente preme Ctrl+X poi Tab517* L'utente preme Ctrl+X e poi Tab
506* L'utente lo fa clic518* L'utente ci fa clic sopra
507 519
508Claude Code concede `focus: true` solo mentre il prompt è vuoto e nient'altro ha il focus della tastiera. Un riquadro che si apre mentre l'utente sta digitando non prende i suoi tasti.520Claude Code concede `focus: true` solo mentre il prompt è vuoto e nient'altro ha il focus della tastiera. Un pannello che si apre mentre l'utente sta digitando non ne intercetta i tasti premuti.
509 521
510<h4 id="what-each-key-does">522<h4 id="what-each-key-does">
511 Cosa fa ogni tasto523 Cosa fa ogni tasto
512</h4>524</h4>
513 525
514Questa tabella elenca cosa fa un tasto mentre il tuo riquadro o banda ha il focus della tastiera:526Questa tabella elenca cosa fa un tasto mentre il tuo pannello o la tua banda ha il focus della tastiera:
515 527
516| Tasto | Cosa fa |528| Tasto | Cosa fa |
517| :- | :- |529| :- | :- |
518| Tab | Si sposta al controllo successivo |530| Tab | Passa al controllo successivo |
519| Su e Giù | Si spostano tra i controlli mentre il tuo disegno si adatta. Quando il riquadro o la banda ha più righe di quante possa mostrare, lo scorrono. |531| Su e Giù | Spostano tra i controlli finché il tuo disegno entra nello spazio disponibile. Quando il pannello o la banda ha più righe di quante ne possa mostrare, lo fanno scorrere. |
520| Invio | Preme il `Button` focalizzato, invia il `Input` focalizzato, o sceglie in un `Select` |532| Invio | Preme il `Button` con il focus, invia l'`Input` con il focus o effettua la scelta in un `Select` |
521| La scorciatoia da tastiera di un pulsante | Preme quel pulsante. Mentre un `Input` ha il focus, ogni tasto stampabile va al campo. |533| Il tasto di scelta rapida di un pulsante | Preme quel pulsante. Mentre un `Input` ha il focus, ogni tasto stampabile va al campo. |
522| Esc | Restituisce il focus della tastiera al prompt. Con `closeOnEscape: true`, chiude anche il riquadro. |534| Esc | Restituisce il focus della tastiera al prompt. Con `closeOnEscape: true`, chiude anche il pannello. |
523 535
524Un mod non può associare Tab o i tasti freccia a nient'altro, quindi un gioco si muove con `w`, `a`, `s`, e `d`.536Un mod non può associare Tab o i tasti freccia a nient'altro, quindi un gioco si controlla con `w`, `a`, `s` e `d`.
525 537
526<h4 id="set-a-hotkey-and-the-first-focus">538<h4 id="set-a-hotkey-and-the-first-focus">
527 Impostare una scorciatoia da tastiera e il primo focus539 Impostare un tasto di scelta rapida e il focus iniziale
528</h4>540</h4>
529 541
530Due proprietà su un controllo decidono come la tastiera lo raggiunge:542Queste prop su un controllo decidono come la tastiera lo raggiunge:
531 543
532* **`hotkey`**: per lasciare che l'utente preme un `Button` con un tasto, dagli una `hotkey` di una cifra o una lettera minuscola, come in `hotkey: 'a'`544* **`hotkey`**: per consentire all'utente di premere un `Button` con un solo tasto, assegnagli una `hotkey` composta da una cifra o da una lettera minuscola, come in `hotkey: 'a'`
533* **`autoFocus`**: per scegliere quale controllo ha il focus quando il riquadro si apre, aggiungi `autoFocus: true` ad esso. Lascia la proprietà fuori dagli altri, perché Claude Code rifiuta `autoFocus: false`.545* **`autoFocus`**: per scegliere quale controllo ha il focus all'apertura del pannello, aggiungi `autoFocus: true` a quel controllo. La prop accetta solo `true`, quindi omettila sugli altri controlli.
534 546
535Come una scorciatoia da tastiera si mostra dipende dal pulsante e dall'app:547Il modo in cui viene mostrato un tasto di scelta rapida dipende dal pulsante e dall'app:
536 548
537| Pulsante | Nel terminale | Nell'app Desktop |549| Pulsante | Nel terminale | Nell'app Desktop |
538| :- | :- | :- |550| :- | :- | :- |
539| Con parentesi, il default | `[ Add one ]`, senza scorciatoia da tastiera mostrata | L'etichetta con un piccolo tasto accanto |551| Con parentesi quadre, l'impostazione predefinita | `[ Add one ]`, senza alcun tasto di scelta rapida mostrato | L'etichetta con un piccolo tasto accanto |
540| Con `plain: true` | `1: One` | L'etichetta con un piccolo tasto accanto |552| Con `plain: true` | `1: One` | L'etichetta con un piccolo tasto accanto |
541 553
542Nel terminale, nomina il tasto nell'etichetta di un pulsante tra parentesi, o usa `plain: true`, così l'utente può vedere cosa premere. Il [riferimento degli elementi](/docs/it/plugins/mods/reference#elements) ha le altre regole di `Button`: `action`, scorciatoie da tastiera con cifra sulla banda, e due pulsanti su una scorciatoia da tastiera.554Nel terminale, indica il tasto nell'etichetta di un pulsante con parentesi quadre, oppure usa `plain: true`, in modo che l'utente possa vedere cosa premere. Il [riferimento degli elementi](/docs/it/plugins/mods/reference#elements) contiene le altre regole di `Button`: `action`, i tasti di scelta rapida numerici sulla banda e due pulsanti sullo stesso tasto di scelta rapida.
543 555
544<h3 id="take-typed-input-and-draw-a-row-for-each-item">556<h3 id="take-typed-input-and-draw-a-row-for-each-item">
545 Prendere input digitato e disegnare una riga per ogni elemento557 Ricevere input digitato e disegnare una riga per ogni elemento
546</h3>558</h3>
547 559
548Molti riquadri sono un campo di testo con un elenco sotto. L'esempio in questa sezione è un riquadro di note: digiti una nota e premi Invio per aggiungerla, e ogni nota ha un pulsante `x` che la elimina. Con due note aggiunte, il terminale disegna il riquadro in questo modo:560Molti pannelli sono un campo di testo con un elenco sotto. L'esempio in questa sezione è un pannello di note: digiti una nota e premi Invio per aggiungerla, e ogni nota ha un pulsante `x` che la elimina. Con due note aggiunte, il terminale disegna il pannello in questo modo:
549 561
550```text theme={null}562```text theme={null}
551╭──────────────────────────────────────────────────────────╮563╭──────────────────────────────────────────────────────────╮
555╰──────────────────────────────────────────────────────────╯567╰──────────────────────────────────────────────────────────╯
556```568```
557 569
558L'esempio usa due tecniche:570L'esempio usa queste tecniche:
559 571
560* **Prendere input digitato**: un `Input` chiama `onSubmit(value)` con il testo del campo quando l'utente preme Invio, e `onInput(value)` ad ogni cambio572* **Ricevere input digitato**: un `Input` chiama `onSubmit(value)` con il testo del campo quando l'utente preme Invio, e `onInput(value)` a ogni modifica
561* **Disegnare un elenco**: mappa i tuoi dati a una riga ciascuno, e dai a ogni pulsante della riga la sua `key`573* **Disegnare un elenco**: mappa i tuoi dati su una riga ciascuno e assegna al pulsante di ogni riga una propria `key`
562 574
563Questo hook disegna il contenuto del riquadro:575Questo hook disegna il contenuto del pannello:
564 576
565```javascript theme={null}577```javascript theme={null}
566// L'elenco che il riquadro disegna578// The list the pane draws
567let notes = []579let notes = []
568 580
569on('ui.render', { component: 'Pane' }, async ($, e, next) => {581on('ui.render', { component: 'Pane' }, async ($, e, next) => {
570 // Disegna solo nel riquadro aperto con l'id 'notes'582 // Draw only in the pane opened with the id 'notes'
571 if (e.requestId !== 'notes') return next(e)583 if (e.requestId !== 'notes') return next(e)
572 const { Box, Text, Button, Input } = $.ui.resolve(e)584 const { Box, Text, Button, Input } = $.ui.resolve(e)
573 const redraw = () => $.ui.invalidate('ui.render')585 const redraw = () => $.ui.invalidate('ui.render')
579 key: 'new-note',591 key: 'new-note',
580 label: 'Note',592 label: 'Note',
581 placeholder: 'Type a note and press Enter',593 placeholder: 'Type a note and press Enter',
582 // Disegna il campo vuoto ogni volta, che lo cancella dopo un invio594 // Draw the field empty each time, which clears it after a submit
583 value: '',595 value: '',
584 submitLabel: 'add',596 submitLabel: 'add',
585 autoFocus: true,597 autoFocus: true,
586 // Viene eseguito quando premi Invio nel campo598 // Runs when you press Enter in the field
587 onSubmit: async (value) => {599 onSubmit: async (value) => {
588 // Ignora una riga vuota600 // Ignore an empty line
589 if (!value.trim()) return601 if (!value.trim()) return
590 notes = [...notes, value.trim()]602 notes = [...notes, value.trim()]
591 redraw()603 redraw()
592 await $.store.set('notes', notes)604 await $.store.set('notes', notes)
593 },605 },
594 }),606 }),
595 // Una riga per ogni nota: un pulsante di eliminazione, quindi il testo della nota607 // One row for each note: a delete button, then the note's text
596 ...notes.map((note, i) =>608 ...notes.map((note, i) =>
597 Box({609 Box({
598 flexDirection: 'row',610 flexDirection: 'row',
599 columnGap: 1,611 columnGap: 1,
600 children: [612 children: [
601 Button({613 Button({
602 // Una key propria, così il pulsante di ogni riga può essere distinto614 // A key of its own, so each row's button can be told apart
603 key: 'delete-' + i,615 key: 'delete-' + i,
604 label: 'x',616 label: 'x',
605 plain: true,617 plain: true,
618})630})
619```631```
620 632
621Per provare il riquadro:633Per provare il pannello:
622 634
623* **Aggiungi una nota**: digita una riga e premi Invio. La riga appare come una nuova riga, e il campo si svuota.635* **Aggiungi una nota**: digita una riga e premi Invio. La riga appare come una nuova riga dell'elenco e il campo si svuota.
624* **Elimina una nota**: premi Tab finché il pulsante `x` della nota non ha il focus, quindi premi Invio. La `x` è l'etichetta del pulsante e non una scorciatoia da tastiera, quindi digitare la lettera non lo preme.636* **Elimina una nota**: premi Tab finché il pulsante `x` della nota non ha il focus, poi premi Invio. La `x` è l'etichetta del pulsante e non un tasto di scelta rapida, quindi digitare la lettera non lo preme.
625 637
626Ogni cambio segue lo stesso ciclo di rendering di `hello-tabs`: il callback cambia `notes`, chiama `redraw`, e salva l'elenco in `$.store`.638Ogni modifica segue lo stesso ciclo di rendering di `hello-tabs`: la callback modifica `notes`, chiama `redraw` e salva l'elenco in `$.store`.
627 639
628Il campo si svuota dopo ogni invio a causa della sua proprietà `value`. `value` è il testo che il campo contiene quando viene disegnato, e la digitazione dell'utente lo sostituisce finché il tuo hook non disegna il campo di nuovo. L'esempio disegna sempre il campo con `''`.640Il campo si svuota dopo ogni invio grazie alla sua prop `value`. `value` è il testo che il campo contiene quando viene disegnato, e ciò che l'utente digita lo sostituisce finché il tuo hook non disegna di nuovo il campo. L'esempio disegna sempre il campo con `''`.
629 641
630L'esempio salva le note e non le carica. Per riportarle nella sessione successiva, leggile in un hook `session.start`, come `hello-tabs` legge `count`.642L'esempio salva le note ma non le carica. Per ripristinarle nella sessione successiva, leggile in un hook `session.start`, nello stesso modo in cui `hello-tabs` legge `count`.
631 643
632Tre proprietà compongono la riga del campo, `Note: Type a note and press Enter ⏎ add`:644Queste prop compongono la riga del campo, `Note: Type a note and press Enter ⏎ add`:
633 645
634| Proprietà | Nell'esempio | Cosa è |646| Prop | Nell'esempio | Cos'è |
635| :- | :- | :- |647| :- | :- | :- |
636| `label` | `Note` | Il testo prima del campo. Il terminale disegna `: ` dopo di esso. |648| `label` | `Note` | Il testo prima del campo. Il terminale disegna `: ` dopo di esso. |
637| `placeholder` | `Type a note and press Enter` | Testo attenuato che si mostra mentre il campo è vuoto |649| `placeholder` | `Type a note and press Enter` | Testo attenuato che viene mostrato mentre il campo è vuoto |
638| `submitLabel` | `add` | La parola dopo `⏎` che dice cosa fa Invio |650| `submitLabel` | `add` | La parola dopo `⏎` che indica cosa fa Invio |
639 651
640Inviare un `Input` non avvia un turno a meno che il tuo callback non chiami [`$.prompt.submit`](/docs/it/plugins/mods/api#start-a-turn-from-a-background-job).652L'invio di un `Input` non avvia un turno a meno che la tua callback non chiami [`$.prompt.submit`](/docs/it/plugins/mods/api#start-a-turn-from-a-background-job).
641 653
642<h2 id="redraw-when-something-changes">654<h2 id="redraw-when-something-changes">
643 Ridisegnare un sito655 Ridisegnare un sito
644</h2>656</h2>
645 657
646Un disegno è un'istantanea: mostra quello che il tuo hook `ui.render` ha restituito l'ultima volta che l'hook è stato eseguito. Per mostrare qualcosa di nuovo, l'hook deve essere eseguito di nuovo. Claude Code lo esegue di nuovo per alcuni cambiamenti, e il tuo mod chiede il resto.658Un disegno è un'istantanea: mostra ciò che il tuo hook `ui.render` ha restituito l'ultima volta che l'hook è stato eseguito. Per mostrare qualcosa di nuovo, l'hook deve essere eseguito di nuovo. Claude Code lo riesegue per alcune modifiche, e il tuo mod lo richiede per le altre.
647 659
648<h3 id="when-claude-code-redraws-without-being-asked">660<h3 id="when-claude-code-redraws-without-being-asked">
649 Quando Claude Code ridisegna senza essere chiesto661 Quando Claude Code ridisegna senza che venga richiesto
650</h3>662</h3>
651 663
652Claude Code esegue di nuovo il tuo hook `ui.render` quando le proprietà del sito cambiano o la larghezza del terminale cambia. Non esegue l'hook su un timer, e non può dire quando una variabile nel tuo modulo cambia.664Claude Code esegue di nuovo il tuo hook `ui.render` quando cambiano le prop del sito o quando cambia la larghezza del terminale. Non esegue l'hook in base a un timer, e non può sapere quando cambia una variabile nel tuo modulo.
653 665
654<h3 id="redraw-when-your-data-changes">666<h3 id="redraw-when-your-data-changes">
655 Ridisegnare quando i tuoi dati cambiano667 Ridisegnare quando i tuoi dati cambiano
656</h3>668</h3>
657 669
658Per avere i tuoi siti disegnati di nuovo dopo che i tuoi dati cambiano, chiama `$.ui.invalidate('ui.render')`. Questo riquadro conta le pressioni. Il callback del pulsante cambia `count`, quindi chiede un ridisegno:670Per far ridisegnare i tuoi siti dopo che i tuoi dati sono cambiati, chiama `$.ui.invalidate('ui.render')`. Questo pannello conta le pressioni. La callback del pulsante modifica `count`, poi richiede un nuovo disegno:
659 671
660```javascript theme={null}672```javascript theme={null}
661let count = 0673let count = 0
672 label: 'Add one',684 label: 'Add one',
673 onPress: () => {685 onPress: () => {
674 count += 1686 count += 1
675 // I dati sono cambiati, quindi chiedi a Claude Code di disegnare il riquadro di nuovo687 // The data changed, so ask Claude Code to draw the pane again
676 $.ui.invalidate('ui.render')688 $.ui.invalidate('ui.render')
677 },689 },
678 }),690 }),
682})694})
683```695```
684 696
685Ogni pressione alza il numero nel riquadro. L'esempio [`hello-tabs`](#build-a-pane-with-tabs) avvolge la stessa chiamata nella sua funzione `redraw`.697Ogni pressione incrementa il numero nel pannello. L'[esempio `hello-tabs`](#build-a-pane-with-tabs) racchiude la stessa chiamata nella sua funzione `redraw`.
686 698
687Un valore che mantieni in [`$.state`](#keep-a-value-in-\$-state) non ha bisogno della chiamata, perché scrivere il valore ridisegna i siti che lo leggono.699Un valore che conservi in [`$.state`](#keep-a-value-in-\$-state) non ha bisogno della chiamata, perché scrivere il valore ridisegna i siti che lo leggono.
688 700
689<h3 id="redraw-on-a-timer">701<h3 id="redraw-on-a-timer">
690 Ridisegnare su un timer702 Ridisegnare in base a un timer
691</h3>703</h3>
692 704
693Per mantenere un orologio, un conto alla rovescia, o un valore da fuori la sessione attuale, ridisegna su un programma. Avvia un timer nell'hook `session.start` del modulo. Se il modulo ne ha già uno, come `hello-tabs`, aggiungi la riga [`$.clock.every`](/docs/it/plugins/mods/api#run-work-in-the-background) ad esso:705Per mantenere aggiornati un orologio, un conto alla rovescia o un valore esterno alla sessione, ridisegna secondo una pianificazione. Avvia un timer nell'hook `session.start` del modulo. Se il modulo ne ha già uno, come nel caso di `hello-tabs`, aggiungi a esso la riga [`$.clock.every`](/docs/it/plugins/mods/api#run-work-in-the-background):
694 706
695```javascript theme={null}707```javascript theme={null}
696on('session.start', async ($, e, next) => {708on('session.start', async ($, e, next) => {
697 // Ogni 1000 millisecondi, chiedi a Claude Code di disegnare di nuovo i tuoi siti709 // Every 1000 milliseconds, ask Claude Code to draw your sites again
698 $.clock.every(1000, () => $.ui.invalidate('ui.render'))710 $.clock.every(1000, () => $.ui.invalidate('ui.render'))
699 return next(e)711 return next(e)
700})712})
701```713```
702 714
703Claude Code ora esegue il tuo hook `ui.render` una volta al secondo. Il timer si ferma quando il modulo si ricarica, e la nuova copia del modulo avvia il suo.715Ora Claude Code esegue il tuo hook `ui.render` una volta al secondo. Il timer si arresta quando il modulo viene ricaricato, e la nuova istanza del modulo avvia il proprio.
704 716
705<h3 id="how-often-a-site-can-redraw">717<h3 id="how-often-a-site-can-redraw">
706 Quanto spesso un sito può ridisegnare718 Con quale frequenza un sito può essere ridisegnato
707</h3>719</h3>
708 720
709Claude Code limita quanto spesso ridisegna un sito, quindi il tuo mod può chiamare `$.ui.invalidate` quanto spesso i suoi dati cambiano. Il riquadro visibile e la banda hanno un limite più alto rispetto ad altri siti, e la [tabella dei limiti](/docs/it/plugins/mods/reference#limits) contiene i numeri.721Claude Code limita la frequenza dei ridisegni di un sito, quindi il tuo mod può chiamare `$.ui.invalidate` tutte le volte che i suoi dati cambiano. Per sapere con quale frequenza ciascun sito può essere ridisegnato, consulta la [tabella dei limiti](/docs/it/plugins/mods/reference#limits).
710 722
711Le chiamate che arrivano più velocemente del limite vengono combinate in un ridisegno. Quel ridisegno esegue il tuo hook una volta, e l'hook legge i tuoi dati come sono in quel momento, quindi il valore più recente si mostra e i valori in mezzo no. Un'animazione non può essere eseguita più velocemente del limite.723Le chiamate che arrivano più velocemente del limite vengono accorpate in un unico ridisegno. Quel ridisegno esegue il tuo hook una sola volta, e l'hook legge i tuoi dati così come sono in quel momento, quindi viene mostrato il valore più recente e non quelli intermedi. Un'animazione non può essere eseguita più velocemente del limite.
712 724
713<h2 id="keep-state">725<h2 id="keep-state">
714 Mantenere lo stato726 Mantenere lo stato
715</h2>727</h2>
716 728
717Un mod ha tre posti per mantenere un valore, e differiscono in quanto tempo il valore dura: finché il modulo non si ricarica, finché la sessione non finisce, o da una sessione all'altra. Scegli in base a quanto tempo il valore deve durare:729Il punto in cui un mod conserva un valore determina quanto a lungo il valore dura: fino al ricaricamento del modulo, fino alla fine della sessione, oppure da una sessione all'altra. Scegli in base a quanto a lungo il valore deve durare:
718 730
719| Mantienilo in | Dura fino a | Usalo per |731| Conservalo in | Dura fino a quando | Usalo per |
720| :- | :- | :- |732| :- | :- | :- |
721| Una variabile a livello di modulo | Il modulo si ricarica, che accade ogni volta che salvi un file durante lo sviluppo | Valori che puoi perdere, come `tab` è in `hello-tabs` |733| Una variabile a livello di modulo | Il modulo si ricarica, cosa che avviene ogni volta che salvi un file durante lo sviluppo | Valori che puoi perdere, come `tab` in `hello-tabs` |
722| `$.state` | La sessione finisce, o l'utente esegue `/clear`, `/resume`, o `/branch` | Valori su cui un disegno dipende che dovrebbero sopravvivere a un ricaricamento |734| `$.state` | La sessione termina, oppure l'utente esegue `/clear`, `/resume` o `/branch` | Valori da cui dipende un disegno e che devono sopravvivere a un ricaricamento |
723| `$.store` | Il tuo mod lo elimina, o nessuna sessione legge o scrive lo store per [`cleanupPeriodDays`](/docs/it/settings-reference#cleanupperioddays). Lo store è un archivio chiave-valore, salvato come file JSON del tuo plugin sotto `~/.claude/plugins/store/`. | Impostazioni, cronologia, qualsiasi cosa l'utente si aspetta di trovare la prossima volta |735| `$.store` | Il tuo mod lo elimina, oppure nessuna sessione legge o scrive lo store per [`cleanupPeriodDays`](/docs/it/settings-reference#cleanupperioddays). Lo store è un archivio chiave-valore, salvato come file JSON proprio del tuo plugin in `~/.claude/plugins/store/`. | Impostazioni, cronologia, tutto ciò che l'utente si aspetta di ritrovare la volta successiva |
724 736
725`$.store.get(key)` si risolve nel valore o `undefined`, e `$.store.set(key, value)` accetta qualsiasi valore JSON.737`$.store.get(key)` si risolve nel valore o in `undefined`, e `$.store.set(key, value)` accetta qualsiasi valore JSON.
726 738
727<h3 id="keep-a-value-in-state">739<h3 id="keep-a-value-in-$-state">
728 Mantenere un valore in `$.state`740 Conservare un valore in `$.state`
729</h3>741</h3>
730 742
731`$.state` contiene valori per la durata di una sessione, e ridisegna per te. È uno stato reattivo: un hook `ui.render` che legge un valore si iscrive ad esso, quindi Claude Code ridisegna quel sito ogni volta che scrivi il valore, e non chiami `$.ui.invalidate`. Un valore in `$.state` sopravvive anche a un ricaricamento del modulo, che una variabile non fa.743`$.state` conserva i valori per la durata di una sessione e ridisegna al posto tuo. È uno stato reattivo: un hook `ui.render` che legge un valore si sottoscrive a esso, quindi Claude Code ridisegna quel punto ogni volta che scrivi il valore, e non devi chiamare `$.ui.invalidate`. Un valore in `$.state` sopravvive inoltre a un ricaricamento del modulo, cosa che una variabile non fa.
732 744
733Per configurarlo, dichiara i tuoi valori, punta il tuo manifesto alla dichiarazione, quindi definisci e usa ogni valore. Gli esempi spostano il `count` da `hello-tabs` in `$.state`.745Per configurarlo, dichiara i tuoi valori, fai puntare il manifest alla dichiarazione, poi definisci e usa ciascun valore. Gli esempi spostano il `count` di `hello-tabs` in `$.state`.
734 746
735<h4 id="declare-the-values">747<h4 id="declare-the-values">
736 Dichiarare i valori748 Dichiarare i valori
737</h4>749</h4>
738 750
739Dichiara i valori in un file di tipi. La chiave esterna è il nome del tuo plugin, e ogni voce sotto di esso è un valore e il suo tipo. Salva questo come `hello-tabs/types/index.d.ts`:751Dichiara i valori in un file di dichiarazione dei tipi. La chiave esterna è il nome del tuo plugin, e ogni voce sotto di essa è un valore con il suo tipo. Salva questo come `hello-tabs/types/index.d.ts`:
740 752
741```typescript hello-tabs/types/index.d.ts theme={null}753```typescript hello-tabs/types/index.d.ts theme={null}
742declare module 'claude-code' {754declare module 'claude-code' {
750```762```
751 763
752<h4 id="point-the-manifest-at-the-declaration">764<h4 id="point-the-manifest-at-the-declaration">
753 Puntare il manifesto alla dichiarazione765 Far puntare il manifest alla dichiarazione
754</h4>766</h4>
755 767
756Per lasciare che `claude plugin validate` controlli il tuo codice contro quel file, aggiungi un campo `types` al manifesto con il suo percorso:768Per consentire a `claude plugin validate` di verificare il tuo codice rispetto a quel file, aggiungi al manifest un campo `types` con il suo percorso:
757 769
758```json hello-tabs/.claude-plugin/plugin.json theme={null}770```json hello-tabs/.claude-plugin/plugin.json theme={null}
759{771{
769 Definire, leggere e scrivere un valore781 Definire, leggere e scrivere un valore
770</h4>782</h4>
771 783
772Nel tuo modulo, definisci ogni valore con un default, leggilo mentre disegni, e scrivilo da un callback. `atom` nomina un valore e il suo default, `read` lo restituisce, e `update` lo scrive. I tre helper chiamano `$.state.get` e `$.state.set` per te:784Nel tuo modulo, definisci ciascun valore con un valore predefinito, leggilo durante il disegno e scrivilo da una callback. `atom` assegna un nome a un valore e al suo valore predefinito, `read` lo restituisce e `update` lo scrive. I tre helper chiamano `$.state.get` e `$.state.set` al posto tuo:
773 785
774```javascript theme={null}786```javascript theme={null}
775import { atom, read, update } from 'claude-code'787import { atom, read, update } from 'claude-code'
776 788
777// In cima al modulo: nomina il valore e dai il suo default789// At the top of the module: name the value and give its default
778const count = atom({ plugin: 'hello-tabs', key: 'count' }, 0)790const count = atom({ plugin: 'hello-tabs', key: 'count' }, 0)
779 791
780// Nell'hook ui.render: leggi il valore per disegnarlo792// In the ui.render hook: read the value to draw it
781const n = await read($, count)793const n = await read($, count)
782 794
783// In un Button: scrivi un nuovo valore dal vecchio795// In a Button: write a new value from the old one
784onPress: () => update($, count, (value) => value + 1)796onPress: () => update($, count, (value) => value + 1)
785```797```
786 798
787Perché l'hook `ui.render` ha letto `count`, Claude Code esegue l'hook di nuovo ogni volta che il pulsante lo scrive.799Poiché l'hook `ui.render` ha letto `count`, Claude Code esegue di nuovo l'hook ogni volta che il pulsante lo scrive.
788 800
789Tre regole si applicano al codice:801Al codice si applicano queste regole:
790 802
791* **Scrivi `plugin` e `key` come stringhe letterali**: `claude plugin validate` le legge dal tuo sorgente803* **Scrivi `plugin` e `key` come stringhe letterali**: `claude plugin validate` li legge dal tuo codice sorgente
792* **Dichiara ogni valore nel file di tipi**: altrimenti la validazione fallisce con `hello-tabs.count is not declared`804* **Dichiara ogni valore nel file di dichiarazione dei tipi**: altrimenti la validazione fallisce con `hello-tabs.count is not declared`
793* **Scrivi da un callback o dall'hook di un altro evento**: un hook `ui.render` può leggere lo stato e non può scriverlo, quindi scrivi da `onPress`, `onSubmit`, o un hook per un altro evento805* **Scrivi da una callback o dall'hook di un altro evento**: un hook `ui.render` può leggere lo stato ma non può scriverlo, quindi scrivi da `onPress`, `onSubmit` o da un hook per un altro evento
794 806
795<h4 id="change-hello-tabs-to-use-state">807<h4 id="change-hello-tabs-to-use-$-state">
796 Cambiare `hello-tabs` per usare `$.state`808 Modificare `hello-tabs` per usare `$.state`
797</h4>809</h4>
798 810
799Per spostare `count` in `hello-tabs` in `$.state`, cambia ogni riga che lo usa:811Per spostare `count` di `hello-tabs` in `$.state`, modifica ogni riga che lo usa:
800 812
801* **In cima al modulo**: aggiungi la riga `import`, e sostituisci `let count = 0` con la riga `atom`813* **In cima al modulo**: aggiungi la riga `import` e sostituisci `let count = 0` con la riga `atom`
802* **Nell'hook `ui.render`**: aggiungi la riga `read` prima di `tabButton`, e disegna `'Count: ' + n` nel `Text`814* **Nell'hook `ui.render`**: aggiungi la riga `read` prima di `tabButton` e disegna `'Count: ' + n` nel `Text`
803* **Nel pulsante Add one**: sostituisci `onPress` con quello in [Salvare da più di una sessione](#save-from-more-than-one-session), che salva il conteggio così come lo scrive815* **Nel pulsante Add one**: sostituisci `onPress` con quello in [Salvare da più di una sessione](#save-from-more-than-one-session), che salva il conteggio oltre a scriverlo
804* **Nell'hook `session.start`**: sostituisci le due righe che leggono `saved` con la chiamata `loadCount` da [Caricare un valore salvato di nuovo dopo `/clear`](#load-a-saved-value-again-after-clear)816* **Nell'hook `session.start`**: sostituisci le due righe che leggono `saved` con la chiamata a `loadCount` da [Caricare di nuovo un valore salvato dopo `/clear`](#load-a-saved-value-again-after-clear)
805 817
806Mantieni `redraw` per i pulsanti delle schede, perché `tab` è ancora una variabile.818Mantieni `redraw` per i pulsanti delle schede, perché `tab` è ancora una variabile.
807 819
808<h3 id="load-a-saved-value-again-after-clear">820<h3 id="load-a-saved-value-again-after-clear">
809 Caricare un valore salvato di nuovo dopo `/clear`821 Caricare di nuovo un valore salvato dopo `/clear`
810</h3>822</h3>
811 823
812Se il tuo mod copia un valore salvato da `$.store` in `$.state` a `session.start`, deve copiarlo di nuovo dopo `/clear`, `/resume`, o `/branch`. Questi comandi rimettono ogni valore `$.state` al suo default, e `session.start` non viene generato di nuovo. [`classic.SessionStart`](/docs/it/plugins/mods/events#hook-the-settings-hook-events) viene generato dopo ognuno di essi, con `e.source` impostato a `clear`, `resume`, o `fork`, quindi copia il valore di nuovo in un hook su di esso. Altrimenti il tuo disegno mostra il default, e un callback che salva il valore `$.state` scrive il default su quello che hai archiviato.824Se il tuo mod copia un valore salvato da `$.store` in `$.state` a `session.start`, deve copiarlo di nuovo dopo `/clear`, `/resume` o `/branch`. Questi comandi reimpostano ogni valore di `$.state` al suo valore predefinito, e `session.start` non viene attivato di nuovo. [`classic.SessionStart`](/docs/it/plugins/mods/events#hook-the-settings-hook-events) invece viene attivato dopo ciascuno di essi, con `e.source` impostato su `clear`, `resume` o `fork`, quindi copia di nuovo il valore in un hook su di esso. Altrimenti il tuo disegno mostra il valore predefinito, e una callback che salva il valore di `$.state` scrive il valore predefinito sopra quello che avevi memorizzato.
813 825
814Questo codice carica `count` da entrambi gli hook. Si basa sulla versione `$.state` di `hello-tabs`, dove `count` è un atom e `update` è importato. Metti `loadCount` sopra `register`, e aggiungi la chiamata `loadCount` all'hook `session.start` che hai già. `classic.SessionStart` viene generato anche all'avvio e dopo la compattazione, che non ripristina `$.state`, quindi il filtro su `source` mantiene l'hook ai tre ripristini:826Questo codice carica `count` da entrambi gli hook. Si basa sulla versione di `hello-tabs` con `$.state`, in cui `count` è un atom e `update` è importato. Metti `loadCount` sopra `register` e aggiungi la chiamata a `loadCount` all'hook `session.start` che hai già. `classic.SessionStart` viene attivato anche all'avvio e dopo la compattazione, che non reimposta `$.state`, quindi il filtro su `source` limita l'hook ai tre reset:
815 827
816```javascript theme={null}828```javascript theme={null}
817// Copia il conteggio salvato da $.store in $.state, o 0 se nulla è salvato829// Copy the saved count from $.store into $.state, or 0 if nothing is saved
818async function loadCount($) {830async function loadCount($) {
819 const saved = Number((await $.store.get('count')) ?? 0)831 const saved = Number((await $.store.get('count')) ?? 0)
820 await update($, count, () => saved)832 await update($, count, () => saved)
821}833}
822 834
823// Viene eseguito prima del tuo primo prompt, e di nuovo dopo un ricaricamento835// Runs before your first prompt, and again after a reload
824on('session.start', async ($, e, next) => {836on('session.start', async ($, e, next) => {
825 await loadCount($)837 await loadCount($)
826 return next(e)838 return next(e)
827})839})
828 840
829// Viene eseguito di nuovo dopo /clear, /resume, e /branch, che riporta fork841// Runs again after /clear, /resume, and /branch, which reports fork
830on('classic.SessionStart', { source: ['clear', 'resume', 'fork'] }, async ($, e, next) => {842on('classic.SessionStart', { source: ['clear', 'resume', 'fork'] }, async ($, e, next) => {
831 await loadCount($)843 await loadCount($)
832 return next(e)844 return next(e)
833})845})
834```846```
835 847
836Con entrambi gli hook in posizione, il riquadro mostra il conteggio salvato dopo `/clear` e non `0`, e la prossima pressione di **Add one** aggiunge al conteggio salvato.848Con entrambi gli hook in posizione, il riquadro mostra il conteggio salvato dopo `/clear` e non `0`, e la successiva pressione di **Add one** si aggiunge al conteggio salvato.
837 849
838`loadCount` scrive il valore archiviato su quello in `$.state`, e `session.start` viene generato di nuovo ogni volta che il modulo si ricarica. Per mantenere lo store dal rimanere indietro, salva ad ogni cambio, come il pulsante **Add one** fa.850`loadCount` scrive il valore memorizzato sopra quello in `$.state`, e `session.start` viene attivato di nuovo ogni volta che il modulo si ricarica. Per evitare che lo store rimanga indietro, salva a ogni modifica, come fa il pulsante **Add one**.
839 851
840Per controllare il ricaricamento senza una sessione, [testa il disegno dopo `/clear`](/docs/it/plugins/mods/test#test-a-drawing-after-clear).852Per verificare il ricaricamento senza una sessione, [testa il disegno dopo `/clear`](/docs/it/plugins/mods/test#test-a-drawing-after-clear).
841 853
842<h3 id="save-from-more-than-one-session">854<h3 id="save-from-more-than-one-session">
843 Salvare da più di una sessione855 Salvare da più di una sessione
844</h3>856</h3>
845 857
846Ogni sessione sulla tua macchina che esegue il tuo mod condivide uno `$.store`. Un `get` seguito da un `set` non è atomico. Quando due sessioni leggono ciascuna un valore, lo cambiano, e lo scrivono di nuovo, corrono, e la seconda scrittura sostituisce la prima.858Ogni sessione sulla tua macchina che esegue il tuo mod condivide un unico `$.store`. Un `get` seguito da un `set` non è atomico. Quando due sessioni leggono ciascuna un valore, lo modificano e lo riscrivono, entrano in competizione, e la seconda scrittura sostituisce la prima.
847 859
848Due scelte lo rendono meno probabile:860Per renderlo meno probabile:
849 861
850* **Dai a ogni elemento la sua chiave**: un `set` cambia solo la sua chiave, quindi le sessioni che scrivono chiavi diverse non si sovrascrivono a vicenda862* **Assegna a ogni elemento la propria chiave**: un `set` modifica solo la propria chiave, quindi le sessioni che scrivono chiavi diverse non si sovrascrivono a vicenda
851* **Leggi di nuovo subito prima di scrivere**: per un valore che più sessioni cambiano, `get` la chiave nel callback e costruisci il nuovo valore da quello, non da una copia che hai caricato a `session.start`. Un'altra scrittura della sessione è ancora persa se atterra tra il tuo `get` e il tuo `set`.863* **Rileggi subito prima di scrivere**: per un valore che più sessioni modificano, esegui `get` sulla chiave nella callback e costruisci il nuovo valore a partire da quello, non da una copia caricata a `session.start`. La scrittura di un'altra sessione va comunque persa se avviene tra il tuo `get` e il tuo `set`.
852 864
853Questo pulsante aggiunge uno a quello che lo store contiene ora, quindi aggiorna il disegno:865Questo pulsante aggiunge uno a qualunque valore lo store contenga in quel momento, poi aggiorna il disegno:
854 866
855```javascript theme={null}867```javascript theme={null}
856onPress: async () => {868onPress: async () => {
857 // Leggi quello che lo store contiene ora, che un'altra sessione potrebbe aver cambiato869 // Read what the store holds now, which another session may have changed
858 const saved = Number((await $.store.get('count')) ?? 0)870 const saved = Number((await $.store.get('count')) ?? 0)
859 // Salva il nuovo conteggio, quindi mostralo871 // Save the new count, then show it
860 await $.store.set('count', saved + 1)872 await $.store.set('count', saved + 1)
861 await update($, count, () => saved + 1)873 await update($, count, () => saved + 1)
862}874}
863```875```
864 876
865Se una seconda sessione ha premuto il suo pulsante tre volte da quando questa sessione è iniziata, questa pressione mostra e salva un conteggio che include quei tre.877Se una seconda sessione ha premuto il proprio pulsante tre volte dall'avvio di questa sessione, questa pressione mostra e salva un conteggio che include quelle tre.
866 878
867<h2 id="next-steps">879<h2 id="next-steps">
868 Prossimi passi880 Passaggi successivi
869</h2>881</h2>
870 882
871* [Reagire agli eventi](/docs/it/plugins/mods/events): alimenta il tuo disegno da chiamate di strumenti e turni883* [Reagire agli eventi](/docs/it/plugins/mods/events): alimenta il tuo disegno dalle chiamate agli strumenti e dai turni
872* [Usare l'API dei mod](/docs/it/plugins/mods/api): alimenta il tuo disegno da timer e chiamate di modello884* [Usare l'API dei mod](/docs/it/plugins/mods/api): alimenta il tuo disegno da timer e chiamate al modello
873* [Testare un disegno](/docs/it/plugins/mods/test#test-a-drawing): premi i tuoi pulsanti da un test, su più di una superficie885* [Testare un disegno](/docs/it/plugins/mods/test#test-a-drawing): premi i tuoi pulsanti da un test, su più di una superficie
874* [Siti di rendering](/docs/it/plugins/mods/reference#render-sites) e [elementi](/docs/it/plugins/mods/reference#elements): le proprietà di ogni sito e le proprietà di ogni elemento886* [Punti di rendering](/docs/it/plugins/mods/reference#render-sites) ed [elementi](/docs/it/plugins/mods/reference#elements): le prop di ciascun punto e le prop di ciascun elemento