@massimo-cassandro/minimo 1.41.4 → 1.41.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +12 -12
  2. package/charts/src/node-helpers/create-svg-canvas-node.mjs +2 -2
  3. package/charts/src/node-helpers/svg-text-to-path.js +9 -9
  4. package/charts/src/rating-display/index.js +1 -1
  5. package/charts/src/rating-display/ratindDisplayAnimation.js +3 -3
  6. package/design-tokens/README.md +2 -2
  7. package/design-tokens/_src/_readme.md +26 -26
  8. package/dev-tools/README.md +16 -16
  9. package/dev-tools/create-favicons/README.md +31 -31
  10. package/dev-tools/create-favicons/src/create-ico.mjs +2 -2
  11. package/dev-tools/create-favicons/src/default-params.mjs +1 -1
  12. package/dev-tools/create-favicons/src/init.mjs +1 -1
  13. package/dev-tools/design-tokens-builder/README.md +102 -102
  14. package/dev-tools/design-tokens-builder/build-tokens-src/build-source-modes.mjs +85 -73
  15. package/dev-tools/design-tokens-builder/build-tokens-src/config.mjs +109 -85
  16. package/dev-tools/design-tokens-builder/build-tokens-src/formats/css.mjs +113 -90
  17. package/dev-tools/design-tokens-builder/build-tokens-src/formats/json.mjs +107 -95
  18. package/dev-tools/design-tokens-builder/build-tokens-src/legacy-tokens-parser.mjs +71 -64
  19. package/dev-tools/design-tokens-builder/build-tokens-src/light-dark.mjs +75 -65
  20. package/dev-tools/design-tokens-builder/build-tokens-src/merge-css.mjs +113 -102
  21. package/dev-tools/design-tokens-builder/build-tokens-src/platforms.mjs +36 -30
  22. package/dev-tools/design-tokens-builder/build-tokens-src/resolve-source-paths.mjs +15 -13
  23. package/dev-tools/design-tokens-builder/build-tokens-src/source-prefixes.mjs +44 -42
  24. package/dev-tools/design-tokens-builder/build-tokens-src/source-transforms.mjs +89 -83
  25. package/dev-tools/design-tokens-builder/build-tokens-src/token-rename-parser.mjs +99 -86
  26. package/dev-tools/design-tokens-builder/build-tokens-src/transforms.mjs +64 -48
  27. package/dev-tools/design-tokens-builder/build-tokens.mjs +80 -68
  28. package/dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs +103 -77
  29. package/dev-tools/design-tokens-builder/tokens-config-sample.mjs +275 -238
  30. package/dev-tools/find-orphan-css-classes/find-orphan-css-classes.mjs +2 -2
  31. package/dev-tools/starter-kit/source_files/app/CLAUDE.md +4 -2
  32. package/dev-tools/starter-kit/source_files/app/{css/index.css → index.css} +2 -2
  33. package/dev-tools/starter-kit/source_files/app/index.js +1 -1
  34. package/dev-tools/starter-kit/source_files/root/_sf/controller/ImgViewerController.php +3 -3
  35. package/dev-tools/starter-kit/source_files/root/_sf/controller/ViewerController.php +2 -2
  36. package/dev-tools/starter-kit/source_files/root/stylelint.config.mjs +1 -1
  37. package/dev-tools/starter-kit/source_files/root/webpack-config-modules/css-rules.mjs +1 -1
  38. package/dev-tools/starter-kit/source_files/root/webpack.config.mjs +15 -1
  39. package/dev-tools/starter-kit/webpack-config-upg.md +12 -0
  40. package/dev-tools/stylelint-config/README.md +7 -7
  41. package/dev-tools/svg-icons-tools/README.md +32 -32
  42. package/dev-tools/svg-icons-tools/src/config-manager.mjs +1 -1
  43. package/dev-tools/svg-icons-tools/src/default-config.mjs +118 -118
  44. package/dev-tools/svg-icons-tools/src/jsx-icon-file-builder.mjs +24 -24
  45. package/dev-tools/svg-icons-tools/src/parse-svg-filename.mjs +3 -3
  46. package/dev-tools/svg-icons-tools/src/parse-svg-files.mjs +1 -1
  47. package/dev-tools/svg-icons-tools/src/parse-svg-markup.mjs +4 -4
  48. package/dev-tools/svg-icons-tools/src/svg-to-jsx.mjs +2 -2
  49. package/dev-tools/svg-icons-tools/src/svg-to-optimized.mjs +2 -2
  50. package/dev-tools/svg-icons-tools/src/svg-to-symbols.mjs +2 -2
  51. package/dev-tools/upd@m/README.md +1 -1
  52. package/dev-tools/upd@m/index.mjs +1 -1
  53. package/dev-tools/update-version/README.md +9 -9
  54. package/package.json +1 -1
  55. package/snippets/unsplash-browser-app/README.md +1 -1
  56. package/snippets/unsplash-browser-app/unsplash-utilities.js +9 -9
  57. package/src/components/autocomplete/README.md +3 -3
  58. package/src/components/autocomplete/autocomplete-engine.js +75 -63
  59. package/src/components/autocomplete/check-autocomplete.js +3 -3
  60. package/src/components/dismiss-alerts.js +3 -3
  61. package/src/components/form-reset-submit.js +6 -6
  62. package/src/components/inner-nav/inner-nav.js +2 -2
  63. package/src/components/modal-alert/modal-alert.js +67 -65
  64. package/src/components/modal-alert/modal-alert.minimo.tokens.mjs +1 -1
  65. package/src/components/modal-popup/modal-popup.js +56 -56
  66. package/src/components/overlay/overlay.js +3 -3
  67. package/src/components/sf-macro/readme.md +1 -1
  68. package/src/components/sf-macro/sf-macro.js +27 -23
  69. package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +83 -79
  70. package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +44 -44
  71. package/src/components/snackbar/snackbar.js +19 -19
  72. package/src/components/spinner/spinner.js +3 -3
  73. package/src/components/unsplash-page/README.md +8 -8
  74. package/src/components/unsplash-page/fetch-unsplash-data.js +3 -3
  75. package/src/components/unsplash-page/unsplash-page.js +33 -33
  76. package/src/components/unsplash-page/unsplash-page.module.css +1 -1
  77. package/src/css/alerts.css +2 -2
  78. package/src/css/forms/forms.css +4 -4
  79. package/src/css/forms/validation.css +1 -1
  80. package/src/css/margin-padding-media.css +4 -4
  81. package/src/css/margin-padding.css +4 -4
  82. package/src/css/reset.css +11 -11
  83. package/src/icons/read-me.md +1 -1
  84. package/src/minimo.css +3 -3
  85. package/src/utilities/better-text-with-places.js +22 -22
  86. package/src/utilities/better-text.js +42 -35
  87. package/src/utilities/classnames.js +8 -8
  88. package/src/utilities/cookies.js +6 -6
  89. package/src/utilities/create-id.js +3 -3
  90. package/src/utilities/disable-btns-on-submit.js +2 -2
  91. package/src/utilities/dom-builder/dom-builder.js +89 -86
  92. package/src/utilities/dom-builder/domBuilderBasicSetup.js +9 -9
  93. package/src/utilities/dom-builder/parseDomString.js +23 -23
  94. package/src/utilities/dom-builder-helpers/README.md +2 -2
  95. package/src/utilities/dom-builder-helpers/form-tags.js +100 -100
  96. package/src/utilities/dom-builder-helpers/picture-tag.js +39 -39
  97. package/src/utilities/enable-submit-btns.js +1 -1
  98. package/src/utilities/escape-html.js +2 -2
  99. package/src/utilities/generate-pwd.js +4 -4
  100. package/src/utilities/linked-dates.js +13 -13
  101. package/src/utilities/parse-file-size.js +6 -6
  102. package/src/utilities/random-id.js +3 -3
  103. package/src/utilities/relative-date.js +40 -40
  104. package/src/utilities/sentence-case.js +1 -1
  105. package/src/utilities/strip-tags.js +1 -1
  106. package/src/utilities/title-case.js +1 -1
  107. package/src/utilities/truncate-string.js +5 -5
  108. package/src/utilities/validation-error-class.js +12 -12
  109. package/src/web-components/json-table/json-table-component.js +123 -121
  110. package/src/web-components/json-table/json-table-component.module.css +6 -6
  111. package/src/web-components/json-table/json-table.minimo.tokens.mjs +6 -6
  112. package/src/web-components/json-table/jt-docs/parametri.md +124 -0
  113. package/src/web-components/json-table/jt-docs.md +622 -0
  114. package/src/web-components/json-table/readme.md +3 -763
  115. package/src/web-components/json-table/src/cell-content.js +25 -25
  116. package/src/web-components/json-table/src/content-utils.js +21 -21
  117. package/src/web-components/json-table/src/data-types.js +32 -32
  118. package/src/web-components/json-table/src/defaults.js +230 -191
  119. package/src/web-components/json-table/src/get-data.js +55 -38
  120. package/src/web-components/json-table/src/icons.js +17 -17
  121. package/src/web-components/json-table/src/info-section.js +18 -18
  122. package/src/web-components/json-table/src/main-builder.js +45 -45
  123. package/src/web-components/json-table/src/pagination.js +32 -32
  124. package/src/web-components/json-table/src/parse-cols.js +18 -18
  125. package/src/web-components/json-table/src/parse-rows.js +17 -17
  126. package/src/web-components/json-table/src/resolve-params.js +53 -41
  127. package/src/web-components/json-table/src/search.js +13 -13
  128. package/src/web-components/json-table/src/sorting.js +20 -20
  129. package/src/web-components/json-table/src/table-body.js +13 -13
  130. package/src/web-components/json-table/src/table-builder.js +34 -34
  131. package/src/web-components/json-table/src/table-tfoot.js +8 -8
  132. package/src/web-components/json-table/src/table-thead.js +21 -21
  133. package/src/web-components/json-table/src/update-info.js +11 -11
  134. package/types/classes.d.ts +2 -2
  135. package/types/global.d.ts +18 -12
@@ -1,766 +1,6 @@
1
1
  # `<json-table>` – datatable da JSON
2
2
 
3
- **json-table** costruisce una tabella HTML da un array di dati JSON (inline o caricato via
4
- fetch), a partire da una definizione delle colonne (`cols`) e da un insieme di tipi di dato
5
- predefiniti ed estendibili, con ordinamento, ricerca e paginazione (lato client oppure, con
6
- `serverSide: true`, delegati al server). È un web component light DOM senza dipendenze esterne:
7
- può quindi essere stilizzato direttamente dal CSS del progetto in cui è utilizzato.
3
+ **json-table** costruisce una tabella HTML da un array di dati JSON (inline o caricato via fetch), a partire da una definizione delle colonne (`cols`) e da un insieme di tipi di dato predefiniti ed estendibili, con ordinamento, ricerca e paginazione (lato client oppure, con `serverSide: true`, delegati al server). È un web component light DOM senza dipendenze esterne: può quindi essere personalizzato direttamente dal CSS del progetto in cui è utilizzato.
8
4
 
9
- ## Installazione
10
-
11
- È sufficiente importare il file del componente (registra il custom element):
12
-
13
- ```javascript
14
- // solo registrazione del tag
15
- import '@massimo-cassandro/minimo/json-table';
16
-
17
- // oppure, se necessario eseguire metodi della classe (es. `setDefaults`):
18
- import { JsonTable } from '@massimo-cassandro/minimo/json-table';
19
- ```
20
-
21
- Il CSS (`json-table-component.module.css`) è importato dal componente stesso; le custom
22
- properties `--jt-*` sono definite in `json-table.minimo.tokens.mjs` e compilate in
23
- `custom-properties.css` da `build-tokens`. Le icone di default (booleani, ordinamento e
24
- paginazione) sono SVG di minimo importati con il suffisso `?inline` (gestito dalla configurazione
25
- webpack dello starter-kit).
26
-
27
- ### Tipi per gli script consumer
28
-
29
- Il file `types/global.d.ts` di minimo dichiara il tipo globale `JsonTable` e registra il tag
30
- `json-table` in `HTMLElementTagNameMap`: aggiungendolo all'`include` del proprio
31
- `jsconfig.json`/`tsconfig.json` (`"node_modules/@massimo-cassandro/minimo/types/global.d.ts"`)
32
- si ottiene il completamento dei metodi senza cast né import di tipo:
33
-
34
- ```javascript
35
- const el = document.querySelector('json-table'); // → JsonTable
36
- el.init({ ... });
37
-
38
- /** @type {JsonTable} */
39
- const other = document.createElement('json-table');
40
- ```
41
-
42
- ## Utilizzo da markup
43
-
44
- ```html
45
- <json-table
46
- jsonurl="/api/rows.json"
47
- caption="Utenti"
48
- perpage="10"
49
- cols='[
50
- { "key": "id", "dataType": "id" },
51
- { "key": "name", "title": "Nome", "render": "<a href=\"/users/[[id]]\">[[name]]</a>" },
52
- { "key": "amount", "title": "Importo", "dataType": "euro", "tfootRender": "@sum" },
53
- { "key": "active", "title": "Attivo", "dataType": "bool" }
54
- ]'
55
- tfoot="true"
56
- serverSide="true"
57
- ></json-table>
58
-
59
- <!-- dati inline (JSON serializzato) al posto di jsonurl -->
60
- <json-table
61
- data='[{"name":"Mario","city":"Roma"}, ...]'
62
- cols='[{ "key": "name", "title": "Nome" }, { "key": "city", "title": "Città" }]'
63
- search="false"
64
- ></json-table>
65
- ```
66
-
67
- I nomi degli attributi sono case-insensitive (`jsonurl` e `jsonUrl` sono equivalenti).
68
- Gli attributi booleani accettano i formati HTML idiomatici: `search` (presente senza valore),
69
- `search="true"`, `search="1"` → true; `search="false"`, `search="0"` → false. Gli attributi
70
- numerici (`perpage`, `paginationdelta`, `searchdebounce`) vengono convertiti in numero.
71
- I valori che iniziano con `[` o `{` vengono interpretati come JSON (un JSON malformato viene
72
- segnalato in console e ignorato).
73
-
74
- Da attributo non è possibile passare funzioni: per il rendering delle celle è disponibile la
75
- sintassi mustache-like `[[key]]` (vedi [`render`](#render)), per il footer gli aggregati
76
- predefiniti (`"@sum"`, ...).
77
-
78
- ## Utilizzo da script
79
-
80
- ```javascript
81
- const el = document.querySelector('json-table');
82
- // oppure: const el = document.createElement('json-table');
83
-
84
- el.init({
85
- jsonUrl: '/api/rows.json',
86
- caption: 'Utenti',
87
- cols: [
88
- { key: 'id', dataType: 'id' },
89
- { key: 'name', title: 'Nome', render: row => `<a href="/users/${row.id}">${row.name}</a>` },
90
- { key: 'amount', title: 'Importo', dataType: 'euro', tfootRender: '@sum' },
91
- { key: 'active', title: 'Attivo', dataType: 'bool' }
92
- ],
93
- tfoot: true
94
- });
95
-
96
- // dati inline al posto di jsonUrl (se presenti entrambi, `data` prevale)
97
- el.init({
98
- data: [{ name: 'Mario', city: 'Roma' }, ...],
99
- cols: [...]
100
- });
101
-
102
- // se appena creato, appendere dopo init():
103
- document.body.appendChild(el);
104
- ```
105
-
106
- ### Con `domBuilder`
107
-
108
- ```javascript
109
- domBuilder([
110
- {
111
- tag: 'json-table',
112
- attrs: { caption: 'Utenti' },
113
- callback: el => el.init({ jsonUrl: '/api/rows.json', cols: [...] })
114
- }
115
- ], container);
116
- ```
117
-
118
- ## Utilizzo misto – attributi HTML + script
119
-
120
- I parametri non inclusi in `init()` vengono letti dall'attributo HTML corrispondente:
121
-
122
- ```html
123
- <json-table caption="Utenti" search="false" cols='[...]'></json-table>
124
- ```
125
-
126
- ```javascript
127
- el.init({ jsonUrl: '/api/rows.json' }); // jsonUrl da script, caption, search e cols da attributo
128
- ```
129
-
130
- **Ordine di precedenza:** `init()` > attributo HTML > `JsonTable.setDefaults()` > default interno.
131
-
132
- Per ignorare esplicitamente un attributo e utilizzare il valore di default, utilizzare `null` nel config:
133
-
134
- ```javascript
135
- el.init({ jsonUrl: '/api/rows.json', search: null }); // search == default (true)
136
- ```
137
-
138
- I parametri oggetto `classes`, `labels`, `dataTypes` e `serverParams` vengono **uniti** ai default
139
- (merge a un livello), quindi ogni sorgente deve indicare solo le chiavi da sovrascrivere:
140
-
141
- ```javascript
142
- el.init({ classes: { table: 'table' } }); // le altre classi restano quelle di default
143
- ```
144
-
145
- ## Default di progetto – `JsonTable.setDefaults()`
146
-
147
- Imposta valori validi per tutte le istanze create successivamente, evitando di ripetere gli
148
- stessi parametri. Da invocare una sola volta, in uno script condiviso eseguito prima degli altri.
149
- I valori vengono uniti a quelli impostati in chiamate precedenti.
150
-
151
- ```javascript
152
- import { JsonTable } from '.../json-table-component.js';
153
-
154
- JsonTable.setDefaults({
155
- perPage: 50,
156
- classes: { searchInput: 'form-control', table: 'table' },
157
- labels: { searchPlaceholder: 'Cerca…', noRows: 'Nessun elemento' },
158
- infoText: (start, end, totRec, filteredRec) => `${filteredRec} di ${totRec} record`
159
- });
160
-
161
- JsonTable.getDefaults(); // default interni + default di progetto
162
- JsonTable.resetDefaults(); // azzera i default di progetto
163
- ```
164
-
165
- ## API dell'istanza
166
-
167
- | Metodo | Descrizione |
168
- |---|---|
169
- | `init(config)` | Avvia il componente (prima o dopo l'inserimento nel DOM) |
170
- | `reload(overrides)` | Ricarica i dati e ricostruisce la struttura, con eventuali parametri sovrascritti (`Promise`); ricerca, ordinamento e pagina vengono azzerati |
171
- | `destroy()` | Svuota il componente; `init()` può essere richiamato in seguito |
172
- | `goToPage(page)` | Mostra la pagina indicata (limitata all'intervallo disponibile) |
173
- | `setSort(key, dir)` | Ordina per la colonna `key` (`'asc'`, `'desc'`, oppure `null` per rimuovere l'ordinamento) e torna alla prima pagina |
174
- | `setSearch(term)` | Filtra le righe con il termine indicato (stringa vuota = nessun filtro) e torna alla prima pagina; l'input di ricerca viene aggiornato |
175
-
176
- In modalità server-side `goToPage`, `setSort` e `setSearch` generano una nuova richiesta.
177
-
178
- Proprietà disponibili dopo il caricamento:
179
-
180
- | Proprietà | Descrizione |
181
- |---|---|
182
- | `params` | parametri risolti |
183
- | `data` | righe grezze (array di oggetti; in modalità server-side solo quelle della pagina corrente) |
184
- | `cols` | colonne dopo il parsing (solo quelle visibili, con classi e tipo di dato risolti) |
185
- | `dataTypes` | mappa dei tipi di dato (predefiniti + personalizzati) |
186
- | `state` | stato del rendering: `totRec`, `filteredRec`, `rows`, `filtered`, `pageRows`, `searchTerm`, `sort` (`{ key, dir }` o `null`), `page`, `totPages` |
187
- | `elements` | elementi generati: `wrapper`, `infoOuter`, `info`, `resultInfo`, `searchInput`, `tableWrapper`, `table`, `thead`, `tbody`, `tfoot`, `tableFooter`, `caption`, `pagination` |
188
-
189
- ```javascript
190
- await el.reload({ jsonUrl: '/api/rows.json?anno=2025' });
191
- await el.reload({ data: [...] });
192
- el.setSort('name', 'desc');
193
- el.goToPage(3);
194
- ```
195
-
196
- ## Eventi
197
-
198
- Entrambi vengono emessi sull'elemento con `bubbles: true`; `event.detail.jsonTable` è l'istanza.
199
-
200
- | Evento | Quando | `event.detail` |
201
- |---|---|---|
202
- | `jt:ready` | al termine della costruzione e del primo rendering (nel microtask successivo, quindi un listener registrato subito dopo `init()` lo intercetta comunque) | `{ jsonTable }` |
203
- | `jt:update` | dopo ogni cambio pagina, ordinamento o ricerca (anche via API) | `{ jsonTable, reason }` con `reason` = `'page'`, `'sort'` o `'search'` |
204
-
205
- ```javascript
206
- el.addEventListener('jt:ready', e => console.log(e.detail.jsonTable.data));
207
- el.addEventListener('jt:update', e => console.log(e.detail.reason, e.detail.jsonTable.state.page));
208
- el.init({ jsonUrl: '/api/rows.json', cols: [...] });
209
- ```
210
-
211
- ## Parametri
212
-
213
- Tutti i parametri sono impostabili sia da attributo HTML che da `init()`. I valori di tipo
214
- funzione solo da `init()`.
215
-
216
- ```javascript
217
- {
218
- debug, // boolean – log in console di parametri, colonne, dati, stato ed
219
- // elementi generati. Default: false
220
-
221
- jsonUrl, // string – URL del JSON da caricare. Ignorato se `data` è presente.
222
- // Default: null
223
- jsonDataField, // string|null – chiave del JSON che contiene l'array delle righe
224
- // (es. 'data' per { data: [...] }); null o '' = la root del JSON è
225
- // l'array stesso. Default: 'data'
226
- totRecField, // string – chiave del JSON con il totale dei record (numerico); se
227
- // assente o non numerico il totale è la lunghezza dell'array.
228
- // Default: 'totRec'
229
- filteredRecField, // string – solo server-side: chiave del JSON con il numero di record
230
- // che soddisfano la ricerca corrente; se assente vale `totRecField`.
231
- // Default: 'filteredRec'
232
- data, // Array<Object> – righe inline; prevale su `jsonUrl`. Da attributo va
233
- // passato come stringa JSON ed è sempre inteso come array delle righe
234
- // (`jsonDataField` ignorato). Default: null
235
-
236
- cols, // ColDefinition[] – OBBLIGATORIO: definizione delle colonne (vedi
237
- // sotto). Se assente o vuoto viene segnalato un errore in console e
238
- // la tabella non viene generata
239
- dataTypes, // Object – tipi di dato personalizzati, uniti a quelli predefiniti
240
- // (vedi sotto). Default: {}
241
-
242
- caption, // string|Function – caption della tabella (testo o HTML), oppure
243
- // funzione che restituisce stringa o Node. Mostrata sotto la tabella
244
- // (vedi "Caption e paginazione"). Default: null
245
- search, // boolean – genera l'input di ricerca. Default: true
246
- searchDebounce, // number – ms di attesa dopo l'ultimo tasto prima di eseguire la
247
- // ricerca. Default: 300
248
-
249
- perPage, // number – righe per pagina; 0 = nessuna paginazione (tutte le righe,
250
- // nessuna navigazione). Default: 25
251
- paginationDelta, // number – pulsanti pagina mostrati a ciascun lato della pagina
252
- // corrente. Default: 2
253
- serverSide, // boolean – paginazione, ordinamento e ricerca delegati al server
254
- // (vedi "Modalità server-side"). Richiede `jsonUrl`. Default: false
255
- serverParams, // Object – nomi dei parametri di query string in modalità server-side,
256
- // uniti ai default (vedi sotto)
257
- initialSort, // { key, dir }|null – ordinamento applicato al caricamento, es.
258
- // { key: 'name', dir: 'asc' }. Default: null
259
-
260
- tfoot, // boolean – genera il tfoot (vedi `tfootRender` delle colonne).
261
- // Non disponibile in modalità server-side. Default: false
262
- updateFooterOnPageChange, // boolean – se true `tfootRender` riceve solo i record della pagina
263
- // corrente (subtotali di pagina) e il footer si aggiorna a ogni cambio
264
- // pagina; se false riceve l'intero set filtrato e si aggiorna solo al
265
- // cambio filtro. Default: false
266
- infoText, // string|Function|null – contenuto dell'area info: stringa mustache-like
267
- // con i segnaposto {start}, {end}, {totRec}, {filteredRec}, {page},
268
- // {totPages}, oppure funzione
269
- // (start, end, totRec, filteredRec, page, totPages) => string|Node.
270
- // null = viene usato `labels.info`. Default: null
271
- template, // Array – layout del contenitore principale (vedi "Template").
272
- // Default: [{ slot: 'infoSection' }, { slot: 'table' }]
273
-
274
- locale, // string – locale per numeri, date e confronto stringhe
275
- // nell'ordinamento. Default: 'it-IT'
276
- currency, // string – codice ISO 4217 usato dal tipo `currency`. Default: 'EUR'
277
- datesLocaleOpts, // Intl.DateTimeFormatOptions – parte data dei tipi date/datetime.
278
- // Default: { year: 'numeric', month: 'short', day: 'numeric' }
279
- timesLocaleOpts, // Intl.DateTimeFormatOptions – parte ora del tipo datetime.
280
- // Default: { hour12: false, hour: '2-digit', minute: '2-digit' }
281
- numbersLocaleOpts, // Intl.NumberFormatOptions – tipo num.
282
- // Default: { maximumFractionDigits: 2 }
283
- currPercLocaleOpts, // Intl.NumberFormatOptions – tipi currency/euro/perc/percDecimal.
284
- // Default: { minimumFractionDigits: 2, maximumFractionDigits: 2 }
285
-
286
- renderNullAs, // string|null – contenuto per i valori null/undefined. Default: '—'
287
- renderZeroAs, // string|null – se non null, contenuto per i valori numerici pari a
288
- // zero. Default: null
289
- renderNaNAs, // string|null – contenuto per i valori non numerici nei tipi numerici.
290
- // Default: '—'
291
-
292
- boolTrueIcon, // icona per i valori true (tipo bool).
293
- // Default: icona `check-bold` di minimo (Phosphor)
294
- boolFalseIcon, // icona per i valori false. Default: icona `x-bold`
295
- sortAscArrowIcon, // icona del pulsante di ordinamento, ordinamento asc attivo.
296
- // Default: icona `arrow-up`
297
- sortDescArrowIcon, // idem, ordinamento desc attivo. Default: icona `arrow-down`
298
- sortNoneArrowIcon, // idem, nessun ordinamento. Default: icona `arrows-down-up`
299
- paginationPrevIcon, // icona del pulsante "pagina precedente". Default: icona `caret-left`
300
- paginationNextIcon, // icona del pulsante "pagina successiva". Default: icona `caret-right`
301
- // Ogni icona può essere una stringa SVG/HTML (es. import `?inline`),
302
- // un Node, un oggetto domBuilder o una funzione che restituisce uno
303
- // di questi valori
304
-
305
- trCallback, // (tr, row, params) => void – callback invocata dopo il rendering di
306
- // ogni riga del body. Default: null
307
- tableId, // string – id del tag <table>. Default: null
308
-
309
- classes, // Object – classi consumer (vedi sotto), unite ai default
310
- labels // Object – testi (vedi sotto), uniti ai default
311
- }
312
- ```
313
-
314
- ### `classes`
315
-
316
- Nomi delle classi assegnate agli elementi generati. Le classi interne di layout (CSS module)
317
- vengono **sempre** applicate in aggiunta a queste; ogni valore sostituisce interamente il
318
- default della stessa chiave.
319
-
320
- ```javascript
321
- classes: {
322
- wrapper: null, // contenitore principale (<section>: info + tabella)
323
- infoOuter: null, // contenitore esterno della sezione info
324
- info: null, // sezione info (testo + ricerca)
325
- resultInfo: null, // contenitore del testo info
326
- search: null, // wrapper dell'input di ricerca
327
- searchInput: 'form-control form-control-sm', // input di ricerca
328
- tableWrapper: 'table-responsive', // div che racchiude la tabella
329
- table: 'table table-bordered', // tag <table>
330
- tableFooter: null, // barra sotto la tabella (caption + paginazione)
331
- caption: null, // contenitore della caption
332
- pagination: null, // <nav> della paginazione
333
- paginationBtn: 'btn-reset', // pulsanti della paginazione
334
- sortBtn: 'btn-reset', // pulsanti di ordinamento nei <th>
335
- empty: null, // cella unica mostrata in assenza di righe
336
- textStart: null, // allineamento inline-start (le celle minimo lo sono già)
337
- textCenter: 'text-center', // allineamento al centro
338
- textEnd: 'text-end', // allineamento inline-end
339
- nowrap: 'text-nowrap', // no-wrap
340
- numeric: 'text-numeric', // cifre tabulari (tipi numerici)
341
- boolCell: null, // classe aggiuntiva per tutte le celle di tipo bool
342
- boolTrue: null, // classe aggiuntiva per le celle bool con valore true
343
- boolFalse: null // classe aggiuntiva per le celle bool con valore false
344
- }
345
- ```
346
-
347
- Le classi di allineamento (`textEnd`, `textCenter`, `nowrap`, `numeric`) sono quelle usate dai
348
- tipi di dato predefiniti: modificandole si cambiano le classi di tutte le colonne di quel tipo.
349
-
350
- ### `labels`
351
-
352
- ```javascript
353
- labels: {
354
- loading: 'Caricamento dati…', // segnaposto di caricamento (visually hidden)
355
- searchPlaceholder: 'Cerca...', // placeholder dell'input di ricerca
356
- searchTitle: 'Cerca nella tabella', // attributo title dell'input
357
- searchAriaLabel: 'Filtra risultati', // aria-label dell'input
358
- info: 'Stai visualizzando le righe da {start} a {end}, su un totale di {filteredRec} record trovati',
359
- // template del testo info (vedi `infoText`)
360
- noRows: 'Nessun record trovato', // testo info e cella unica con set di dati vuoto
361
- noResults: 'Nessun risultato per la ricerca', // idem, con ricerca senza risultati
362
- sortAsc: 'Ordina questa colonna in senso ascendente (A → Z)', // title/aria-label del
363
- sortDesc: 'Ordina questa colonna in senso discendente (Z → A)', // pulsante di ordinamento:
364
- sortNone: 'Rimuovi l’ordinamento a questa colonna', // descrivono l'azione del
365
- // prossimo click
366
- paginationAriaLabel: 'Navigazione pagine', // aria-label del <nav>
367
- prevPage: 'Pagina precedente', // title/aria-label del pulsante precedente
368
- nextPage: 'Pagina successiva', // idem, successivo
369
- pageTitle: 'Vai a pagina {page}', // idem, pulsanti pagina
370
- currentPage: 'Pagina {page}, corrente' // idem, pagina corrente
371
- }
372
- ```
373
-
374
- I segnaposto di `labels.info` / `infoText`:
375
-
376
- | Segnaposto | Valore |
377
- |---|---|
378
- | `{start}` | indice (da 1) del primo record della pagina corrente, nel set filtrato |
379
- | `{end}` | indice dell'ultimo record della pagina corrente |
380
- | `{totRec}` | totale dei record non filtrati (dal JSON, vedi `totRecField`, o lunghezza dei dati) |
381
- | `{filteredRec}` | totale dei record dopo il filtro |
382
- | `{page}` | pagina corrente |
383
- | `{totPages}` | numero di pagine |
384
-
385
- I numeri vengono formattati secondo `locale`.
386
-
387
- ## Colonne – `cols`
388
-
389
- Parametro **obbligatorio**: array di oggetti, uno per colonna:
390
-
391
- ```javascript
392
- cols: [
393
- {
394
- key, // string – OBBLIGATORIO: chiave dell'oggetto riga (ammessa la notazione con
395
- // punto per valori annidati, es. 'owner.name')
396
- title, // contenuto del <th>: testo, HTML, Node, array domBuilder o funzione.
397
- // Nelle colonne ordinabili è il testo del pulsante. Default: la chiave
398
- dataType, // string – tipo di dato, una delle chiavi di `dataTypes`; `type` è un alias
399
- // equivalente. Default: 'string'
400
- render, // (row, tr, td) => contenuto | stringa mustache-like – vedi sotto. Default: null
401
- tfootRender, // (rows, td) => contenuto | aggregato '@…' | stringa statica – contenuto della
402
- // cella del tfoot (solo se `tfoot` è true). null = cella vuota. Default: null
403
- rowHeading, // boolean – se true la cella è un'intestazione di riga (th[scope=row]).
404
- // Default: false
405
- searchable, // boolean – abilita la ricerca sulla colonna. Default: true
406
- sortable, // boolean – abilita l'ordinamento sulla colonna. Default: true
407
- sortValue, // valore | row => valore – valore usato per l'ordinamento; prevale su quello
408
- // del tipo di dato. Default: non impostato (tipo di dato / valore grezzo)
409
- searchValue, // idem, per la ricerca. Default: non impostato
410
- condition, // boolean | params => boolean – se false la colonna non viene renderizzata.
411
- // Default: true
412
- headerClass, // string – classi del <th>, in sostituzione di quelle del tipo di dato
413
- cellClass // string – classi delle celle body/tfoot, in sostituzione di quelle del tipo.
414
- // Se solo una tra `headerClass` e `cellClass` è presente, l'altra assume lo
415
- // stesso valore. Default: null (classi del tipo di dato)
416
- },
417
- ...
418
- ]
419
- ```
420
-
421
- ### `render`
422
-
423
- Funzione con argomenti posizionali, tutti facoltativi:
424
-
425
- ```javascript
426
- render: (row, tr, td) => contenuto
427
- ```
428
-
429
- - `row` – l'oggetto dati della riga
430
- - `tr` – l'elemento `<tr>` della riga
431
- - `td` – l'elemento della cella (`<td>` o `<th scope="row">`)
432
-
433
- Il valore restituito è il contenuto della cella: testo, stringa HTML, numero, Node o array
434
- domBuilder. Casi particolari:
435
-
436
- - `undefined` (nessun `return`): la cella viene renderizzata dal tipo di dato, come se `render`
437
- non fosse definito. Utile per decorare soltanto `td`/`tr` (classi, attributi, `title`):
438
-
439
- ```javascript
440
- render: (row, tr, td) => { if (row.amount < 0) td.classList.add('text-danger'); }
441
- ```
442
-
443
- - `null`: viene mostrato `renderNullAs`
444
-
445
- Da attributo HTML (o da script, per i casi semplici) `render` può essere una stringa
446
- mustache-like: ogni segnaposto `[[key]]` viene sostituito con il valore corrispondente della
447
- riga (chiavi annidate ammesse; i valori null diventano `renderNullAs`):
448
-
449
- ```javascript
450
- render: '<a href="/users/[[id]]">[[owner.name]]</a>'
451
- ```
452
-
453
- Le stringhe HTML vengono inserite tramite la Sanitizer API (`Element.setHTML`, dove supportata):
454
- script, attributi handler di eventi e URL `javascript:` vengono rimossi, mentre `class`, `id`,
455
- `style` e `data-*` sono conservati.
456
-
457
- ### `tfootRender`
458
-
459
- Con `tfoot: true` ogni colonna produce una cella nel footer, il cui contenuto è dato da
460
- `tfootRender`:
461
-
462
- - funzione `(rows, td) => contenuto`, dove `rows` è l'intero set filtrato (oppure i soli record
463
- della pagina corrente se `updateFooterOnPageChange` è true)
464
- - uno degli aggregati predefiniti (vedi sotto)
465
- - qualsiasi altra stringa: contenuto statico (es. l'etichetta `'Totale'`)
466
- - `null`: cella vuota
467
-
468
- Aggregati predefiniti, calcolati sui valori **numerici** della colonna (i valori non numerici
469
- vengono ignorati) e, tranne `@count`, formattati dal tipo di dato della colonna (es. come valuta
470
- per `euro`, con `%` per `perc`):
471
-
472
- | Aggregato | Valore |
473
- |---|---|
474
- | `'@sum'` | somma |
475
- | `'@avg'` | media aritmetica |
476
- | `'@min'` | minimo |
477
- | `'@max'` | massimo |
478
- | `'@count'` | numero di valori numerici (formattato con `locale`, senza il tipo di dato) |
479
-
480
- Un aggregato non riconosciuto viene segnalato in console e produce una cella vuota. Le celle del
481
- footer ricevono le stesse classi (`cellClass`) delle celle del body.
482
-
483
- Il `tfoot` non è disponibile in modalità server-side (il componente riceve solo la pagina
484
- corrente, gli aggregati sarebbero parziali): se richiesto viene ignorato con un avviso in console.
485
-
486
- ## Tipi di dato – `dataTypes`
487
-
488
- Ogni colonna ha un tipo di dato (`dataType`, default `string`) che ne definisce classi, rendering
489
- e valori di ordinamento/ricerca. Tipi predefiniti:
490
-
491
- | Tipo | Descrizione | Classi delle celle |
492
- |---|---|---|
493
- | `string` | valore così com'è | – |
494
- | `num` | numero formattato con `numbersLocaleOpts` | `textEnd numeric nowrap` |
495
- | `id` | id numerico: valore grezzo, allineato a destra, non ricercabile | `textEnd numeric` |
496
- | `perc` | percentuale in scala 0–100, `currPercLocaleOpts` + `%` | `textEnd numeric nowrap` |
497
- | `percDecimal` | percentuale in scala 0–1 (moltiplicata per 100) | `textEnd numeric nowrap` |
498
- | `currency` | formato valuta `Intl` con `currency` | `textEnd numeric nowrap` |
499
- | `euro` | come `currency`, EUR forzato | `textEnd numeric nowrap` |
500
- | `date` | elemento `<time>`, `datesLocaleOpts`; accetta stringhe ISO, timestamp, `Date` e oggetti data Symfony | `textEnd nowrap` |
501
- | `datetime` | come `date`, con la parte ora (`timesLocaleOpts`): `<time><span class="[nowrap]">data</span> <small>ora</small></time>` | `textEnd nowrap` |
502
- | `bool` | icone `boolTrueIcon`/`boolFalseIcon` (accetta anche `1`/`0`, `'true'`/`'false'`); `null` → `renderNullAs`; non ordinabile né ricercabile | stili interni delle icone |
503
- | `email` | andate a capo facoltative attorno alla `@` | – |
504
-
505
- I tipi numerici applicano `renderNaNAs` ai valori non numerici e `renderZeroAs` (se impostato)
506
- agli zeri. Per tutti i tipi i valori `null`/`undefined` vengono resi come `renderNullAs`.
507
-
508
- ### Tipi personalizzati
509
-
510
- Il parametro `dataTypes` è unito ai tipi predefiniti: una chiave già esistente sovrascrive solo
511
- le proprietà indicate, una chiave nuova può estendere un tipo esistente con `inheritsFrom`.
512
-
513
- ```javascript
514
- dataTypes: {
515
- // modifica solo le classi del tipo predefinito `num`
516
- num: { cellClass: 'text-end fw-bold' },
517
-
518
- // nuovo tipo basato su `num` (stesse classi, ordinamento, ricerca e gestione NaN/zero)
519
- km: {
520
- inheritsFrom: 'num',
521
- render: (value, row, params) => `${value.toLocaleString(params.locale)} km`
522
- }
523
- }
524
- ```
525
-
526
- Proprietà di un tipo di dato (tutte facoltative):
527
-
528
- ```javascript
529
- {
530
- headerClass, // string – classi di default del <th>
531
- cellClass, // string – classi di default delle celle
532
- internalCellClass, // (value, row, params) => string – classi aggiunte sempre alle celle,
533
- // indipendentemente da `cellClass` (usato dal tipo `bool` per le icone)
534
- render, // (value, row, params) => contenuto – non invocato per i valori null
535
- sortValue, // (value, row, params) => valore per l'ordinamento
536
- searchValue, // (value, row, params) => stringa per la ricerca
537
- colDefaults, // Object – default forzati per le colonne di questo tipo
538
- // (es. { sortable: false }), comunque sovrascrivibili nella colonna
539
- inheritsFrom // string – solo tipi nuovi: tipo predefinito da estendere
540
- }
541
- ```
542
-
543
- A differenza del `render` di colonna (`(row, tr, td)`), il `render` del tipo di dato riceve per
544
- primo il **valore** della cella, perché il tipo è generico rispetto al campo.
545
-
546
- ## Ordinamento
547
-
548
- Ogni colonna con `sortable: true` (default; i tipi `bool` lo disattivano) ha un pulsante nel
549
- `<th>` che cicla tra nessun ordinamento → ascendente → discendente → nessuno; l'attributo
550
- `aria-sort` del `<th>` e l'icona riflettono lo stato, `title`/`aria-label` del pulsante
551
- descrivono l'azione del click successivo (`labels.sortAsc/sortDesc/sortNone`). È attivo un solo
552
- ordinamento per volta; il cambio di ordinamento riporta alla prima pagina.
553
-
554
- Lato client il confronto usa i valori precalcolati per ogni riga (`sortValue` di colonna, poi del
555
- tipo di dato, poi il valore grezzo): i valori vuoti (`null`, `''`, `NaN`) vanno sempre in coda,
556
- i numeri sono confrontati numericamente, il resto con `localeCompare` (`locale`, collazione
557
- numerica, insensibile a maiuscole e accenti). L'ordinamento è stabile.
558
-
559
- `initialSort: { key, dir }` applica un ordinamento al caricamento; `setSort(key, dir)` lo cambia
560
- via script.
561
-
562
- ## Ricerca
563
-
564
- L'input di ricerca (`search: true`) filtra le righe dopo `searchDebounce` ms dall'ultimo tasto:
565
- ogni parola del termine (separatore: spazi) deve essere contenuta nel testo di ricerca della riga,
566
- composto dai valori delle colonne `searchable` (`searchValue` di colonna, poi del tipo di dato,
567
- poi il valore grezzo), senza distinzione tra maiuscole e minuscole. La ricerca riporta alla prima
568
- pagina; `setSearch(term)` la imposta via script.
569
-
570
- ## Paginazione
571
-
572
- Con `perPage` > 0 (default 25) le righe vengono suddivise in pagine e sotto la tabella compare la
573
- navigazione: pulsanti precedente/successivo (icone `paginationPrevIcon`/`paginationNextIcon`),
574
- la prima e l'ultima pagina e `paginationDelta` pagine per lato della corrente, con puntini di
575
- sospensione per le pagine omesse. La navigazione è nascosta quando c'è una sola pagina.
576
- `perPage: 0` disattiva la paginazione (tutte le righe in un'unica pagina).
577
-
578
- `goToPage(page)` cambia pagina via script; `state.page`/`state.totPages` riportano lo stato.
579
-
580
- ### Caption e paginazione
581
-
582
- La caption è mostrata **sotto la tabella**, nella barra `tableFooter`, allineata a sinistra; a
583
- destra, nella stessa barra, la navigazione delle pagine. La caption non è un elemento
584
- `<caption>` (che dovrebbe stare dentro la tabella e non potrebbe ospitare la navigazione senza
585
- farla leggere come nome della tabella) ma un contenitore con id, collegato alla tabella tramite
586
- `aria-labelledby`: il nome accessibile della tabella è quindi lo stesso di una `<caption>`.
587
- Posizioni diverse si ottengono con gli slot `caption` e `pagination` del [template](#template).
588
-
589
- ## Modalità server-side
590
-
591
- Con `serverSide: true` il componente non elabora i dati in locale: a ogni cambio pagina,
592
- ordinamento o ricerca invia una nuova richiesta GET a `jsonUrl`, aggiungendo alla query string i
593
- parametri definiti in `serverParams` (quelli già presenti in `jsonUrl` vengono conservati):
594
-
595
- ```javascript
596
- serverParams: {
597
- page: 'page', // pagina richiesta (da 1)
598
- start: 'start', // indice (da 0) del primo record richiesto = (page - 1) * perPage,
599
- // comodo per `LIMIT start, perPage`
600
- perPage: 'perPage', // record per pagina
601
- sort: 'sort', // chiave della colonna ordinata (omesso senza ordinamento)
602
- dir: 'dir', // 'asc' | 'desc' (omesso senza ordinamento)
603
- search: 'search' // termine di ricerca (omesso se vuoto)
604
- }
605
- ```
606
-
607
- Un valore `null` omette il parametro (es. `serverParams: { start: null }` per inviare solo `page`).
608
- Richiesta di esempio, seconda pagina ordinata per nome con ricerca attiva:
609
-
610
- ```
611
- GET /api/rows.json?page=2&start=25&perPage=25&sort=name&dir=desc&search=mar
612
- ```
613
-
614
- Il JSON di risposta deve contenere le **sole righe della pagina richiesta** in `jsonDataField`,
615
- il totale dei record in `totRecField` e il numero di record che soddisfano la ricerca in
616
- `filteredRecField` (se assente vale il totale):
617
-
618
- ```json
619
- { "data": [ ...25 righe... ], "totRec": 1500, "filteredRec": 40 }
620
- ```
621
-
622
- Durante la richiesta il contenitore principale ha `aria-busy="true"` (la tabella viene resa
623
- semitrasparente); le risposte superate da una richiesta più recente vengono ignorate. Se la
624
- pagina richiesta non esiste più (il set di dati si è ridotto), viene richiesta l'ultima
625
- disponibile. In questa modalità `data`, `filtered` e `pageRows` dello stato contengono solo la
626
- pagina corrente e il `tfoot` non è disponibile. `serverSide` richiede `jsonUrl`: con `data` inline
627
- viene ignorato con un avviso in console.
628
-
629
- ## Template
630
-
631
- `template` definisce il contenuto del contenitore principale come array domBuilder, in cui gli
632
- elementi `{ slot: 'nome' }` vengono sostituiti dalle parti predefinite:
633
-
634
- | Slot | Contenuto |
635
- |---|---|
636
- | `infoSection` | sezione info completa (testo info + input di ricerca, in riga) |
637
- | `resultInfo` | solo il testo info |
638
- | `search` | solo l'input di ricerca (se `search` è true) |
639
- | `table` | wrapper + tabella (thead, tbody, tfoot) e barra `tableFooter` con caption e paginazione |
640
- | `caption` | solo la caption (se `caption` è impostata) |
641
- | `pagination` | solo la navigazione delle pagine (se `perPage` > 0) |
642
-
643
- `caption` e `pagination` fanno parte della barra sotto la tabella dello slot `table`; se il
644
- template li colloca esplicitamente altrove, vengono rimossi dalla barra (che sparisce se resta
645
- vuota).
646
-
647
- Il default `[{ slot: 'infoSection' }, { slot: 'table' }]` corrisponde alla struttura descritta
648
- in [Struttura generata](#struttura-generata). Esempio con ricerca e paginazione sopra la tabella
649
- e info sotto:
650
-
651
- ```javascript
652
- template: [
653
- { className: 'flex gap-2 mbe-sm', children: [{ slot: 'search' }, { slot: 'pagination' }] },
654
- { slot: 'table' }, // barra sotto la tabella con la sola caption
655
- { slot: 'resultInfo' }
656
- ]
657
- ```
658
-
659
- Da `init()` è accettata anche una funzione `(parts, params) => array`, dove `parts` contiene le
660
- parti predefinite (oggetti domBuilder) con le stesse chiavi degli slot. Gli slot non
661
- riconosciuti vengono segnalati in console e ignorati.
662
-
663
- ## Struttura generata
664
-
665
- ```html
666
- <json-table>
667
- <section class="[wrapper] [classes.wrapper]">
668
- <div class="[infoOuter] [classes.infoOuter]">
669
- <div class="[info] [classes.info]">
670
- <div class="[resultInfo] [classes.resultInfo]" aria-live="polite">Stai visualizzando le righe da 1 a 25, ...</div>
671
- <div class="[search] [classes.search]"> <!-- solo se search: true -->
672
- <input type="search" class="form-control form-control-sm" ...>
673
- </div>
674
- </div>
675
- </div>
676
- <div class="[tableOuter]">
677
- <div class="[tableWrapper] table-responsive"> <!-- classes.tableWrapper -->
678
- <table class="[table] table table-bordered" aria-labelledby="jt-1-caption"> <!-- classes.table; aria-labelledby solo se caption -->
679
- <thead>
680
- <tr>
681
- <th scope="col" data-key="name" data-sortable="true" class="[sortable] ..." aria-sort="ascending">
682
- <button type="button" class="[sortBtn] btn-reset" title="Ordina ..." aria-label="Nome: Ordina ...">
683
- <span class="[sortTitle]">Nome</span>
684
- <span class="[sortIcon]" aria-hidden="true"><svg ...></svg></span>
685
- </button>
686
- </th>
687
- <th scope="col" data-key="active" class="text-center">Attivo</th> <!-- non ordinabile -->
688
- </tr>
689
- </thead>
690
- <tbody>
691
- <tr data-jt-idx="0">
692
- <th scope="row" data-key="id" class="text-end text-numeric">1</th> <!-- rowHeading -->
693
- <td data-key="name">Mario</td>
694
- <td data-key="active" class="[boolCell] [boolTrue]"><svg ...></svg></td>
695
- </tr>
696
- <!-- oppure, senza righe: -->
697
- <tr><td colspan="3" class="[empty] [classes.empty]">Nessun record trovato</td></tr>
698
- </tbody>
699
- <tfoot> <!-- solo se tfoot: true -->
700
- <tr><td data-key="id"></td><td data-key="name">Totale</td>...</tr>
701
- </tfoot>
702
- </table>
703
- </div>
704
- <div class="[tableFooter] [classes.tableFooter]"> <!-- solo se caption o perPage > 0 -->
705
- <div class="[caption] [classes.caption]" id="jt-1-caption">Utenti</div> <!-- solo se caption -->
706
- <nav class="[pagination] [classes.pagination]" aria-label="Navigazione pagine"> <!-- solo se perPage > 0; hidden con una sola pagina -->
707
- <ul class="[paginationList]">
708
- <li class="[paginationItem]"><button type="button" class="[paginationBtn] btn-reset [paginationArrow]" data-page="prev" aria-label="Pagina precedente" disabled><svg ...></svg></button></li>
709
- <li class="[paginationItem]"><button type="button" class="[paginationBtn] btn-reset" data-page="1" aria-current="page" aria-label="Pagina 1, corrente">1</button></li>
710
- <li class="[paginationItem]"><button type="button" class="[paginationBtn] btn-reset" data-page="2" aria-label="Vai a pagina 2">2</button></li>
711
- <li class="[paginationItem]"><span class="[paginationEllipsis]" aria-hidden="true">…</span></li>
712
- <li class="[paginationItem]"><button type="button" class="[paginationBtn] btn-reset" data-page="10" aria-label="Vai a pagina 10">10</button></li>
713
- <li class="[paginationItem]"><button type="button" class="[paginationBtn] btn-reset [paginationArrow]" data-page="next" aria-label="Pagina successiva"><svg ...></svg></button></li>
714
- </ul>
715
- </nav>
716
- </div>
717
- </div>
718
- </section>
719
- </json-table>
720
- ```
721
-
722
- Le classi tra parentesi quadre sono quelle interne del CSS module. Nei `<th>` ordinabili
723
- l'attributo `aria-sort` (`ascending`/`descending`) è presente solo sulla colonna ordinata;
724
- `title` e `aria-label` del pulsante descrivono l'azione del click successivo.
725
-
726
- ## Custom properties CSS
727
-
728
- Definite in `json-table.minimo.tokens.mjs` (namespace `--jt-*`):
729
-
730
- | Proprietà | Default (token minimo) |
731
- |---|---|
732
- | `--jt-wrapper-margin-block` | `{size.md}` |
733
- | `--jt-busy-opacity` | `.5` |
734
- | `--jt-info-gap` | `{size.sm}` |
735
- | `--jt-info-font-size` | `{font.size.sm}` |
736
- | `--jt-info-color` | `{text.muted}` |
737
- | `--jt-info-outer-padding-block-end` | `{size.xs}` |
738
- | `--jt-search-max-width` | `20rem` |
739
- | `--jt-thead-hover-background-color` | `color-mix(in srgb, {table.thead.background.color} 90%, {accent})` |
740
- | `--jt-sort-btn-padding-block` | `{table.cell.padding.block}` |
741
- | `--jt-sort-btn-padding-inline` | `{table.cell.padding.inline}` |
742
- | `--jt-sort-btn-line-height` | `{table.cell.line-height}` |
743
- | `--jt-sort-icon-size` | `1em` |
744
- | `--jt-sort-icon-gap` | `.4em` |
745
- | `--jt-sort-icon-none-opacity` | `.4` |
746
- | `--jt-table-footer-padding-block-start` | `{size.xs}` |
747
- | `--jt-caption-font-size` | `{font.size.sm}` |
748
- | `--jt-caption-color` | `{text.muted}` |
749
- | `--jt-pagination-border-width` | `1px` |
750
- | `--jt-pagination-border-color` | `{table.border.color}` |
751
- | `--jt-pagination-radius` | `{radius.xxs}` |
752
- | `--jt-pagination-font-size` | `{font.size.sm}` |
753
- | `--jt-pagination-line-height` | `{table.cell.line-height}` |
754
- | `--jt-pagination-btn-min-width` | `2.2em` |
755
- | `--jt-pagination-btn-padding-block` | `{table.cell.padding.block}` |
756
- | `--jt-pagination-btn-padding-inline` | `{table.cell.padding.inline}` |
757
- | `--jt-pagination-icon-size` | `1em` |
758
- | `--jt-pagination-current-background-color` | `{table.thead.background.color}` |
759
- | `--jt-pagination-current-font-weight` | `{font.weight.semibold}` |
760
- | `--jt-pagination-hover-background-color` | `{table.body.tr.hover-bg-color}` |
761
- | `--jt-pagination-disabled-opacity` | `.5` |
762
- | `--jt-bool-icon-size` | `1.1em` |
763
- | `--jt-bool-true-color` | `{status.success.color}` |
764
- | `--jt-bool-false-color` | `{status.danger.color}` |
765
- | `--jt-empty-color` | `{text.muted}` |
766
- | `--jt-empty-padding-block` | `{size.sm}` |
5
+
6
+ [Documentazione](jt-docs.md)