@massimo-cassandro/minimo 0.6.7 → 0.7.0
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/package.json +1 -1
- package/src/components/sf-macro/sf-macro.js +3 -2
- package/src/custom-properties-default.css +0 -7
- package/src/icons/caret-down-bold.svg +1 -0
- package/design-tokens-src/components/recaptcha.minimo.tokens.jsonc +0 -24
- package/design-tokens-src/components/toast.minimo.tokens.jsonc +0 -29
- package/src/components/alert-autoclose.js +0 -9
- package/src/components/auto-datatable/auto-datatable.css +0 -355
- package/src/components/auto-datatable/auto-datatable.js +0 -154
- package/src/components/create-blurhash-canvas.js +0 -47
- package/src/components/img-viewer-dom-builder.js +0 -196
- package/src/components/modal-alert/flash-alerts.js +0 -32
- package/src/components/modal-content/modal-content.js +0 -152
- package/src/components/modal-content/modal-content.module.css +0 -142
- package/src/components/popup-page/popup-page.css +0 -72
- package/src/components/popup-page/popup-page.js +0 -84
- package/src/components/print-icon.js +0 -51
- package/src/components/recaptcha/recaptcha.css +0 -73
- package/src/components/spinner/TODO spinner-circle.css +0 -54
- package/src/components/spinner/TODO spinner-three-dots.css +0 -14
- package/src/components/spinner/readme.md +0 -1
- package/src/components/spinner/spinner-trailing-dots.css +0 -51
- package/src/components/spinner/spinner-wrapper.css +0 -20
- package/src/components/spinner/spinner.js +0 -30
- package/src/components/toast/toast.js +0 -77
- package/src/components/toast/toast.module.css +0 -59
- package/src/components/vanilla-cookie-consent/cookie-consent.css +0 -20
- package/src/components/vanilla-cookie-consent/cookie-consent.js +0 -76
- package/src/components/vanilla-cookie-consent/render-cookie-list.js +0 -32
- package/src/components/vanilla-cookie-consent/src/cookie-list.js +0 -85
- package/src/components/vanilla-cookie-consent/src/it-translation.js +0 -38
- package/src/components/vanilla-cookie-consent/src/run-analytics.js +0 -54
- package/src/components/vanilla-cookie-consent/src/run-recaptcha.js +0 -71
- package/src/css/forms/select-indicator.svg +0 -3
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* minimo: img-viewer-dom-builder
|
|
3
|
-
* Produce un array da utilizzare con domBuilder per generare un tag `picture`
|
|
4
|
-
*
|
|
5
|
-
* @returns Array
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// TODO implementare getImgInfo (da ada)
|
|
9
|
-
// TODO detect se amabiente local per uso avif
|
|
10
|
-
|
|
11
|
-
/*
|
|
12
|
-
img_viewer_dom_builder({
|
|
13
|
-
viewer_url: 'iviewer',
|
|
14
|
-
sources: [
|
|
15
|
-
{
|
|
16
|
-
src: 'xxx',
|
|
17
|
-
crop: null, // 'x,y,w,h',
|
|
18
|
-
w: 100,
|
|
19
|
-
h: 100,
|
|
20
|
-
imgWidths: [100, 200, 300],
|
|
21
|
-
mq: null, // '(max-width: xxx)'
|
|
22
|
-
},
|
|
23
|
-
...
|
|
24
|
-
],
|
|
25
|
-
imgClassName: null,
|
|
26
|
-
// condition: true | false,
|
|
27
|
-
add2XWidths: false, // true,
|
|
28
|
-
alt_text: '',
|
|
29
|
-
useAvif: false | true,
|
|
30
|
-
// loadingMode: null | 'lazy' | 'eager'
|
|
31
|
-
})
|
|
32
|
-
*/
|
|
33
|
-
export function img_viewer_dom_builder({
|
|
34
|
-
/** url del viewer */
|
|
35
|
-
viewer_url,
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
array dei sorgenti
|
|
39
|
-
deve contenere almeno un oggetto configurato come `source_default`
|
|
40
|
-
l'ultimo oggetto della lista è quello sulla base el quale si costruirà il tag img
|
|
41
|
-
In mancanza di uno degli elementi richiesti (fatta eccezione per `mq` e `crop`),
|
|
42
|
-
il sorgente viene ignorato
|
|
43
|
-
*/
|
|
44
|
-
sources = [], // array dei sorgenti
|
|
45
|
-
|
|
46
|
-
/** se false, il markup non viene generato */
|
|
47
|
-
condition = true,
|
|
48
|
-
|
|
49
|
-
/** se true, alle dimensioni fornite, viene aggiunta la versione 2x */
|
|
50
|
-
add2XWidths = false,
|
|
51
|
-
|
|
52
|
-
/** testo alt */
|
|
53
|
-
alt_text = null,
|
|
54
|
-
|
|
55
|
-
/** classe del tag img */
|
|
56
|
-
imgClassName = null,
|
|
57
|
-
|
|
58
|
-
/** se true viene usato anche il formato avif, oltre a webp e jpg */
|
|
59
|
-
useAvif = false,
|
|
60
|
-
|
|
61
|
-
/** valore dell'attributo loading: eager o lazy */
|
|
62
|
-
loadingMode = null
|
|
63
|
-
}) {
|
|
64
|
-
|
|
65
|
-
if(!viewer_url || !condition) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const originalSourcesLength = (sources?? []).length,
|
|
70
|
-
source_default = {
|
|
71
|
-
id: null, // id per immagini da db
|
|
72
|
-
src: null, // percorso dalla root dell'immagine sorgente
|
|
73
|
-
crop: null, // eventuali coordinate per il crop dell'immagine sorgente
|
|
74
|
-
w: null, // larghezza e altezza dell'immagine da restituire
|
|
75
|
-
h: null,
|
|
76
|
-
imgWidths: [], // dimensioni dell'immagine
|
|
77
|
-
mq: null // media query, necessaria solo per gli oggetti prima dell'ultimo
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
sources = sources.map(item => {
|
|
81
|
-
item = {...source_default, ...item?? {}};
|
|
82
|
-
|
|
83
|
-
if((!item.src && !item.id) || !item.w || !item.h || !item.imgWidths?.length) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return item;
|
|
88
|
-
|
|
89
|
-
}).filter(result => result != null);
|
|
90
|
-
|
|
91
|
-
if(!sources.length || sources.length !== originalSourcesLength) {
|
|
92
|
-
// eslint-disable-next-line no-console
|
|
93
|
-
console.error('`sources` array error');
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// array per gli elementi <source>
|
|
98
|
-
const sourceTagsArray = [],
|
|
99
|
-
srcset_builder = (format, srcsetsArray) => {
|
|
100
|
-
return srcsetsArray.map(src => `${src[0]}${format? `&f=${format}` : ''} ${src[1]}`).join(',');
|
|
101
|
-
},
|
|
102
|
-
formats = (useAvif? ['avif','webp'] : ['webp']);
|
|
103
|
-
|
|
104
|
-
// sono definite fuori dal ciclo forEach perché saranno utilizzate anche dal tag img finale
|
|
105
|
-
let srcsetsArray, sizes;
|
|
106
|
-
|
|
107
|
-
// costruzione array `sourceTagsArray`
|
|
108
|
-
sources.forEach((item, sourceIdx) => {
|
|
109
|
-
|
|
110
|
-
item.imgWidths = item.imgWidths.map(w => add2XWidths? [w, w * 2] : w).flat().toSorted((a,b) => b - a);
|
|
111
|
-
|
|
112
|
-
const isLastSource = sourceIdx === sources.length - 1,
|
|
113
|
-
baseSrc = viewer_url + (item.src? `?src=${encodeURIComponent(item.src)}&` : `/${item.id}?`);
|
|
114
|
-
|
|
115
|
-
srcsetsArray = item.imgWidths.map(w =>{
|
|
116
|
-
const bbHeight = w / (item.w / item.h);
|
|
117
|
-
return [`${baseSrc}bb=${w}x${bbHeight}`, `${w}w`];
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
sizes = item.imgWidths.map((w,idx) => {
|
|
121
|
-
|
|
122
|
-
// la prima dimensione va ignorata (sarà utilizzata nell'iterazione successiva)
|
|
123
|
-
if(idx === 0) {
|
|
124
|
-
return null;
|
|
125
|
-
|
|
126
|
-
} else {
|
|
127
|
-
// elemento `sizes` diverso dal primo e dall'ultimo
|
|
128
|
-
const middle_size_mq = `(${w}px < width <= ${item.imgWidths.at(idx-1)}px) ${item.imgWidths.at(idx-1)}px`;
|
|
129
|
-
|
|
130
|
-
// primo elemento dell'attributo sizes
|
|
131
|
-
if(idx === 1) {
|
|
132
|
-
return `(width > ${w}px) ${item.imgWidths.at(0)}px`;
|
|
133
|
-
|
|
134
|
-
// ultimo
|
|
135
|
-
} else if(idx === item.imgWidths.length - 1) {
|
|
136
|
-
return [
|
|
137
|
-
middle_size_mq,
|
|
138
|
-
`${w}px`
|
|
139
|
-
];
|
|
140
|
-
|
|
141
|
-
// tutti gli altri
|
|
142
|
-
} else {
|
|
143
|
-
return middle_size_mq;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}).filter(s => s != null).flat().join(','); // rimuove elemento null, flat e crea stringa sizes
|
|
147
|
-
|
|
148
|
-
// il formato `null` è riferito a jpeg, che non è necessario indicare esplicitamente
|
|
149
|
-
// ed è utilizzato solo nel caso di presenza di media query per creare il tag source per il formato jpeg,
|
|
150
|
-
// non va inoltre considerato nell'ultimo elemento di source
|
|
151
|
-
// visto che, in questo caso, il formato jpeg viene gestito nel tag `img`
|
|
152
|
-
[...formats, ...(item.mq && !isLastSource? [null] : [])].forEach(format => {
|
|
153
|
-
sourceTagsArray.push({
|
|
154
|
-
tag: 'source',
|
|
155
|
-
attrs: {
|
|
156
|
-
type: format? `image/${format}` : null,
|
|
157
|
-
srcset: srcset_builder(format, srcsetsArray),
|
|
158
|
-
sizes: sizes,
|
|
159
|
-
media: item.mq,
|
|
160
|
-
|
|
161
|
-
// width e height sono necessarie solo in caso di presenza della media query
|
|
162
|
-
// presupponendo che in questi casi l'immagine abbia proporzioni diverse
|
|
163
|
-
// da quelle dell'immagine del tag `img`.
|
|
164
|
-
// In assenza di media query, vengono "ereditate" quelle indicate in `img`
|
|
165
|
-
width: item.mq? item.w : null,
|
|
166
|
-
height: item.mq? item.h : null,
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const img_source_obj = sources.at(-1);
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
tag: 'picture',
|
|
177
|
-
condition: condition,
|
|
178
|
-
children: [
|
|
179
|
-
...sourceTagsArray,
|
|
180
|
-
{
|
|
181
|
-
tag: 'img',
|
|
182
|
-
className: imgClassName,
|
|
183
|
-
attrs: {
|
|
184
|
-
alt: alt_text,
|
|
185
|
-
width: img_source_obj.w,
|
|
186
|
-
height: img_source_obj.h,
|
|
187
|
-
srcset: srcset_builder(null, srcsetsArray),
|
|
188
|
-
sizes: sizes,
|
|
189
|
-
src: srcsetsArray.at(-1)[0],
|
|
190
|
-
loading: loadingMode,
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
]
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { mAlert } from './modal-alert.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/*
|
|
5
|
-
twig message labels:
|
|
6
|
-
- success
|
|
7
|
-
- notice
|
|
8
|
-
- error
|
|
9
|
-
- warning
|
|
10
|
-
*/
|
|
11
|
-
document.querySelectorAll('.flash-alert').forEach(item => {
|
|
12
|
-
|
|
13
|
-
mAlert({
|
|
14
|
-
// test
|
|
15
|
-
// type : 'confirm',
|
|
16
|
-
// timer: null,
|
|
17
|
-
|
|
18
|
-
type : item.dataset.label === 'notice'? 'warning' : item.dataset.label,
|
|
19
|
-
// title : item.message,
|
|
20
|
-
mes : item.dataset.message
|
|
21
|
-
// use_warning_icon: true, // solo confirm
|
|
22
|
-
// ok_btn_text: 'OK',
|
|
23
|
-
// cancel_btn_text: 'Annulla',
|
|
24
|
-
// callback: function(esito) {}, // confirm: console.log( esito? 'Confermato' : 'Annullato')
|
|
25
|
-
// timer: 4000 // ms
|
|
26
|
-
// extra_btn: '<button type="button" data-confirm-result="annulla" class="stop-btn btn btn-confirm">Annulla</button>',
|
|
27
|
-
// extra_btn_selector: '.stop-btn',
|
|
28
|
-
// extra_btn_focus: true,
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
});
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { domBuilder, classnames } from '@node_modules/@massimo-cassandro/js-utilities/index.js';
|
|
2
|
-
import { spinner } from '@minimo/spinner.js';
|
|
3
|
-
import * as styles from './modal-content.module.css?inline';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement
|
|
9
|
-
|
|
10
|
-
export function modalContent({
|
|
11
|
-
|
|
12
|
-
/** iframe | content */
|
|
13
|
-
mode = 'iframe',
|
|
14
|
-
|
|
15
|
-
/** dialog extra class */
|
|
16
|
-
dialogClassName = null,
|
|
17
|
-
|
|
18
|
-
/** iframe url */
|
|
19
|
-
iframeUrl = null,
|
|
20
|
-
|
|
21
|
-
/** content string (markup) o array */
|
|
22
|
-
content = null,
|
|
23
|
-
|
|
24
|
-
/** content extra classname */
|
|
25
|
-
contentClassName = null,
|
|
26
|
-
|
|
27
|
-
/** dimensione modal: full, large, medium o small */
|
|
28
|
-
size = 'large',
|
|
29
|
-
|
|
30
|
-
/** padding: std (var(--size-md) 0) o none */
|
|
31
|
-
padding = 'std'
|
|
32
|
-
}) {
|
|
33
|
-
|
|
34
|
-
if(!['content', 'iframe'].includes(mode)) {
|
|
35
|
-
throw `modalContent: parametro 'mode' non corretto (${mode})`;
|
|
36
|
-
}
|
|
37
|
-
if(!iframeUrl && mode === 'iframe') {
|
|
38
|
-
throw 'modalContent: parametro `iframeUrl` mancante';
|
|
39
|
-
}
|
|
40
|
-
if(content == null && mode === 'content') {
|
|
41
|
-
throw 'modalContent: parametro `content` mancante';
|
|
42
|
-
}
|
|
43
|
-
if(!['full', 'large', 'medium', 'small'].includes(size)) {
|
|
44
|
-
throw `modalContent: parametro 'size' non corretto (${size})`;
|
|
45
|
-
}
|
|
46
|
-
if(!['std', 'none'].includes(padding)) {
|
|
47
|
-
throw `modalContent: parametro 'padding' non corretto (${padding})`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let dialog_element, dialog_inner, iframe_element = null, content_element = null;
|
|
51
|
-
const iframeLoadEventHandler = () => {
|
|
52
|
-
dialog_element.classList.add(styles.on);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
if(!dialog_element) {
|
|
56
|
-
|
|
57
|
-
domBuilder([
|
|
58
|
-
{
|
|
59
|
-
tag: 'dialog',
|
|
60
|
-
className: styles.dialog,
|
|
61
|
-
attrs: {
|
|
62
|
-
'closedby': 'any'
|
|
63
|
-
},
|
|
64
|
-
children: [
|
|
65
|
-
{
|
|
66
|
-
tag: 'button',
|
|
67
|
-
className: styles.closeButton, // TODO standardizzare close btn
|
|
68
|
-
attrs: {
|
|
69
|
-
'aria-label': 'Chiudi'
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
className: styles.dialogInner,
|
|
74
|
-
children: [
|
|
75
|
-
{
|
|
76
|
-
className: styles.modalSpinner,
|
|
77
|
-
content: spinner({container: null, withOverlay: false })
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
}
|
|
84
|
-
], document.body);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
dialog_element = document.querySelector(`.${styles.dialog}`);
|
|
88
|
-
dialog_inner = dialog_element.querySelector(`.${styles.dialogInner}`);
|
|
89
|
-
|
|
90
|
-
dialog_element.querySelector(`.${styles.closeButton}`).addEventListener('click', () => {
|
|
91
|
-
dialog_element.close();
|
|
92
|
-
}, false);
|
|
93
|
-
|
|
94
|
-
// listener chiusura
|
|
95
|
-
dialog_element.addEventListener('close', () => {
|
|
96
|
-
|
|
97
|
-
iframe_element?.removeEventListener('load', iframeLoadEventHandler, false);
|
|
98
|
-
iframe_element?.remove();
|
|
99
|
-
content_element?.remove();
|
|
100
|
-
|
|
101
|
-
document.body.classList.remove('overflow-hidden');
|
|
102
|
-
dialog_element.classList.remove(styles.on);
|
|
103
|
-
}, false);
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// aggiunta classi extra
|
|
109
|
-
dialog_element.className = classnames(
|
|
110
|
-
styles.dialog,
|
|
111
|
-
dialogClassName,
|
|
112
|
-
styles[`size-${size}`],
|
|
113
|
-
styles[`padding-${padding}`]
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
domBuilder([
|
|
117
|
-
{
|
|
118
|
-
condition: mode === 'iframe',
|
|
119
|
-
className: styles.iframeEl,
|
|
120
|
-
tag: 'iframe',
|
|
121
|
-
attrs: {
|
|
122
|
-
src: ''
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
condition: mode === 'content',
|
|
127
|
-
className: classnames(styles.contentEl, contentClassName),
|
|
128
|
-
content: (content && !Array.isArray(content))? content : null,
|
|
129
|
-
children: (content && Array.isArray(content))? content : null
|
|
130
|
-
}
|
|
131
|
-
], dialog_inner);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
document.body.classList.add('overflow-hidden');
|
|
135
|
-
dialog_element.showModal();
|
|
136
|
-
dialog_element.focus();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if(mode === 'iframe') {
|
|
140
|
-
iframe_element = dialog_element.querySelector(`.${styles.iframeEl}`);
|
|
141
|
-
iframe_element.src = iframeUrl;
|
|
142
|
-
|
|
143
|
-
// listener load per i frame
|
|
144
|
-
iframe_element?.addEventListener('load', iframeLoadEventHandler, false);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
} else if (mode === 'content') {
|
|
148
|
-
content_element = dialog_element.querySelector(`.${styles.contentEl}`);
|
|
149
|
-
dialog_element.classList.add(styles.on);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/* TODO custom props nel file generale */
|
|
2
|
-
/* TODO prevedere opzione con bordo del pulsante di chiusura (NB: si disallinea) */
|
|
3
|
-
/* TODO cambiare icona chiusura con svg? */
|
|
4
|
-
/* TODO aggiungere wrapper intorno a dialogInner (a filo con il dialog) per la scroll bar */
|
|
5
|
-
|
|
6
|
-
.dialog { /* dialog */
|
|
7
|
-
--modal-border-radius: var(--radius-md, 1.2rem);
|
|
8
|
-
position: fixed;
|
|
9
|
-
max-width: 80dvw;
|
|
10
|
-
max-height: 90dvh;
|
|
11
|
-
padding: 0;
|
|
12
|
-
margin: auto;
|
|
13
|
-
overflow: visible;
|
|
14
|
-
background-color: var(--body-bg-color, #fff);
|
|
15
|
-
border: none;
|
|
16
|
-
border-radius: var(--modal-border-radius);
|
|
17
|
-
box-shadow: 0 0 2rem .5rem rgb(0 0 0 / .5);
|
|
18
|
-
transition: scale .2s ease-out;
|
|
19
|
-
scale: 0;
|
|
20
|
-
|
|
21
|
-
/* stylelint-disable selector-class-pattern */
|
|
22
|
-
&.size-full {
|
|
23
|
-
width: 80dvw;
|
|
24
|
-
height: 90dvh;
|
|
25
|
-
}
|
|
26
|
-
/* dimensioni std -> size == 'large' */
|
|
27
|
-
&.size-large {
|
|
28
|
-
width: 50rem; /* 800px */
|
|
29
|
-
height: auto;
|
|
30
|
-
}
|
|
31
|
-
&.size-medium {
|
|
32
|
-
width: 37.5rem; /* 600px */
|
|
33
|
-
height: 37.5rem;
|
|
34
|
-
}
|
|
35
|
-
&.size-small {
|
|
36
|
-
width: 32rem; /* ~500 x 400 */
|
|
37
|
-
height: 25rem;
|
|
38
|
-
}
|
|
39
|
-
/* stylelint-enable selector-class-pattern */
|
|
40
|
-
|
|
41
|
-
&.on {
|
|
42
|
-
scale: 1;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
&::backdrop {
|
|
46
|
-
overscroll-behavior: contain;
|
|
47
|
-
background-color: rgb(0 0 0 / .7);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.dialogInner {
|
|
53
|
-
width: 100%;
|
|
54
|
-
height: 100%;
|
|
55
|
-
padding-inline-end: var(--size-md);
|
|
56
|
-
overflow-x: hidden;
|
|
57
|
-
overflow-y: auto;
|
|
58
|
-
/* scrollbar-gutter: stable; */
|
|
59
|
-
border-radius: var(--modal-border-radius);
|
|
60
|
-
|
|
61
|
-
/* stylelint-disable selector-class-pattern */
|
|
62
|
-
.padding-std & {
|
|
63
|
-
padding: var(--size-md) 0;
|
|
64
|
-
}
|
|
65
|
-
.padding-none & {
|
|
66
|
-
padding: 0;
|
|
67
|
-
}
|
|
68
|
-
/* stylelint-enable selector-class-pattern */
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.modalSpinner {
|
|
72
|
-
position: relative;
|
|
73
|
-
padding-block-start: var(--size-2xl);
|
|
74
|
-
|
|
75
|
-
.dialog.on & {
|
|
76
|
-
display: none;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.iframeEl, .contentEl {
|
|
81
|
-
width: 100%;
|
|
82
|
-
overscroll-behavior: contain;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.iframeEl {
|
|
86
|
-
height: 100%;
|
|
87
|
-
padding: 0;
|
|
88
|
-
margin: 0;
|
|
89
|
-
border: none;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.contentEl {
|
|
93
|
-
min-height: 100%;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.closeButton {
|
|
97
|
-
--btn-color: var(--secondary-fg, #000);
|
|
98
|
-
--btn-bg-color: var(--secondary, #fff);
|
|
99
|
-
--btn-hover-color: var(--secondary, #fff);
|
|
100
|
-
--btn-hover-bg-color: var(--secondary-fg, #000);
|
|
101
|
-
--icon-size: 2.5rem;
|
|
102
|
-
--btn-padding: var(--size-xs, .5rem);
|
|
103
|
-
--icon-bars-thickness: 3px;
|
|
104
|
-
|
|
105
|
-
position: absolute;
|
|
106
|
-
top: calc(-1 * var(--icon-size) / 3);
|
|
107
|
-
right: calc(-1 * var(--icon-size) / 3);
|
|
108
|
-
display: block;
|
|
109
|
-
width: var(--icon-size);
|
|
110
|
-
height: var(--icon-size);
|
|
111
|
-
padding: var(--btn-padding);
|
|
112
|
-
color: var(--btn-color);
|
|
113
|
-
cursor: pointer;
|
|
114
|
-
background-color: var(--btn-bg-color);
|
|
115
|
-
/* border: var(--icon-bars-thickness) solid currentColor; */
|
|
116
|
-
border: none;
|
|
117
|
-
border-radius: 50%;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
&:hover {
|
|
121
|
-
--btn-color: var(--btn-hover-color);
|
|
122
|
-
--btn-bg-color: var(--btn-hover-bg-color);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
&::before, &::after {
|
|
126
|
-
position: absolute;
|
|
127
|
-
top: 50%;
|
|
128
|
-
left: var(--btn-padding);
|
|
129
|
-
display: block;
|
|
130
|
-
width: calc(var(--icon-size) - (var(--btn-padding) * 2));
|
|
131
|
-
height: var(--icon-bars-thickness);
|
|
132
|
-
content: '';
|
|
133
|
-
background: currentColor;
|
|
134
|
-
}
|
|
135
|
-
&::before {
|
|
136
|
-
transform: translateY(-50%) rotate(45deg);
|
|
137
|
-
}
|
|
138
|
-
&::after {
|
|
139
|
-
transform: translateY(-50%) rotate(-45deg);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
.content-dialog {
|
|
2
|
-
display: none;
|
|
3
|
-
width: 90dvw;
|
|
4
|
-
max-width: 900px;
|
|
5
|
-
height: 90dvh;
|
|
6
|
-
padding: 1rem;
|
|
7
|
-
margin: auto;
|
|
8
|
-
background-color: var(--body-background-color);
|
|
9
|
-
border: none;
|
|
10
|
-
border-radius: var(--radius-lg);
|
|
11
|
-
box-shadow: var(--shadow-4);
|
|
12
|
-
transform: translateY(-200vh);
|
|
13
|
-
animation: dialog-in .3s ease-out;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
&[open] {
|
|
17
|
-
display: block;
|
|
18
|
-
transform: none;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
&::backdrop {
|
|
22
|
-
overscroll-behavior: contain;
|
|
23
|
-
background-color: color-mix(in srgb, #000 40%, transparent);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.content-dialog-close {
|
|
28
|
-
position: sticky;
|
|
29
|
-
top: 0;
|
|
30
|
-
z-index: 1;
|
|
31
|
-
align-self: flex-end;
|
|
32
|
-
|
|
33
|
-
button {
|
|
34
|
-
top: -.5rem;
|
|
35
|
-
right: -.5rem;
|
|
36
|
-
width: 2rem;
|
|
37
|
-
aspect-ratio: 1;
|
|
38
|
-
padding: 4px;
|
|
39
|
-
background-color: var(--body-background-color);
|
|
40
|
-
border: 1px solid var(--neutral-100);
|
|
41
|
-
border-radius: 50%;
|
|
42
|
-
box-shadow: var(--shadow-3);
|
|
43
|
-
|
|
44
|
-
@media (hover: hover) { /* @media (any-hover: hover) { */
|
|
45
|
-
&:hover {
|
|
46
|
-
background-color: color-mix(in srgb, var(--text-color) 10%, transparent);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
svg {
|
|
53
|
-
width: 1.5rem;
|
|
54
|
-
aspect-ratio: 1;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.content-dialog-inner {
|
|
59
|
-
position: relative;
|
|
60
|
-
z-index: 0;
|
|
61
|
-
display: flex;
|
|
62
|
-
flex-flow: column nowrap;
|
|
63
|
-
gap: .4rem;
|
|
64
|
-
align-items: stretch;
|
|
65
|
-
justify-content: flex-start;
|
|
66
|
-
isolation: isolate;
|
|
67
|
-
}
|
|
68
|
-
.content-dialog-body {
|
|
69
|
-
position: relative;
|
|
70
|
-
flex: 1;
|
|
71
|
-
overflow: auto;
|
|
72
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// TODO completare
|
|
2
|
-
|
|
3
|
-
import './popup-page.css';
|
|
4
|
-
import xIcon from '@icone/x.svg?inline';
|
|
5
|
-
import { spinner } from '../spinner/spinner';
|
|
6
|
-
/**
|
|
7
|
-
`indicator_class`: classe da aggiungere al wrapper per indicare in modo univoco il dialog
|
|
8
|
-
*/
|
|
9
|
-
export function content_dialog_markup(indicator_class) {
|
|
10
|
-
|
|
11
|
-
return `<dialog class="${indicator_class} content-dialog">` +
|
|
12
|
-
'<div class="content-dialog-inner">' +
|
|
13
|
-
'<div class="content-dialog-close">' +
|
|
14
|
-
`<button type="button" class="btn-reset content-dialog-close-btn" aria-label="Chiudi finestra">${xIcon}</button>` +
|
|
15
|
-
'</div>' +
|
|
16
|
-
'<div class="content-dialog-body"></div>' +
|
|
17
|
-
'</div>'+
|
|
18
|
-
'</dialog>';
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
`content_url` : url del file contenente il contenuto da caricare via ajax
|
|
24
|
-
`indicator_class`: classe da aggiungere al wrapper per indicare in modo univoco il dialog
|
|
25
|
-
`once_callback` : callback da invocare solo la prima volta, alla creazione del dialog
|
|
26
|
-
*/
|
|
27
|
-
let dialog_list = {};
|
|
28
|
-
export async function show_ajax_content_dialog({content_url, class_identifier, once_callback = null}){
|
|
29
|
-
|
|
30
|
-
const close_dialog = (class_identifier) => {
|
|
31
|
-
dialog_list[class_identifier].close();
|
|
32
|
-
document.body.classList.remove('overflow-hidden');
|
|
33
|
-
}
|
|
34
|
-
,open_dialog = (class_identifier) => {
|
|
35
|
-
dialog_list[class_identifier].showModal();
|
|
36
|
-
document.body.classList.add('overflow-hidden');
|
|
37
|
-
}
|
|
38
|
-
;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if(!Object.keys(dialog_list).includes(class_identifier)) {
|
|
42
|
-
document.body.insertAdjacentHTML('beforeend',
|
|
43
|
-
content_dialog_markup(class_identifier)
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
const dialog = document.querySelector(`.content-dialog.${class_identifier}`);
|
|
47
|
-
dialog_list[class_identifier] = dialog;
|
|
48
|
-
dialog.querySelector('.content-dialog-close-btn').addEventListener('click', () => {
|
|
49
|
-
close_dialog(class_identifier);
|
|
50
|
-
}, false);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const dialog_body = dialog.querySelector('.content-dialog-body');
|
|
54
|
-
dialog_body.innerHTML = spinner();
|
|
55
|
-
open_dialog(class_identifier);
|
|
56
|
-
|
|
57
|
-
const url = content_url;
|
|
58
|
-
(async () => {
|
|
59
|
-
const response = await fetch(url),
|
|
60
|
-
content = await response.text();
|
|
61
|
-
return content;
|
|
62
|
-
})()
|
|
63
|
-
.then(content => {
|
|
64
|
-
dialog_body.innerHTML = content;
|
|
65
|
-
|
|
66
|
-
if(once_callback && typeof once_callback === 'function') {
|
|
67
|
-
once_callback(dialog_body);
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
.catch(err => {
|
|
71
|
-
/* eslint-disable no-console */
|
|
72
|
-
console.error(url);
|
|
73
|
-
console.error(err);
|
|
74
|
-
/* eslint-enable no-console */
|
|
75
|
-
|
|
76
|
-
alert('Si è verificato un errore.\n'+
|
|
77
|
-
'Ricarica la pagina e ripeti l’operazione');
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
} else {
|
|
81
|
-
open_dialog(class_identifier);
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
}
|