@massimo-cassandro/minimo 1.41.4 → 1.41.5
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.
- package/README.md +12 -12
- package/charts/src/node-helpers/create-svg-canvas-node.mjs +2 -2
- package/charts/src/node-helpers/svg-text-to-path.js +9 -9
- package/charts/src/rating-display/index.js +1 -1
- package/charts/src/rating-display/ratindDisplayAnimation.js +3 -3
- package/design-tokens/README.md +2 -2
- package/design-tokens/_src/_readme.md +26 -26
- package/dev-tools/README.md +16 -16
- package/dev-tools/create-favicons/README.md +31 -31
- package/dev-tools/create-favicons/src/create-ico.mjs +2 -2
- package/dev-tools/create-favicons/src/default-params.mjs +1 -1
- package/dev-tools/create-favicons/src/init.mjs +1 -1
- package/dev-tools/design-tokens-builder/README.md +102 -102
- package/dev-tools/design-tokens-builder/build-tokens-src/build-source-modes.mjs +85 -73
- package/dev-tools/design-tokens-builder/build-tokens-src/config.mjs +109 -85
- package/dev-tools/design-tokens-builder/build-tokens-src/formats/css.mjs +113 -90
- package/dev-tools/design-tokens-builder/build-tokens-src/formats/json.mjs +107 -95
- package/dev-tools/design-tokens-builder/build-tokens-src/legacy-tokens-parser.mjs +71 -64
- package/dev-tools/design-tokens-builder/build-tokens-src/light-dark.mjs +75 -65
- package/dev-tools/design-tokens-builder/build-tokens-src/merge-css.mjs +113 -102
- package/dev-tools/design-tokens-builder/build-tokens-src/platforms.mjs +36 -30
- package/dev-tools/design-tokens-builder/build-tokens-src/resolve-source-paths.mjs +15 -13
- package/dev-tools/design-tokens-builder/build-tokens-src/source-prefixes.mjs +44 -42
- package/dev-tools/design-tokens-builder/build-tokens-src/source-transforms.mjs +89 -83
- package/dev-tools/design-tokens-builder/build-tokens-src/token-rename-parser.mjs +99 -86
- package/dev-tools/design-tokens-builder/build-tokens-src/transforms.mjs +64 -48
- package/dev-tools/design-tokens-builder/build-tokens.mjs +80 -68
- package/dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs +103 -77
- package/dev-tools/design-tokens-builder/tokens-config-sample.mjs +275 -238
- package/dev-tools/find-orphan-css-classes/find-orphan-css-classes.mjs +2 -2
- package/dev-tools/starter-kit/source_files/app/CLAUDE.md +4 -2
- package/dev-tools/starter-kit/source_files/app/{css/index.css → index.css} +2 -2
- package/dev-tools/starter-kit/source_files/app/index.js +1 -1
- package/dev-tools/starter-kit/source_files/root/_sf/controller/ImgViewerController.php +3 -3
- package/dev-tools/starter-kit/source_files/root/_sf/controller/ViewerController.php +2 -2
- package/dev-tools/starter-kit/source_files/root/stylelint.config.mjs +1 -1
- package/dev-tools/starter-kit/source_files/root/webpack-config-modules/css-rules.mjs +1 -1
- package/dev-tools/stylelint-config/README.md +7 -7
- package/dev-tools/svg-icons-tools/README.md +32 -32
- package/dev-tools/svg-icons-tools/src/config-manager.mjs +1 -1
- package/dev-tools/svg-icons-tools/src/default-config.mjs +118 -118
- package/dev-tools/svg-icons-tools/src/jsx-icon-file-builder.mjs +24 -24
- package/dev-tools/svg-icons-tools/src/parse-svg-filename.mjs +3 -3
- package/dev-tools/svg-icons-tools/src/parse-svg-files.mjs +1 -1
- package/dev-tools/svg-icons-tools/src/parse-svg-markup.mjs +4 -4
- package/dev-tools/svg-icons-tools/src/svg-to-jsx.mjs +2 -2
- package/dev-tools/svg-icons-tools/src/svg-to-optimized.mjs +2 -2
- package/dev-tools/svg-icons-tools/src/svg-to-symbols.mjs +2 -2
- package/dev-tools/upd@m/README.md +1 -1
- package/dev-tools/upd@m/index.mjs +1 -1
- package/dev-tools/update-version/README.md +9 -9
- package/package.json +1 -1
- package/snippets/unsplash-browser-app/README.md +1 -1
- package/snippets/unsplash-browser-app/unsplash-utilities.js +9 -9
- package/src/components/autocomplete/README.md +3 -3
- package/src/components/autocomplete/autocomplete-engine.js +75 -63
- package/src/components/autocomplete/check-autocomplete.js +3 -3
- package/src/components/dismiss-alerts.js +3 -3
- package/src/components/form-reset-submit.js +6 -6
- package/src/components/inner-nav/inner-nav.js +2 -2
- package/src/components/modal-alert/modal-alert.js +67 -65
- package/src/components/modal-alert/modal-alert.minimo.tokens.mjs +1 -1
- package/src/components/modal-popup/modal-popup.js +56 -56
- package/src/components/overlay/overlay.js +3 -3
- package/src/components/sf-macro/readme.md +1 -1
- package/src/components/sf-macro/sf-macro.js +27 -23
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +83 -79
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +44 -44
- package/src/components/snackbar/snackbar.js +19 -19
- package/src/components/spinner/spinner.js +3 -3
- package/src/components/unsplash-page/README.md +8 -8
- package/src/components/unsplash-page/fetch-unsplash-data.js +3 -3
- package/src/components/unsplash-page/unsplash-page.js +33 -33
- package/src/components/unsplash-page/unsplash-page.module.css +1 -1
- package/src/css/alerts.css +2 -2
- package/src/css/forms/forms.css +4 -4
- package/src/css/forms/validation.css +1 -1
- package/src/css/margin-padding-media.css +4 -4
- package/src/css/margin-padding.css +4 -4
- package/src/css/reset.css +11 -11
- package/src/icons/read-me.md +1 -1
- package/src/minimo.css +3 -3
- package/src/utilities/better-text-with-places.js +22 -22
- package/src/utilities/better-text.js +42 -35
- package/src/utilities/classnames.js +8 -8
- package/src/utilities/cookies.js +6 -6
- package/src/utilities/create-id.js +3 -3
- package/src/utilities/disable-btns-on-submit.js +2 -2
- package/src/utilities/dom-builder/dom-builder.js +89 -86
- package/src/utilities/dom-builder/domBuilderBasicSetup.js +9 -9
- package/src/utilities/dom-builder/parseDomString.js +23 -23
- package/src/utilities/dom-builder-helpers/README.md +2 -2
- package/src/utilities/dom-builder-helpers/form-tags.js +100 -100
- package/src/utilities/dom-builder-helpers/picture-tag.js +39 -39
- package/src/utilities/enable-submit-btns.js +1 -1
- package/src/utilities/escape-html.js +2 -2
- package/src/utilities/generate-pwd.js +4 -4
- package/src/utilities/linked-dates.js +13 -13
- package/src/utilities/parse-file-size.js +6 -6
- package/src/utilities/random-id.js +3 -3
- package/src/utilities/relative-date.js +40 -40
- package/src/utilities/sentence-case.js +1 -1
- package/src/utilities/strip-tags.js +1 -1
- package/src/utilities/title-case.js +1 -1
- package/src/utilities/truncate-string.js +5 -5
- package/src/utilities/validation-error-class.js +12 -12
- package/src/web-components/json-table/json-table-component.js +123 -121
- package/src/web-components/json-table/json-table-component.module.css +6 -6
- package/src/web-components/json-table/json-table.minimo.tokens.mjs +6 -6
- package/src/web-components/json-table/readme.md +72 -108
- package/src/web-components/json-table/src/cell-content.js +25 -25
- package/src/web-components/json-table/src/content-utils.js +21 -21
- package/src/web-components/json-table/src/data-types.js +32 -32
- package/src/web-components/json-table/src/defaults.js +230 -191
- package/src/web-components/json-table/src/get-data.js +55 -38
- package/src/web-components/json-table/src/icons.js +17 -17
- package/src/web-components/json-table/src/info-section.js +18 -18
- package/src/web-components/json-table/src/main-builder.js +45 -45
- package/src/web-components/json-table/src/pagination.js +32 -32
- package/src/web-components/json-table/src/parse-cols.js +18 -18
- package/src/web-components/json-table/src/parse-rows.js +17 -17
- package/src/web-components/json-table/src/resolve-params.js +53 -41
- package/src/web-components/json-table/src/search.js +13 -13
- package/src/web-components/json-table/src/sorting.js +20 -20
- package/src/web-components/json-table/src/table-body.js +13 -13
- package/src/web-components/json-table/src/table-builder.js +34 -34
- package/src/web-components/json-table/src/table-tfoot.js +8 -8
- package/src/web-components/json-table/src/table-thead.js +21 -21
- package/src/web-components/json-table/src/update-info.js +11 -11
- package/types/classes.d.ts +2 -2
- package/types/global.d.ts +18 -12
|
@@ -4,28 +4,30 @@
|
|
|
4
4
|
/** @typedef {import('./defaults.js').SortDef} SortDef */
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Risultato di `getData()`.
|
|
8
8
|
* @typedef {Object} DataResult
|
|
9
|
-
* @property {Array<Object>} rows -
|
|
10
|
-
* @property {number} totRec -
|
|
11
|
-
*
|
|
12
|
-
* @property {number} filteredRec -
|
|
13
|
-
* `params.filteredRecField`
|
|
9
|
+
* @property {Array<Object>} rows - L'array delle righe (solo la pagina richiesta, in modalità server-side)
|
|
10
|
+
* @property {number} totRec - Numero totale di record: il valore numerico di `params.totRecField` nel
|
|
11
|
+
* JSON recuperato, altrimenti `rows.length`
|
|
12
|
+
* @property {number} filteredRec - Numero di record che corrispondono alla ricerca corrente: il valore numerico di
|
|
13
|
+
* `params.filteredRecField` nel JSON recuperato (modalità server-side), altrimenti `totRec`
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Stato della richiesta in modalità server-side.
|
|
18
18
|
* @typedef {Object} ServerRequest
|
|
19
|
-
* @property {number} page -
|
|
20
|
-
* @property {number} perPage -
|
|
21
|
-
* @property {SortDef|null} sort -
|
|
22
|
-
* @property {string} search -
|
|
19
|
+
* @property {number} page - Pagina richiesta (da 1)
|
|
20
|
+
* @property {number} perPage - Righe per pagina
|
|
21
|
+
* @property {SortDef|null} sort - Ordinamento attivo, oppure null
|
|
22
|
+
* @property {string} search - Termine di ricerca ('' = nessuno)
|
|
23
|
+
* @property {Array<{key: string, searchable: boolean, sortable: boolean}>} [cols] - Colonne visualizzate (già analizzate);
|
|
24
|
+
* usate solo con `jqDatatableMode` per inviare `columns[i][...]` e l'indice della colonna ordinata
|
|
23
25
|
*/
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
|
-
*
|
|
27
|
-
* @param {*} json -
|
|
28
|
-
* @param {string|null|undefined} field -
|
|
28
|
+
* Legge un campo numerico del JSON recuperato; `undefined` se mancante o non numerico.
|
|
29
|
+
* @param {*} json - JSON recuperato
|
|
30
|
+
* @param {string|null|undefined} field - Chiave da leggere
|
|
29
31
|
* @returns {number|undefined}
|
|
30
32
|
*/
|
|
31
33
|
function numericField(json, field) {
|
|
@@ -39,13 +41,16 @@ function numericField(json, field) {
|
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
44
|
+
* Costruisce l'URL di una richiesta server-side: `params.jsonUrl` più i parametri della query string
|
|
45
|
+
* indicati in `params.serverParams` (i parametri impostati a `null` vengono omessi; `sort`/`dir` vengono inviati
|
|
46
|
+
* solo quando è attivo un ordinamento, `search` solo quando non è vuoto). I parametri della query string
|
|
47
|
+
* già presenti in `jsonUrl` vengono conservati.
|
|
46
48
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
+
* Con `params.jqDatatableMode` e `request.cols` vengono inviati anche, come fa jQuery DataTables, `draw=1`,
|
|
50
|
+
* `columns[i][name|searchable|orderable]` e, per `sort`, l'indice della colonna al posto della sua chiave.
|
|
51
|
+
*
|
|
52
|
+
* @param {JsonTableParams} params - Parametri risolti
|
|
53
|
+
* @param {ServerRequest} request - Stato della richiesta
|
|
49
54
|
* @returns {string}
|
|
50
55
|
*
|
|
51
56
|
* @example
|
|
@@ -60,7 +65,7 @@ export function buildServerUrl(params, request) {
|
|
|
60
65
|
const url = new URL(String(params.jsonUrl), document.baseURI);
|
|
61
66
|
const names = params.serverParams ?? {};
|
|
62
67
|
|
|
63
|
-
/** @type {(name: string|null|undefined, value: string|number|null|undefined) => void} */
|
|
68
|
+
/** @type {(name: string|null|undefined, value: string|number|boolean|null|undefined) => void} */
|
|
64
69
|
const set = (name, value) => {
|
|
65
70
|
if (name && value != null && value !== '') {
|
|
66
71
|
url.searchParams.set(name, String(value));
|
|
@@ -70,7 +75,19 @@ export function buildServerUrl(params, request) {
|
|
|
70
75
|
set(names.page, request.page);
|
|
71
76
|
set(names.start, (request.page - 1) * request.perPage);
|
|
72
77
|
set(names.perPage, request.perPage);
|
|
73
|
-
|
|
78
|
+
const jqCols = params.jqDatatableMode ? request.cols : null;
|
|
79
|
+
if (jqCols) {
|
|
80
|
+
set('draw', 1);
|
|
81
|
+
jqCols.forEach((col, idx) => {
|
|
82
|
+
set(`columns[${idx}][name]`, col.key);
|
|
83
|
+
set(`columns[${idx}][searchable]`, col.searchable);
|
|
84
|
+
set(`columns[${idx}][orderable]`, col.sortable);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
set(names.sort, jqCols && request.sort
|
|
89
|
+
? jqCols.findIndex(col => col.key === request.sort?.key)
|
|
90
|
+
: request.sort?.key);
|
|
74
91
|
set(names.dir, request.sort ? request.sort.dir : null);
|
|
75
92
|
set(names.search, request.search);
|
|
76
93
|
|
|
@@ -79,34 +96,34 @@ export function buildServerUrl(params, request) {
|
|
|
79
96
|
|
|
80
97
|
|
|
81
98
|
/**
|
|
82
|
-
*
|
|
99
|
+
* Recupera l'array delle righe dalla sorgente configurata.
|
|
83
100
|
*
|
|
84
|
-
* `data`
|
|
85
|
-
*
|
|
86
|
-
* JSON
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
101
|
+
* `data` ha la precedenza su `jsonUrl`. Con `jsonUrl` il JSON viene recuperato e le righe vengono
|
|
102
|
+
* lette dalla chiave `jsonDataField` (`null`/`''` = la radice del JSON è l'array stesso); quando il
|
|
103
|
+
* JSON contiene anche una chiave numerica `totRecField`, viene restituita come `totRec`, altrimenti `totRec` è
|
|
104
|
+
* la lunghezza dell'array delle righe. In modalità server-side (`request` indicato) l'URL porta i parametri di paginazione /
|
|
105
|
+
* ordinamento / ricerca (vedi `buildServerUrl`) e viene letto anche `filteredRecField`.
|
|
106
|
+
* Restituisce `null` quando non è configurata alcuna sorgente.
|
|
90
107
|
*
|
|
91
|
-
* @param {JsonTableParams} params -
|
|
92
|
-
* @param {ServerRequest|null} [request=null] -
|
|
93
|
-
* @returns {Promise<DataResult|null>}
|
|
94
|
-
* @throws {Error}
|
|
95
|
-
*
|
|
108
|
+
* @param {JsonTableParams} params - Parametri risolti (vedi `resolve-params.js`)
|
|
109
|
+
* @param {ServerRequest|null} [request=null] - Stato della richiesta server-side; `null` per una richiesta semplice (default: null)
|
|
110
|
+
* @returns {Promise<DataResult|null>} Righe e totali, oppure `null` quando non sono impostati né `data` né `jsonUrl`
|
|
111
|
+
* @throws {Error} Quando `data` non è un array, in caso di errori HTTP/di rete, oppure quando il JSON recuperato
|
|
112
|
+
* non contiene un array in `jsonDataField`
|
|
96
113
|
*
|
|
97
114
|
* @example
|
|
98
|
-
* // inline
|
|
115
|
+
* // dati inline (jsonUrl ignorato)
|
|
99
116
|
* await getData({ ...params, data: [{ id: 1 }], jsonUrl: '/ignored.json' });
|
|
100
117
|
* // → { rows: [{ id: 1 }], totRec: 1, filteredRec: 1 }
|
|
101
118
|
*
|
|
102
|
-
* //
|
|
119
|
+
* // JSON recuperato: { data: [...], totRec: 1500 } (jsonDataField default: 'data', totRecField default: 'totRec')
|
|
103
120
|
* await getData({ ...params, jsonUrl: '/api/rows.json' });
|
|
104
121
|
*
|
|
105
|
-
* //
|
|
122
|
+
* // JSON recuperato la cui radice è l'array stesso
|
|
106
123
|
* await getData({ ...params, jsonUrl: '/api/rows.json', jsonDataField: null });
|
|
107
124
|
*
|
|
108
125
|
* // server-side: GET /api/rows.json?page=2&start=25&perPage=25&search=mar
|
|
109
|
-
* //
|
|
126
|
+
* // JSON atteso: { data: [...25 righe], totRec: 1500, filteredRec: 40 }
|
|
110
127
|
* await getData({ ...params, jsonUrl: '/api/rows.json', serverSide: true }, { page: 2, perPage: 25, sort: null, search: 'mar' });
|
|
111
128
|
*/
|
|
112
129
|
export async function getData(params, request = null) {
|
|
@@ -10,41 +10,41 @@ import caretRight from '../../../icons/caret-right.svg?inline';
|
|
|
10
10
|
|
|
11
11
|
/** @typedef {import('./defaults.js').IconDef} IconDef */
|
|
12
12
|
|
|
13
|
-
/**
|
|
13
|
+
/** Icona predefinita dei valori `true` (`check-bold` di minimo, markup SVG inline) */
|
|
14
14
|
export const boolTrueIcon = checkBold;
|
|
15
|
-
/**
|
|
15
|
+
/** Icona predefinita dei valori `false` (`x-bold` di minimo) */
|
|
16
16
|
export const boolFalseIcon = xBold;
|
|
17
|
-
/**
|
|
17
|
+
/** Icona predefinita del pulsante di ordinamento, ordinamento crescente attivo (`arrow-up` di minimo) */
|
|
18
18
|
export const sortAscArrowIcon = arrowUp;
|
|
19
|
-
/**
|
|
19
|
+
/** Icona predefinita del pulsante di ordinamento, ordinamento decrescente attivo (`arrow-down` di minimo) */
|
|
20
20
|
export const sortDescArrowIcon = arrowDown;
|
|
21
|
-
/**
|
|
21
|
+
/** Icona predefinita del pulsante di ordinamento, nessun ordinamento attivo (`arrows-down-up` di minimo) */
|
|
22
22
|
export const sortNoneArrowIcon = arrowsDownUp;
|
|
23
|
-
/**
|
|
23
|
+
/** Icona predefinita del pulsante pagina precedente (`caret-left` di minimo) */
|
|
24
24
|
export const paginationPrevIcon = caretLeft;
|
|
25
|
-
/**
|
|
25
|
+
/** Icona predefinita del pulsante pagina successiva (`caret-right` di minimo) */
|
|
26
26
|
export const paginationNextIcon = caretRight;
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Stringhe di markup già analizzate, indicizzate dalla stringa stessa.
|
|
30
30
|
* @type {Map<string, DocumentFragment>}
|
|
31
31
|
*/
|
|
32
32
|
const fragmentCache = new Map();
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Risolve la definizione di un'icona in un contenuto utilizzabile da domBuilder (`content`) o da `setContent()`.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
37
|
+
* Le stringhe di markup vengono analizzate una sola volta tramite un `<template>` inerte e clonate a ogni chiamata, così che la
|
|
38
|
+
* stessa icona possa essere inserita in molte celle senza nuova analisi e senza passare dal sanitizer HTML
|
|
39
|
+
* usato da domBuilder per le stringhe di markup (le icone sono configurazione fornita dallo sviluppatore,
|
|
40
|
+
* non dati dell'utente). Anche i nodi DOM vengono clonati, dato che un nodo può stare in un solo posto.
|
|
41
41
|
*
|
|
42
|
-
* @param {IconDef|null|undefined} icon -
|
|
43
|
-
* @returns {Node|DomBuilderItem[]|null}
|
|
42
|
+
* @param {IconDef|null|undefined} icon - Definizione dell'icona (vedi `IconDef`)
|
|
43
|
+
* @returns {Node|DomBuilderItem[]|null} Un nodo nuovo (o un array domBuilder), `null` quando `icon` è nullish
|
|
44
44
|
*
|
|
45
45
|
* @example
|
|
46
|
-
* iconContent('<svg …></svg>'); // → DocumentFragment (clone
|
|
47
|
-
* iconContent(document.querySelector('svg')); // →
|
|
46
|
+
* iconContent('<svg …></svg>'); // → DocumentFragment (clone del markup analizzato)
|
|
47
|
+
* iconContent(document.querySelector('svg')); // → SVGElement clonato
|
|
48
48
|
* iconContent({ tag: 'span', content: '✓' }); // → [{ tag: 'span', content: '✓' }] (domBuilder array)
|
|
49
49
|
* iconContent(() => '<svg …></svg>'); // → DocumentFragment
|
|
50
50
|
* iconContent(null); // → null
|
|
@@ -7,13 +7,13 @@ import { classnames } from '../../../utilities/classnames.js';
|
|
|
7
7
|
/** @typedef {import('./main-builder.js').JsonTableElements} JsonTableElements */
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* domBuilder
|
|
10
|
+
* Elemento domBuilder del contenitore del testo informativo (slot del template `resultInfo`).
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Struttura generata: `div.resultInfo[classes.resultInfo][aria-live=polite]`; il contenuto è
|
|
13
|
+
* impostato da `update-info.js`. L'elemento viene memorizzato in `elements.resultInfo`.
|
|
14
14
|
*
|
|
15
|
-
* @param {JsonTableParams} params -
|
|
16
|
-
* @param {JsonTableElements} elements -
|
|
15
|
+
* @param {JsonTableParams} params - Parametri risolti
|
|
16
|
+
* @param {JsonTableElements} elements - Oggetto che raccoglie gli elementi generati (modificato)
|
|
17
17
|
* @returns {DomBuilderItem}
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
@@ -30,21 +30,21 @@ export function resultInfoPart(params, elements) {
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* domBuilder
|
|
34
|
-
* `params.search`
|
|
33
|
+
* Elemento domBuilder dell'input di ricerca (slot del template `search`), renderizzato solo quando
|
|
34
|
+
* `params.search` è true.
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* Struttura generata: `div.search[classes.search] > input[type=search][classes.searchInput]`.
|
|
37
|
+
* L'input viene memorizzato in `elements.searchInput`.
|
|
38
38
|
*
|
|
39
39
|
* TODO listener sull'input di ricerca: step 3
|
|
40
40
|
*
|
|
41
|
-
* @param {JsonTableParams} params -
|
|
42
|
-
* @param {JsonTableElements} elements -
|
|
41
|
+
* @param {JsonTableParams} params - Parametri risolti
|
|
42
|
+
* @param {JsonTableElements} elements - Oggetto che raccoglie gli elementi generati (modificato)
|
|
43
43
|
* @returns {DomBuilderItem}
|
|
44
44
|
*
|
|
45
45
|
* @example
|
|
46
46
|
* domBuilder([searchPart(params, elements)], host);
|
|
47
|
-
* elements.searchInput; // → HTMLInputElement (
|
|
47
|
+
* elements.searchInput; // → HTMLInputElement (quando params.search è true)
|
|
48
48
|
*/
|
|
49
49
|
export function searchPart(params, elements) {
|
|
50
50
|
return {
|
|
@@ -68,21 +68,21 @@ export function searchPart(params, elements) {
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* domBuilder
|
|
71
|
+
* Elemento domBuilder dell'intera sezione informativa (slot del template `infoSection`): testo informativo + input di ricerca.
|
|
72
72
|
*
|
|
73
|
-
*
|
|
73
|
+
* Struttura generata:
|
|
74
74
|
* ```
|
|
75
75
|
* div.infoOuter[classes.infoOuter]
|
|
76
76
|
* div.info[classes.info]
|
|
77
77
|
* div.resultInfo ← resultInfoPart()
|
|
78
|
-
* div.search > input[type=search] ← searchPart(),
|
|
78
|
+
* div.search > input[type=search] ← searchPart(), solo se `params.search` è true
|
|
79
79
|
* ```
|
|
80
80
|
*
|
|
81
|
-
*
|
|
81
|
+
* I riferimenti agli elementi generati vengono memorizzati in `elements`
|
|
82
82
|
* (`infoOuter`, `info`, `resultInfo`, `searchInput`).
|
|
83
83
|
*
|
|
84
|
-
* @param {JsonTableParams} params -
|
|
85
|
-
* @param {JsonTableElements} elements -
|
|
84
|
+
* @param {JsonTableParams} params - Parametri risolti
|
|
85
|
+
* @param {JsonTableElements} elements - Oggetto che raccoglie gli elementi generati (modificato)
|
|
86
86
|
* @returns {DomBuilderItem}
|
|
87
87
|
*
|
|
88
88
|
* @example
|
|
@@ -13,25 +13,25 @@ import { paginationPart } from './pagination.js';
|
|
|
13
13
|
/** @typedef {import('./defaults.js').TemplateSlot} TemplateSlot */
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Elementi generati dal componente, raccolti durante la costruzione.
|
|
17
17
|
* @typedef {Object} JsonTableElements
|
|
18
|
-
* @property {HTMLElement} [wrapper] -
|
|
19
|
-
* @property {HTMLElement} [infoOuter] -
|
|
20
|
-
* @property {HTMLElement} [info] -
|
|
21
|
-
* @property {HTMLElement} [resultInfo] -
|
|
22
|
-
* @property {HTMLInputElement} [searchInput] -
|
|
23
|
-
* @property {HTMLElement} [tableWrapper] - Div
|
|
24
|
-
* @property {HTMLTableElement} [table] -
|
|
25
|
-
* @property {HTMLTableSectionElement} [thead] -
|
|
26
|
-
* @property {HTMLTableSectionElement} [tbody] -
|
|
27
|
-
* @property {HTMLTableSectionElement} [tfoot] -
|
|
28
|
-
* @property {HTMLElement} [tableFooter] -
|
|
29
|
-
* @property {HTMLElement} [caption] -
|
|
30
|
-
* @property {HTMLElement} [pagination] -
|
|
18
|
+
* @property {HTMLElement} [wrapper] - Wrapper principale (`section`), contiene le parti del template
|
|
19
|
+
* @property {HTMLElement} [infoOuter] - Contenitore esterno delle info
|
|
20
|
+
* @property {HTMLElement} [info] - Contenitore delle info (riga flex: testo informativo + ricerca)
|
|
21
|
+
* @property {HTMLElement} [resultInfo] - Contenitore del testo informativo
|
|
22
|
+
* @property {HTMLInputElement} [searchInput] - Input di ricerca (solo quando `search` è true)
|
|
23
|
+
* @property {HTMLElement} [tableWrapper] - Div che racchiude la tabella (`table-responsive` di default)
|
|
24
|
+
* @property {HTMLTableElement} [table] - L'elemento `<table>`
|
|
25
|
+
* @property {HTMLTableSectionElement} [thead] - L'elemento `<thead>`
|
|
26
|
+
* @property {HTMLTableSectionElement} [tbody] - L'elemento `<tbody>`
|
|
27
|
+
* @property {HTMLTableSectionElement} [tfoot] - L'elemento `<tfoot>` (solo quando `tfoot` è true)
|
|
28
|
+
* @property {HTMLElement} [tableFooter] - Barra del footer sotto la tabella (caption + paginazione), quando renderizzata
|
|
29
|
+
* @property {HTMLElement} [caption] - Contenitore della caption (solo quando `caption` è impostato)
|
|
30
|
+
* @property {HTMLElement} [pagination] - `<nav>` della paginazione (solo quando `perPage` > 0)
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Indica se un elemento del template è un segnaposto di slot.
|
|
35
35
|
* @param {*} item
|
|
36
36
|
* @returns {item is { slot: TemplateSlot }}
|
|
37
37
|
*/
|
|
@@ -41,10 +41,10 @@ function isSlot(item) {
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* Raccoglie, ricorsivamente (`children` e `content` array), i nomi degli slot usati da un template.
|
|
45
45
|
*
|
|
46
|
-
* @param {Array<TemplateItem|string|Node>} items -
|
|
47
|
-
* @param {Set<string>} [found=new Set()] -
|
|
46
|
+
* @param {Array<TemplateItem|string|Node>} items - Elementi del template
|
|
47
|
+
* @param {Set<string>} [found=new Set()] - Accumulatore (default: new Set())
|
|
48
48
|
* @returns {Set<string>}
|
|
49
49
|
*
|
|
50
50
|
* @example
|
|
@@ -70,17 +70,17 @@ export function collectSlots(items, found = new Set()) {
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
74
|
-
* template
|
|
75
|
-
*
|
|
73
|
+
* Sostituisce, ricorsivamente (`children` e `content` array), ogni elemento `{ slot: 'name' }` di un
|
|
74
|
+
* template con la corrispondente parte predefinita. Gli slot sconosciuti vengono segnalati in console
|
|
75
|
+
* e saltati. Gli elementi non slot vengono copiati in modo superficiale, così il template originale non viene mai modificato.
|
|
76
76
|
*
|
|
77
|
-
* @param {Array<TemplateItem|string|Node>} items -
|
|
78
|
-
* @param {Object<string, DomBuilderItem>} parts -
|
|
77
|
+
* @param {Array<TemplateItem|string|Node>} items - Elementi del template
|
|
78
|
+
* @param {Object<string, DomBuilderItem>} parts - Parti predefinite, indicizzate per nome dello slot
|
|
79
79
|
* @returns {Array<DomBuilderItem|string|Node>}
|
|
80
80
|
*
|
|
81
81
|
* @example
|
|
82
82
|
* expandSlots([{ className: 'row', children: [{ slot: 'search' }, { slot: 'resultInfo' }] }, { slot: 'table' }], parts);
|
|
83
|
-
* // → [{ className: 'row', children: [<search
|
|
83
|
+
* // → [{ className: 'row', children: [<parte search>, <parte resultInfo>] }, <parte table>]
|
|
84
84
|
*/
|
|
85
85
|
export function expandSlots(items, parts) {
|
|
86
86
|
|
|
@@ -123,43 +123,43 @@ export function expandSlots(items, parts) {
|
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
126
|
+
* Costruisce l'intera struttura del componente dentro l'elemento host (svuotato prima) tramite domBuilder:
|
|
127
|
+
* un wrapper principale fisso il cui contenuto è definito da `params.template`.
|
|
128
128
|
*
|
|
129
|
-
*
|
|
130
|
-
* - `infoSection` → `infoSectionPart()` (
|
|
131
|
-
* - `resultInfo` → `resultInfoPart()` (
|
|
132
|
-
* - `search` → `searchPart()` (
|
|
133
|
-
* - `table` → `tablePart()` (
|
|
134
|
-
* - `caption` → `captionPart()` (caption
|
|
135
|
-
* - `pagination` → `paginationPart()` (
|
|
129
|
+
* Slot del template disponibili (vedi `TemplateItem`):
|
|
130
|
+
* - `infoSection` → `infoSectionPart()` (testo informativo + input di ricerca)
|
|
131
|
+
* - `resultInfo` → `resultInfoPart()` (solo testo informativo)
|
|
132
|
+
* - `search` → `searchPart()` (solo input di ricerca)
|
|
133
|
+
* - `table` → `tablePart()` (wrapper della tabella + tabella con thead, tbody, tfoot, più la barra del footer)
|
|
134
|
+
* - `caption` → `captionPart()` (contenitore della caption; parte della barra del footer di `table` se non collocato esplicitamente)
|
|
135
|
+
* - `pagination` → `paginationPart()` (nav della paginazione; idem)
|
|
136
136
|
*
|
|
137
|
-
*
|
|
137
|
+
* Struttura generata con il template predefinito (`[{ slot: 'infoSection' }, { slot: 'table' }]`):
|
|
138
138
|
* ```
|
|
139
139
|
* section.wrapper[classes.wrapper]
|
|
140
140
|
* div.infoOuter[classes.infoOuter]
|
|
141
141
|
* div.info[classes.info]
|
|
142
142
|
* div.resultInfo
|
|
143
|
-
* div.search > input[type=search] (
|
|
143
|
+
* div.search > input[type=search] (se `search`)
|
|
144
144
|
* div.tableOuter
|
|
145
145
|
* div.tableWrapper[classes.tableWrapper]
|
|
146
146
|
* table#tableId.table[classes.table]
|
|
147
|
-
* thead / tbody / tfoot (tfoot
|
|
148
|
-
* div.tableFooter[classes.tableFooter] (
|
|
149
|
-
* div.caption (
|
|
150
|
-
* nav.pagination (
|
|
147
|
+
* thead / tbody / tfoot (tfoot se `tfoot`)
|
|
148
|
+
* div.tableFooter[classes.tableFooter] (se `caption` o `perPage` > 0)
|
|
149
|
+
* div.caption (se `caption`)
|
|
150
|
+
* nav.pagination (se `perPage` > 0)
|
|
151
151
|
* ```
|
|
152
152
|
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
153
|
+
* `<tbody>`, `<tfoot>` e paginazione vengono creati vuoti: vedi `renderTbody()`, `renderTfoot()`
|
|
154
|
+
* e `renderPagination()`.
|
|
155
155
|
*
|
|
156
|
-
* @param {JsonTable} jt -
|
|
157
|
-
* @returns {JsonTableElements}
|
|
156
|
+
* @param {JsonTable} jt - L'istanza del componente (elemento host, `params`, `cols`)
|
|
157
|
+
* @returns {JsonTableElements} Riferimenti agli elementi generati
|
|
158
158
|
*
|
|
159
159
|
* @example
|
|
160
160
|
* jt.params.template = [
|
|
161
161
|
* { className: 'flex gap-2', children: [{ slot: 'search' }, { slot: 'pagination' }] },
|
|
162
|
-
* { slot: 'table' }, // footer
|
|
162
|
+
* { slot: 'table' }, // barra del footer con la sola caption: la paginazione è collocata sopra
|
|
163
163
|
* { slot: 'resultInfo' }
|
|
164
164
|
* ];
|
|
165
165
|
* const elements = mainBuilder(jt);
|
|
@@ -176,7 +176,7 @@ export function mainBuilder(jt) {
|
|
|
176
176
|
const captionItem = captionPart(jt, elements, capId);
|
|
177
177
|
const paginationItem = paginationPart(jt, elements);
|
|
178
178
|
|
|
179
|
-
//
|
|
179
|
+
// parti della barra del footer: rimosse più sotto quando il template le colloca altrove
|
|
180
180
|
/** @type {DomBuilderItem[]} */
|
|
181
181
|
const footerChildren = [captionItem, paginationItem];
|
|
182
182
|
const footerBar = tableFooterPart(jt, elements, footerChildren);
|
|
@@ -9,10 +9,10 @@ import { iconContent } from './icons.js';
|
|
|
9
9
|
/** @typedef {import('./main-builder.js').JsonTableElements} JsonTableElements */
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* `perPage` <= 0
|
|
12
|
+
* Numero di pagine necessarie per mostrare `count` righe, `perPage` per pagina (almeno 1).
|
|
13
|
+
* `perPage` <= 0 significa nessuna paginazione: una sola pagina.
|
|
14
14
|
*
|
|
15
|
-
* @param {number} count -
|
|
15
|
+
* @param {number} count - Numero di righe
|
|
16
16
|
* @param {number} perPage - Rows per page
|
|
17
17
|
* @returns {number}
|
|
18
18
|
*
|
|
@@ -30,21 +30,21 @@ export function calcTotPages(count, perPage) {
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* Costruisce l'elenco dei numeri di pagina da mostrare nella navigazione: la pagina corrente con `delta`
|
|
34
|
+
* pagine per lato (la finestra viene allargata vicino ai bordi in modo da mantenere una dimensione costante),
|
|
35
|
+
* più la prima e l'ultima pagina; `null` indica un salto (puntini di sospensione). Quando il salto nasconderebbe una
|
|
36
|
+
* sola pagina, viene mostrata quella pagina al posto dei puntini.
|
|
37
37
|
*
|
|
38
|
-
* @param {number} current -
|
|
39
|
-
* @param {number} totPages -
|
|
40
|
-
* @param {number} [delta=2] -
|
|
38
|
+
* @param {number} current - Pagina corrente (da 1)
|
|
39
|
+
* @param {number} totPages - Numero totale di pagine
|
|
40
|
+
* @param {number} [delta=2] - Pagine per lato rispetto alla corrente (default: 2)
|
|
41
41
|
* @returns {Array<number|null>}
|
|
42
42
|
*
|
|
43
43
|
* @example
|
|
44
44
|
* pageList(1, 3); // → [1, 2, 3]
|
|
45
45
|
* pageList(1, 10); // → [1, 2, 3, 4, 5, null, 10]
|
|
46
46
|
* pageList(6, 12); // → [1, null, 4, 5, 6, 7, 8, null, 12]
|
|
47
|
-
* pageList(5, 10); // → [1, 2, 3, 4, 5, 6, 7, null, 10] (
|
|
47
|
+
* pageList(5, 10); // → [1, 2, 3, 4, 5, 6, 7, null, 10] (pagina 2 mostrata al posto dei puntini che la nasconderebbero da sola)
|
|
48
48
|
* pageList(10, 10); // → [1, null, 6, 7, 8, 9, 10]
|
|
49
49
|
* pageList(4, 10, 1); // → [1, 2, 3, 4, 5, null, 10]
|
|
50
50
|
*/
|
|
@@ -60,7 +60,7 @@ export function pageList(current, totPages, delta = 2) {
|
|
|
60
60
|
let min = Math.max(1, current - side);
|
|
61
61
|
let max = Math.min(totPages, current + side);
|
|
62
62
|
|
|
63
|
-
//
|
|
63
|
+
// mantiene costante la dimensione della finestra vicino ai bordi
|
|
64
64
|
while (max - min + 1 < width) {
|
|
65
65
|
if (min > 1) {
|
|
66
66
|
min--;
|
|
@@ -95,7 +95,7 @@ export function pageList(current, totPages, delta = 2) {
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* Sostituisce il segnaposto `{page}` di un'etichetta di paginazione.
|
|
99
99
|
* @param {string|undefined} label
|
|
100
100
|
* @param {number} page
|
|
101
101
|
* @param {string} locale
|
|
@@ -107,29 +107,29 @@ function pageLabel(label, page, locale) {
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
* domBuilder
|
|
111
|
-
* `params.perPage`
|
|
112
|
-
* `click`
|
|
113
|
-
*
|
|
110
|
+
* Elemento domBuilder del `<nav>` della paginazione (slot del template `pagination`), renderizzato solo quando
|
|
111
|
+
* `params.perPage` è > 0. Il `<nav>` viene memorizzato in `elements.pagination` e riceve un listener
|
|
112
|
+
* `click` delegato sui suoi pulsanti, che chiama `jt.goToPage()`. Il contenuto (elenco delle pagine) viene
|
|
113
|
+
* renderizzato da `renderPagination()` e l'intero `<nav>` è nascosto quando c'è una sola pagina.
|
|
114
114
|
*
|
|
115
|
-
*
|
|
115
|
+
* Struttura generata (vedi `renderPagination`):
|
|
116
116
|
* ```
|
|
117
117
|
* nav.pagination[classes.pagination][aria-label=labels.paginationAriaLabel]
|
|
118
118
|
* ul.paginationList
|
|
119
119
|
* li.paginationItem > button.paginationBtn[classes.paginationBtn][data-page=prev][aria-label][title] > icon
|
|
120
120
|
* li.paginationItem > button.paginationBtn[data-page=1][aria-label="Vai a pagina 1"] 1
|
|
121
|
-
* li.paginationItem > button.paginationBtn[data-page=2][aria-current=page] 2 ←
|
|
121
|
+
* li.paginationItem > button.paginationBtn[data-page=2][aria-current=page] 2 ← pagina corrente
|
|
122
122
|
* li.paginationItem > span.paginationEllipsis …
|
|
123
123
|
* li.paginationItem > button.paginationBtn[data-page=next] > icon
|
|
124
124
|
* ```
|
|
125
125
|
*
|
|
126
|
-
* @param {JsonTable} jt -
|
|
127
|
-
* @param {JsonTableElements} elements -
|
|
126
|
+
* @param {JsonTable} jt - L'istanza del componente
|
|
127
|
+
* @param {JsonTableElements} elements - Oggetto che raccoglie gli elementi generati (modificato)
|
|
128
128
|
* @returns {DomBuilderItem}
|
|
129
129
|
*
|
|
130
130
|
* @example
|
|
131
131
|
* domBuilder([paginationPart(jt, elements)], host);
|
|
132
|
-
* elements.pagination; // → HTMLElement (nav),
|
|
132
|
+
* elements.pagination; // → HTMLElement (nav), quando params.perPage > 0
|
|
133
133
|
*/
|
|
134
134
|
export function paginationPart(jt, elements) {
|
|
135
135
|
|
|
@@ -162,21 +162,21 @@ export function paginationPart(jt, elements) {
|
|
|
162
162
|
|
|
163
163
|
|
|
164
164
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
165
|
+
* Renderizza l'elenco delle pagine dentro `elements.pagination` a partire dallo stato corrente (`page`, `totPages`),
|
|
166
|
+
* sostituendo il contenuto precedente; il `<nav>` è nascosto quando c'è una sola pagina.
|
|
167
167
|
*
|
|
168
|
-
*
|
|
169
|
-
* `'prev'`, `'next'`
|
|
170
|
-
*
|
|
171
|
-
*
|
|
168
|
+
* Quando `focusTarget` è indicato (il `data-page` del pulsante che ha causato il cambio:
|
|
169
|
+
* `'prev'`, `'next'` o un numero di pagina) il focus viene spostato sul corrispondente nuovo pulsante, oppure
|
|
170
|
+
* sul pulsante della pagina corrente quando quello non è più disponibile, così che gli utenti da tastiera
|
|
171
|
+
* non perdano la loro posizione.
|
|
172
172
|
*
|
|
173
|
-
* @param {JsonTable} jt -
|
|
174
|
-
* @param {string|null} [focusTarget=null] - `data-page`
|
|
173
|
+
* @param {JsonTable} jt - L'istanza del componente
|
|
174
|
+
* @param {string|null} [focusTarget=null] - `data-page` del pulsante a cui dare il focus dopo il rendering (default: null)
|
|
175
175
|
* @returns {void}
|
|
176
176
|
*
|
|
177
177
|
* @example
|
|
178
|
-
* renderPagination(jt); //
|
|
179
|
-
* renderPagination(jt, 'next'); //
|
|
178
|
+
* renderPagination(jt); // dopo l'aggiornamento di `jt.state`
|
|
179
|
+
* renderPagination(jt, 'next'); // come sopra, spostando il focus sul pulsante "avanti"
|
|
180
180
|
*/
|
|
181
181
|
export function renderPagination(jt, focusTarget = null) {
|
|
182
182
|
|