@massimo-cassandro/minimo 1.32.4 → 1.33.1

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 (88) hide show
  1. package/README.md +2 -1
  2. package/dev-tools/starter-kit/source_files/_private/pwd.md +16 -0
  3. package/dev-tools/starter-kit/source_files/_private/sf.md +12 -0
  4. package/dev-tools/starter-kit/source_files/{CLAUDE-frontend.md → app/CLAUDE.md} +2 -1
  5. package/dev-tools/starter-kit/source_files/app/assets/api_htaccess +20 -0
  6. package/dev-tools/starter-kit/source_files/{layout-critical.css → app/css/layout.critical.css} +1 -1
  7. package/dev-tools/starter-kit/source_files/app/css/layout.css +0 -0
  8. package/dev-tools/starter-kit/source_files/app/index.js +1 -0
  9. package/dev-tools/starter-kit/{package-tpl.json → source_files/root/package-tpl.json} +1 -1
  10. package/dev-tools/starter-kit/source_files/{stylelint.config.mjs → root/stylelint.config.mjs} +1 -1
  11. package/dev-tools/starter-kit/source_files/root/webpack-config-modules/inline-critical-css.mjs +41 -0
  12. package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/purgecss-setup.mjs +1 -1
  13. package/dev-tools/starter-kit/{webpack.config.mjs → source_files/root/webpack.config.mjs} +56 -38
  14. package/dev-tools/starter-kit/starter-install.sh +233 -81
  15. package/dev-tools/stylelint-config/README.md +45 -0
  16. package/dev-tools/stylelint-config/index.js +184 -0
  17. package/dev-tools/stylelint-config/test/test.module.scss +9 -0
  18. package/package.json +11 -2
  19. package/snippets/php/iviewer.php +488 -0
  20. package/snippets/twig-symfony/ViewerController.php +549 -0
  21. package/src/custom-properties.css +36 -0
  22. package/src/minimo.css +3 -0
  23. package/src/utilities/dom-builder/dom-builder.js +9 -5
  24. package/src/web-components/json-table/json-table-component.js +632 -0
  25. package/src/web-components/json-table/json-table-component.module.css +247 -0
  26. package/src/web-components/json-table/json-table.minimo.tokens.mjs +243 -0
  27. package/src/web-components/json-table/readme.md +764 -0
  28. package/src/web-components/json-table/src/cell-content.js +136 -0
  29. package/src/web-components/json-table/src/content-utils.js +103 -0
  30. package/src/web-components/json-table/src/data-types.js +280 -0
  31. package/src/web-components/json-table/src/defaults.js +424 -0
  32. package/src/web-components/json-table/src/get-data.js +152 -0
  33. package/src/web-components/json-table/src/icons.js +80 -0
  34. package/src/web-components/json-table/src/info-section.js +107 -0
  35. package/src/web-components/json-table/src/main-builder.js +218 -0
  36. package/src/web-components/json-table/src/pagination.js +253 -0
  37. package/src/web-components/json-table/src/parse-cols.js +113 -0
  38. package/src/web-components/json-table/src/parse-rows.js +81 -0
  39. package/src/web-components/json-table/src/resolve-params.js +166 -0
  40. package/src/web-components/json-table/src/search.js +71 -0
  41. package/src/web-components/json-table/src/sorting.js +111 -0
  42. package/src/web-components/json-table/src/table-body.js +109 -0
  43. package/src/web-components/json-table/src/table-builder.js +152 -0
  44. package/src/web-components/json-table/src/table-tfoot.js +56 -0
  45. package/src/web-components/json-table/src/table-thead.js +183 -0
  46. package/src/web-components/json-table/src/update-info.js +67 -0
  47. package/src/web-components/s-datatable-component/{docs.md → readme.md} +67 -3
  48. package/src/web-components/s-datatable-component/s-datatable-component.js +1 -1
  49. package/types/global.d.ts +17 -3
  50. package/dev-tools/starter-kit/source_files/app_index.js +0 -1
  51. package/snippets/config-templates/_htaccess +0 -69
  52. package/snippets/config-templates/robots.txt +0 -5
  53. package/snippets/config-templates/rollup.config.mjs +0 -115
  54. /package/dev-tools/starter-kit/source_files/{_root_robots.txt → app/assets/robots.txt} +0 -0
  55. /package/dev-tools/starter-kit/source_files/{_root_htaccess → app/assets/root_htaccess} +0 -0
  56. /package/{src → dev-tools/starter-kit/source_files/app/css}/fonts.css +0 -0
  57. /package/dev-tools/starter-kit/source_files/{favicons-readme.md → app/favicons/favicons-readme.md} +0 -0
  58. /package/dev-tools/starter-kit/{webpack-template.ejs → source_files/app/tpl/index.ejs} +0 -0
  59. /package/dev-tools/starter-kit/source_files/{__project__.code-workspace → root/__project__.code-workspace} +0 -0
  60. /package/dev-tools/starter-kit/source_files/{_browserslistrc → root/_browserslistrc} +0 -0
  61. /package/dev-tools/starter-kit/source_files/{_editorconfig → root/_editorconfig} +0 -0
  62. /package/dev-tools/starter-kit/source_files/{_gitignore → root/_gitignore} +0 -0
  63. /package/dev-tools/starter-kit/source_files/{_prettierrc → root/_prettierrc} +0 -0
  64. /package/dev-tools/starter-kit/source_files/{eslint.config.mjs → root/eslint.config.mjs} +0 -0
  65. /package/dev-tools/starter-kit/source_files/{jsconfig.json → root/jsconfig.json} +0 -0
  66. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/css-rules.mjs +0 -0
  67. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/get-jsConfig-aliases.mjs +0 -0
  68. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/mini-svg-data-uri-loader.cjs +0 -0
  69. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/postcss.config.mjs +0 -0
  70. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/purgecss-variables-safelist.mjs +0 -0
  71. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/svg-rules.mjs +0 -0
  72. /package/dev-tools/starter-kit/{webpack-config-modules → source_files/root/webpack-config-modules}/svgo.config.mjs +0 -0
  73. /package/snippets/{config-templates/_github → _github}/dependabot.yml +0 -0
  74. /package/snippets/{error-pages/error-pages.js → error-pages.js} +0 -0
  75. /package/snippets/{config-templates/react → react}/offcanvas/offcanvas.jsx +0 -0
  76. /package/snippets/{config-templates/react → react}/offcanvas/offcanvas.module.scss +0 -0
  77. /package/snippets/{config-templates → root}/_hintrc.cjs +0 -0
  78. /package/snippets/{config-templates → root}/_npmignore +0 -0
  79. /package/snippets/{config-templates → root}/_npmrc +0 -0
  80. /package/snippets/{config-templates → root}/_stylelintignore +0 -0
  81. /package/snippets/{config-templates → root}/babel.config--react.json +0 -0
  82. /package/snippets/{config-templates → root}/babel.config--solidJS.json +0 -0
  83. /package/snippets/{ImgViewerController.php → twig-symfony/ImgViewerController.php} +0 -0
  84. /package/snippets/{UnsplashController.php → twig-symfony/UnsplashController.php} +0 -0
  85. /package/snippets/{config-templates → twig-symfony}/_env.local +0 -0
  86. /package/snippets/{error-pages → twig-symfony}/bundles/TwigBundle/Exception/error.html.twig +0 -0
  87. /package/snippets/{flash-messages.html.twig → twig-symfony/flash-messages.html.twig} +0 -0
  88. /package/snippets/{minimo-form-layout.html.twig → twig-symfony/minimo-form-layout.html.twig} +0 -0
@@ -0,0 +1,56 @@
1
+ /*! minimo - json-table: tfoot rendering */
2
+
3
+ import { domBuilder } from '../../../utilities/dom-builder/dom-builder.js';
4
+ import { classnames } from '../../../utilities/classnames.js';
5
+ import { setContent } from './content-utils.js';
6
+ import { tfootContent } from './cell-content.js';
7
+
8
+ /** @typedef {import('../json-table-component.js').JsonTable} JsonTable */
9
+
10
+ /**
11
+ * Renders the footer row inside `elements.tfoot` (present only when `params.tfoot` is true),
12
+ * replacing the previous content. Every column produces a cell whose content comes from
13
+ * `tfootContent()` (column `tfootRender`); the footer is emptied when there are no rows.
14
+ *
15
+ * The rows passed to `tfootRender` are the whole filtered set, or the current page only when
16
+ * `updateFooterOnPageChange` is true.
17
+ *
18
+ * Generated structure: `tr > td[data-key][cellClass]…`
19
+ *
20
+ * @param {JsonTable} jt - The component instance
21
+ * @returns {void}
22
+ *
23
+ * @example
24
+ * renderTfoot(jt); // after `jt.state` has been updated
25
+ */
26
+ export function renderTfoot(jt) {
27
+
28
+ const { params, elements, state, cols } = jt;
29
+ const tfoot = elements.tfoot;
30
+
31
+ if (!tfoot) {
32
+ return;
33
+ }
34
+
35
+ if (!state.filtered.length) {
36
+ tfoot.replaceChildren();
37
+ return;
38
+ }
39
+
40
+ const rows = (params.updateFooterOnPageChange ? state.pageRows : state.filtered).map(parsed => parsed.row);
41
+
42
+ domBuilder([
43
+ {
44
+ tag: 'tr',
45
+ children: cols.map(col => ({
46
+ tag: 'td',
47
+ className: classnames(col.cellClass),
48
+ attrs: { 'data-key': col.key },
49
+ callback: el => {
50
+ const td = /** @type {HTMLTableCellElement} */ (el);
51
+ setContent(td, tfootContent(col, rows, params, td));
52
+ }
53
+ }))
54
+ }
55
+ ], tfoot, { emptyParent: true });
56
+ }
@@ -0,0 +1,183 @@
1
+ /*! minimo - json-table: thead */
2
+
3
+ import * as styles from '../json-table-component.module.css';
4
+ import { classnames } from '../../../utilities/classnames.js';
5
+ import { setContent } from './content-utils.js';
6
+ import { iconContent } from './icons.js';
7
+ import { nextSortDir } from './sorting.js';
8
+
9
+ /** @typedef {import('./defaults.js').JsonTableParams} JsonTableParams */
10
+ /** @typedef {import('../json-table-component.js').JsonTable} JsonTable */
11
+ /** @typedef {import('./main-builder.js').JsonTableElements} JsonTableElements */
12
+
13
+ /** @typedef {'none'|'ascending'|'descending'} SortState */
14
+
15
+ /**
16
+ * Updates the sort state of a sortable `<th>`: `aria-sort` attribute (removed when `none`),
17
+ * icon and `title`/`aria-label` of the sort button (both describing the action of the next
18
+ * click, e.g. "sort descending" when the ascending sort is active).
19
+ *
20
+ * @param {HTMLTableCellElement} th - The `<th>` generated by `theadPart()`
21
+ * @param {SortState} state - Sort state to apply
22
+ * @param {JsonTableParams} params - Resolved params (icons and labels)
23
+ * @returns {void}
24
+ *
25
+ * @example
26
+ * setSortState(th, 'ascending', params);
27
+ * // th[aria-sort=ascending], icon → params.sortAscArrowIcon, button title → params.labels.sortDesc
28
+ */
29
+ export function setSortState(th, state, params) {
30
+
31
+ const btn = th.querySelector('button');
32
+ const icon = th.querySelector('[data-jt-sort-icon]');
33
+
34
+ if (state === 'none') {
35
+ th.removeAttribute('aria-sort');
36
+ } else {
37
+ th.setAttribute('aria-sort', state);
38
+ }
39
+
40
+ const nextLabel = state === 'none'
41
+ ? params.labels.sortAsc
42
+ : (state === 'ascending' ? params.labels.sortDesc : params.labels.sortNone);
43
+
44
+ if (btn) {
45
+ const titleText = (th.querySelector('[data-jt-sort-title]')?.textContent ?? '').trim();
46
+ btn.title = nextLabel ?? '';
47
+ btn.setAttribute('aria-label', titleText ? `${titleText}: ${nextLabel}` : (nextLabel ?? ''));
48
+ }
49
+
50
+ if (icon) {
51
+ const iconDef = state === 'none'
52
+ ? params.sortNoneArrowIcon
53
+ : (state === 'ascending' ? params.sortAscArrowIcon : params.sortDescArrowIcon);
54
+ setContent(/** @type {HTMLElement} */ (icon), iconContent(iconDef));
55
+ }
56
+ }
57
+
58
+
59
+ /**
60
+ * Applies the current sort (`jt.state.sort`) to every sortable `<th>` of the thead: the sorted
61
+ * column gets `aria-sort` and the matching icon, the others are reset to `none`.
62
+ *
63
+ * @param {JsonTable} jt - The component instance
64
+ * @returns {void}
65
+ *
66
+ * @example
67
+ * jt.state.sort = { key: 'name', dir: 'desc' };
68
+ * applySortState(jt); // th[data-key=name][aria-sort=descending], the other th without aria-sort
69
+ */
70
+ export function applySortState(jt) {
71
+
72
+ const { elements, params, state } = jt;
73
+
74
+ if (!elements.thead) {
75
+ return;
76
+ }
77
+
78
+ elements.thead.querySelectorAll('th[data-sortable]').forEach(el => {
79
+ const th = /** @type {HTMLTableCellElement} */ (el);
80
+ const isSorted = state.sort != null && th.dataset.key === state.sort.key;
81
+ setSortState(th, isSorted ? (state.sort?.dir === 'desc' ? 'descending' : 'ascending') : 'none', params);
82
+ });
83
+ }
84
+
85
+
86
+ /**
87
+ * Attaches the delegated `click` listener to the thead: a click on a sort button cycles the
88
+ * column sort (none → asc → desc → none, see `nextSortDir`) through `jt.setSort()`.
89
+ * The thead is not rebuilt on sort, so the focus stays on the clicked button.
90
+ *
91
+ * @param {JsonTable} jt - The component instance
92
+ * @returns {void}
93
+ *
94
+ * @example
95
+ * setSortListener(jt); // after mainBuilder(jt)
96
+ */
97
+ export function setSortListener(jt) {
98
+
99
+ const thead = jt.elements.thead;
100
+
101
+ if (!thead) {
102
+ return;
103
+ }
104
+
105
+ thead.addEventListener('click', e => {
106
+ const btn = /** @type {HTMLElement|null} */ (
107
+ /** @type {HTMLElement} */ (e.target).closest('button[data-key]')
108
+ );
109
+ if (!btn) {
110
+ return;
111
+ }
112
+ const key = btn.dataset.key ?? '';
113
+ const current = jt.state.sort?.key === key ? jt.state.sort.dir : null;
114
+ jt.setSort(key, nextSortDir(current));
115
+ });
116
+ }
117
+
118
+
119
+ /**
120
+ * domBuilder item of the `<thead>`.
121
+ *
122
+ * Generated structure:
123
+ * ```
124
+ * thead > tr
125
+ * th[scope=col][data-key][headerClass] ← not sortable: content = col.title
126
+ * th.sortable[scope=col][data-key][data-sortable=true][headerClass] ← sortable
127
+ * button.sortBtn[classes.sortBtn][type=button][data-key][title][aria-label]
128
+ * span.sortTitle[data-jt-sort-title] ← col.title
129
+ * span.sortIcon[data-jt-sort-icon] ← sort icon (see `setSortState`)
130
+ * ```
131
+ *
132
+ * The `<thead>` is stored in `elements.thead`; the sort listener is attached by `setSortListener()`.
133
+ *
134
+ * @param {JsonTable} jt - The component instance (`params`, `cols`)
135
+ * @param {JsonTableElements} elements - Object collecting the generated elements (mutated)
136
+ * @returns {DomBuilderItem}
137
+ *
138
+ * @example
139
+ * domBuilder([{ tag: 'table', children: [theadPart(jt, elements)] }], host);
140
+ * elements.thead; // → HTMLTableSectionElement
141
+ */
142
+ export function theadPart(jt, elements) {
143
+
144
+ const { params, cols } = jt;
145
+
146
+ return {
147
+ tag: 'thead',
148
+ callback: el => { elements.thead = /** @type {HTMLTableSectionElement} */ (el); },
149
+ children: [
150
+ {
151
+ tag: 'tr',
152
+ children: cols.map(col => ({
153
+ tag: 'th',
154
+ className: classnames(col.headerClass, col.sortable && styles.sortable),
155
+ attrs: {
156
+ scope: 'col',
157
+ 'data-key': col.key,
158
+ 'data-sortable': col.sortable ? 'true' : null
159
+ },
160
+ content: col.sortable ? null : col.title,
161
+ children: col.sortable
162
+ ? [
163
+ {
164
+ tag: 'button',
165
+ className: classnames(styles.sortBtn, params.classes.sortBtn),
166
+ attrs: { type: 'button', 'data-key': col.key },
167
+ children: [
168
+ { tag: 'span', className: styles.sortTitle, attrs: { 'data-jt-sort-title': '' }, content: col.title },
169
+ { tag: 'span', className: styles.sortIcon, attrs: { 'data-jt-sort-icon': '', 'aria-hidden': 'true' } }
170
+ ]
171
+ }
172
+ ]
173
+ : [],
174
+ callback: el => {
175
+ if (col.sortable) {
176
+ setSortState(/** @type {HTMLTableCellElement} */ (el), 'none', params);
177
+ }
178
+ }
179
+ }))
180
+ }
181
+ ]
182
+ };
183
+ }
@@ -0,0 +1,67 @@
1
+ /*! minimo - json-table: info text update */
2
+
3
+ import { setContent } from './content-utils.js';
4
+
5
+ /** @typedef {import('../json-table-component.js').JsonTable} JsonTable */
6
+
7
+ /**
8
+ * Updates the info text (`elements.resultInfo`) from the current state.
9
+ *
10
+ * Content resolution:
11
+ * - `params.infoText` function → `infoText(start, end, totRec, filteredRec, page, totPages)`
12
+ * - no rows → `labels.noResults` (search active) or `labels.noRows`
13
+ * - otherwise the mustache-like template `params.infoText` (string) or `labels.info`, with the
14
+ * placeholders `{start}`, `{end}`, `{totRec}`, `{filteredRec}`, `{page}`, `{totPages}` replaced
15
+ * by the locale-formatted numbers
16
+ *
17
+ * `start`/`end` are the 1-based indexes of the first/last row of the current page within the
18
+ * filtered set (0 when there are no rows).
19
+ *
20
+ * @param {JsonTable} jt - The component instance
21
+ * @returns {void}
22
+ *
23
+ * @example
24
+ * updateInfo(jt);
25
+ * // default `labels.info`, page 2 of 25 rows per page, 60 rows → "Stai visualizzando le righe da 26 a 50, su un totale di 60 record trovati"
26
+ */
27
+ export function updateInfo(jt) {
28
+
29
+ const { params, elements, state } = jt;
30
+ const target = elements.resultInfo;
31
+
32
+ if (!target) {
33
+ return;
34
+ }
35
+
36
+ const shown = state.pageRows.length;
37
+ const perPage = params.perPage > 0 ? params.perPage : shown;
38
+ const start = shown ? (state.page - 1) * perPage + 1 : 0;
39
+
40
+ /** @type {Record<string, number>} */
41
+ const values = {
42
+ start,
43
+ end: shown ? start + shown - 1 : 0,
44
+ totRec: state.totRec,
45
+ filteredRec: state.filteredRec,
46
+ page: state.page,
47
+ totPages: state.totPages
48
+ };
49
+
50
+ let content;
51
+
52
+ if (typeof params.infoText === 'function') {
53
+ content = params.infoText(values.start, values.end, values.totRec, values.filteredRec, values.page, values.totPages);
54
+
55
+ } else if (values.filteredRec === 0) {
56
+ content = state.searchTerm ? params.labels.noResults : params.labels.noRows;
57
+
58
+ } else {
59
+ const tpl = params.infoText ?? params.labels.info ?? '';
60
+ content = String(tpl).replace(
61
+ /\{(start|end|totRec|filteredRec|page|totPages)\}/g,
62
+ (_, key) => values[key].toLocaleString(params.locale)
63
+ );
64
+ }
65
+
66
+ setContent(target, content);
67
+ }
@@ -1,6 +1,8 @@
1
- # `s-datatable` web-component per simple-datatables
1
+ # `s-datatable` web-component per [simple-datatables](https://fiduswriter.github.io/simple-datatables/documentation/)
2
+
3
+
4
+ >**NB: deprecato, utilizzare [json-table](../json-table/readme.md)**
2
5
 
3
- <https://fiduswriter.github.io/simple-datatables/documentation/>
4
6
 
5
7
  ## Installazione
6
8
 
@@ -176,6 +178,68 @@ document.dispatchEvent(new CustomEvent('datatable:search', {
176
178
  }));
177
179
  ```
178
180
 
181
+ ## Parametri/attributi
182
+
183
+ Tutti i parametri sono leggibili sia da attributo HTML che da script (`init()`).
184
+ Ordine di precedenza: config (script) > attributo HTML > default interno.
185
+
186
+ ### Parametri del componente
187
+
188
+ ```javascript
189
+ {
190
+ json, // URL da cui recuperare i dati (struttura attesa: { data: [...] }).
191
+ // Ignorato se `data` è presente.
192
+
193
+ data, // Dati inline, array di oggetti plain. Ha precedenza su `json`.
194
+ // Utile in contesti SSR (Twig, Blade, ...) dove il JSON è già
195
+ // disponibile server-side; per grandi dataset preferire `json`.
196
+
197
+ cols, // Definizione delle colonne. Vedi "Parametro cols" più sotto.
198
+ // Default: []
199
+
200
+ tableClass, // Classi CSS del tag <table>, in sostituzione di 'table table-bordered'.
201
+ // La classe interna styles.table (necessaria al layout) viene
202
+ // comunque sempre applicata.
203
+ // Default: 'table table-bordered'
204
+
205
+ renderNullAs, // Stringa globale da mostrare al posto di valori null/undefined,
206
+ // sovrascrivibile per singola colonna con `_renderNullAs`.
207
+ // Default: '—' (em dash)
208
+
209
+ updateFooterOnPageChange, // Se true, `_footerRender` riceve solo i record della
210
+ // pagina corrente (subtotale). Se false, l'intero set filtrato
211
+ // (il footer si aggiorna solo al cambio filtro, non pagina).
212
+ // Default: false
213
+
214
+ refs, // string[] di percorsi URL da cui, se si proviene, la pagina
215
+ // corrente viene ripristinata dal cookie di sessione 'sd-pag'.
216
+ // Confronto su pathname (query string/hash ignorati): es. ['/utenti']
217
+ // intercetta anche '/utenti/1234'.
218
+
219
+ topSlot, // Elemento DOM o markup HTML nell'area in alto a sinistra.
220
+ // Solo via init() (non leggibile da attributo HTML). Ignorato
221
+ // se showInfoAtTop è true. Vedi sezione dedicata più sotto.
222
+
223
+ showInfoAtTop, // Replica il testo dell'area info anche in alto a sinistra.
224
+ // Ha priorità su topSlot se true. Vedi sezione dedicata più sotto.
225
+ // Default: true
226
+ }
227
+ ```
228
+
229
+ ### Parametri nativi di simple-datatables
230
+
231
+ ```javascript
232
+ {
233
+ perPage, // Numero di righe per pagina, passato direttamente come opzione
234
+ // nativa `perPage` del costruttore DataTable.
235
+ // Default: 25
236
+ }
237
+ ```
238
+
239
+ Tutte le altre opzioni native di simple-datatables (`searchable`, `sortable`, `paging`,
240
+ `pagerDelta`, `perPageSelect`, `locale`, `labels`, `classes`, `template`, ...) sono
241
+ impostate internamente dal componente e **non** sono configurabili da attributo/script.
242
+
179
243
  ## Parametro `cols`
180
244
 
181
245
  Array di oggetti di configurazione delle colonne. Le chiavi con prefisso `_` sono
@@ -217,7 +281,7 @@ cols: [
217
281
  // 'sf_datetime' – data e ora da oggetto Symfony ({ date, timezone }),
218
282
  // pre-elaborato in _load
219
283
  // 'sf_date' – come 'sf_datetime', ma mostra solo la data
220
- // 'datetime' – data e ora da stringa/valore parsabile da `new Date()`
284
+ // 'datetime' – data e ora da stringa/valore elaborabile da `new Date()`
221
285
  // 'date' – come 'datetime', ma mostra solo la data
222
286
  // (date/datetime: formato it-IT, allineamento a destra,
223
287
  // data-order impostato per l'ordinamento; null → '—')
@@ -502,7 +502,7 @@ class SimpleDatatableAdapter extends HTMLElement {
502
502
  * Se presente e !== undefined sovrascrive sempre l'attributo.
503
503
  * Passare esplicitamente `null` per ignorare l'attributo e
504
504
  * ricevere il defaultValue.
505
- * 2. Attributo HTML – se il valore inizia con [ o { viene auto-parsato
505
+ * 2. Attributo HTML – se il valore inizia con [ o { viene auto-elaborato
506
506
  * da JSON (utile per cols, che può stare nell'attributo).
507
507
  * 3. defaultValue – fallback finale.
508
508
  *
package/types/global.d.ts CHANGED
@@ -3,9 +3,23 @@
3
3
  // The canonical definition lives in dom-builder.js — this only re-exports it.
4
4
  type DomBuilderItem = import('../src/utilities/dom-builder/dom-builder.js').DomBuilderItem;
5
5
 
6
- // Sanitizer API (Element.setHTML / getHTML) — not yet in TypeScript's lib.dom.d.ts.
6
+ // Global alias for the `<json-table>` web component class, so consumer scripts can write
7
+ // `/** @type {JsonTable} */` without importing the type. The tag name map augmentation makes
8
+ // `document.querySelector('json-table')` / `document.createElement('json-table')` return a
9
+ // `JsonTable` instance without casts. Consumers get both by adding this file to their
10
+ // jsconfig/tsconfig `include` (e.g. "node_modules/@massimo-cassandro/minimo/types/global.d.ts").
11
+ type JsonTable = import('../src/web-components/json-table/json-table-component.js').JsonTable;
12
+
13
+ interface HTMLElementTagNameMap {
14
+ 'json-table': JsonTable;
15
+ }
16
+
17
+ // Sanitizer API (Element.setHTML / getHTML). Declared as required members (not optional) so
18
+ // the augmentation stays compatible with the lib.dom versions that already include them
19
+ // (overload signatures must all be optional or all required); the runtime code still checks
20
+ // `typeof el.setHTML === 'function'` before using it.
7
21
  // https://developer.mozilla.org/en-US/docs/Web/API/Element/setHTML
8
22
  interface Element {
9
- setHTML?(input: string, options?: { sanitizer?: unknown }): void;
10
- getHTML?(options?: { serializableShadowRoots?: boolean; shadowRoots?: ShadowRoot[] }): string;
23
+ setHTML(input: string, options?: { sanitizer?: unknown }): void;
24
+ getHTML(options?: { serializableShadowRoots?: boolean; shadowRoots?: ShadowRoot[] }): string;
11
25
  }
@@ -1 +0,0 @@
1
- import './index.css';
@@ -1,69 +0,0 @@
1
-
2
- # no cache
3
- # <IfModule mod_headers.c>
4
- # Header set Cache-Control "no-cache, no-store, must-revalidate"
5
- # Header set Pragma "no-cache"
6
- # Header set Expires 0
7
- # </IfModule>
8
-
9
- # blocco iframe
10
- # "deny" = tutti siti
11
- # "sameorigin" tutti tranne quelli che vengono dalla stessa origine
12
- # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
13
- Header set X-Frame-Options "sameorigin"
14
-
15
-
16
- <IfModule mod_expires.c>
17
- ExpiresActive On
18
- AddType application/vnd.ms-fontobject .eot
19
- AddType application/x-font-ttf .ttf
20
- AddType application/x-font-opentype .otf
21
- AddType application/x-font-woff .woff
22
- AddType application/x-font-woff2 .woff2
23
- AddType application/font-sfnt otf ttf
24
- AddType application/font-woff woff
25
- AddType application/font-woff2 woff2
26
- AddType image/svg+xml .svg
27
-
28
- ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
29
- ExpiresByType application/x-font-ttf "access plus 1 year"
30
- ExpiresByType application/x-font-opentype "access plus 1 year"
31
- ExpiresByType application/x-font-woff "access plus 1 year"
32
- ExpiresByType application/x-font-woff2 "access plus 1 year"
33
- ExpiresByType application/font-sfnt "access plus 1 year"
34
- ExpiresByType application/font-woff "access plus 1 year"
35
- ExpiresByType application/font-woff2 "access plus 1 year"
36
-
37
- ExpiresByType text/html "access plus 1 hour"
38
- ExpiresByType text/css "access plus 1 year"
39
- ExpiresByType text/x-javascript "access plus 1 year"
40
- ExpiresByType application/javascript "access plus 1 year"
41
- ExpiresByType application/x-javascript "access plus 1 year"
42
-
43
- ExpiresByType image/svg+xml "access plus 1 year"
44
- ExpiresByType image/gif "access plus 1 year"
45
- ExpiresByType image/png "access plus 1 year"
46
- ExpiresByType image/jpeg "access plus 1 year"
47
- ExpiresByType image/pjpeg "access plus 1 year"
48
- ExpiresByType image/webp "access plus 1 year"
49
- ExpiresByType image/avif "access plus 1 year"
50
-
51
- ExpiresByType application/pdf "access plus 1 year"
52
-
53
- ExpiresByType video/mp4 "access plus 1 year"
54
- ExpiresByType video/webm "access plus 1 year"
55
- ExpiresByType video/x-m4v "access plus 1 year"
56
- ExpiresByType video/quicktime "access plus 1 year"
57
- ExpiresByType audio/mpeg "access plus 1 year"
58
- ExpiresByType audio/x-wav "access plus 1 year"
59
-
60
- ExpiresByType image/x-icon "access plus 1 year"
61
- ExpiresDefault "access plus 1 year"
62
- </IfModule>
63
-
64
- <IfModule !mod_expires.c>
65
- <IfModule mod_headers.c>
66
- # 1 year
67
- Header set Cache-Control 'public, max-age 31536000'
68
- </IfModule>
69
- </IfModule>
@@ -1,5 +0,0 @@
1
- User-agent: *
2
- Allow: /
3
- # Disallow: /
4
-
5
- Sitemap: https://www.example.com/sitemap.xml
@@ -1,115 +0,0 @@
1
- import terser from '@rollup/plugin-terser';
2
- import fs from 'fs';
3
- import node_resolve from '@rollup/plugin-node-resolve';
4
- import commonjs from '@rollup/plugin-commonjs';
5
-
6
- // https://github.com/hyhappy/rollup-plugin-string-html
7
- // import htmlString from 'rollup-plugin-string-html';
8
-
9
- // https://github.com/exuanbo/rollup-plugin-minify-html-template-literals
10
- // https://github.com/asyncLiz/minify-html-literals
11
- // https://github.com/kangax/html-minifier#options-quick-reference
12
- // import minifyHTML from 'rollup-plugin-minify-html-template-literals';
13
-
14
- import p from '../package.json'; // assert { type: 'json' };
15
-
16
- const terserOptions = {
17
- compress: {
18
- passes: 2
19
- }
20
- },
21
- anno = new Date().getFullYear(),
22
- dirs = [
23
- {source_dir: './front-end/js', output_dir: './AppBundle/Resources/public/js'}
24
- ];
25
-
26
- let config = [];
27
-
28
- // lettura subdir apps e aggiunta a `dirs`
29
- fs.readdirSync('./front-end/apps').forEach(item => {
30
- let stats = fs.statSync(`./front-end/apps/${item}`); // stats.isFile() / stats.isDirectory()
31
- if(stats.isDirectory()) {
32
- dirs.push({
33
- source_dir: `./front-end/apps/${item}`,
34
- output_dir: `./AppBundle/Resources/public/apps/${item}`
35
- });
36
- }
37
- });
38
-
39
- dirs.forEach(dir => {
40
-
41
- fs.readdirSync(dir.source_dir)
42
- .filter(f => /\.js$/.test(f))
43
- .filter(f => /^[^_]/.test(f)) // ignore files starting with _
44
- .forEach(file => {
45
-
46
- let format = 'iife',
47
- name = null;
48
-
49
- if(/(-umd\.js)$/.test(file)) {
50
- format = 'umd';
51
- name = file.replace('-umd.js', '').replace(/-/g, '_');
52
- }
53
-
54
- config.push(
55
- {
56
- // preserveEntrySignatures: false,
57
- input: `${dir.source_dir}/${file}`,
58
- plugins: [
59
- // deve essere il primo
60
- // minifyHTML({
61
- // options: {
62
- // minifyOptions: {
63
- // html5: true,
64
- // collapseWhitespace: true,
65
- // collapseInlineTagWhitespace: true,
66
- // conservativeCollapse: true,
67
- // decodeEntities: true
68
- // },
69
- // shouldMinify: () => true
70
- // },
71
- // }),
72
- node_resolve(),
73
- commonjs(),
74
- terser(terserOptions),
75
- ],
76
- output: [{
77
- file: `${dir.output_dir}/${file.replace('.js', '-min.js')}`,
78
- format: format,
79
- sourcemap: true,
80
- name: name,
81
- banner: `/*! xxxx v.${p.version} - Massimo Cassandro ${anno} */`,
82
- // footer: `//! Released on ${new Date().toLocaleString('it-IT', { year: 'numeric', month: 'short', day: '2-digit', hour12: false, hour:'2-digit', minute:'2-digit' })}`
83
- }]
84
- }
85
- );
86
-
87
- });
88
- });
89
-
90
- export default config;
91
-
92
-
93
- // versione statica
94
-
95
- // export default [
96
- // {
97
- // input: 'input.js',
98
- // plugins: [
99
- // node_resolve(),
100
- // // commonjs(),
101
- // terser({ compress: { passes: 2 } }),
102
- // ],
103
- // output: [
104
- // {
105
- // file: 'output.min.js',
106
- // format: 'iife',
107
- // sourcemap: true,
108
-
109
- // banner: `/*! xxxx v.${p.version} - Massimo Cassandro ${anno} */`,
110
- // // footer: `//! Released on ${new Date().toLocaleString('it-IT', { year: 'numeric', month: 'short', day: '2-digit', hour12: false, hour:'2-digit', minute:'2-digit' })}`
111
- // }
112
- // ]
113
- // },
114
- // ...
115
- // ];