mypgs 1.1.5 → 1.3.2
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/assets/javascript/_imports.js +25 -0
- package/assets/javascript/_pgs.js +37 -1
- package/assets/javascript/components/_accordion.js +105 -66
- package/assets/javascript/components/_dropdown.js +48 -3
- package/assets/javascript/components/_menu.js +71 -6
- package/assets/javascript/components/_modals.js +45 -3
- package/assets/javascript/components/_notifications.js +163 -0
- package/assets/javascript/components/_slides.js +12 -1
- package/assets/javascript/components/_stepTabs.js +17 -4
- package/assets/javascript/components/_steps.js +33 -6
- package/assets/javascript/functions/_formValidate.js +4 -5
- package/assets/javascript/index.js +8 -4
- package/assets/javascript/patterns/_header.js +1 -1
- package/assets/javascript/pgs.d.ts +5 -1
- package/assets/scss/components/_logo.scss +1 -1
- package/assets/scss/layout/_pageShell.scss +15 -20
- package/dist/css/index.css +8 -8
- package/dist/css/index.css.map +1 -1
- package/dist/css/index.min.css +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/javascript/index.js +836 -268
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/index.min.js +1 -1
- package/package.json +7 -2
- package/assets/javascript/components/_exeNotifications.js +0 -85
- package/assets/javascript/functions/_notifications.js +0 -74
- package/assets/javascript/functions/_sendForm.js +0 -100
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { pgs } from "./_pgs.js";
|
|
2
|
+
|
|
3
|
+
import { PGS_accordion } from "./components/_accordion.js";
|
|
4
|
+
import { PGS_dropdown } from "./components/_dropdown.js";
|
|
5
|
+
import { PGS_menu } from "./components/_menu.js";
|
|
6
|
+
import { PGS_modal } from "./components/_modals.js";
|
|
7
|
+
import { PGS_notification } from "./components/_notifications.js";
|
|
8
|
+
import { PGS_slides } from "./components/_slides.js";
|
|
9
|
+
import { PGS_stepTabs } from "./components/_stepTabs.js";
|
|
10
|
+
import { PGS_steps } from "./components/_steps.js";
|
|
11
|
+
import { PGS_formValidate } from "./functions/_formValidate.js";
|
|
12
|
+
import { PGS_scrollHorizontal } from "./functions/_scrollY.js";
|
|
13
|
+
|
|
14
|
+
pgs.registerImport({
|
|
15
|
+
PGS_accordion,
|
|
16
|
+
PGS_dropdown,
|
|
17
|
+
PGS_menu,
|
|
18
|
+
PGS_modal,
|
|
19
|
+
PGS_notification,
|
|
20
|
+
PGS_slides,
|
|
21
|
+
PGS_stepTabs,
|
|
22
|
+
PGS_steps,
|
|
23
|
+
PGS_formValidate,
|
|
24
|
+
PGS_scrollHorizontal,
|
|
25
|
+
});
|
|
@@ -224,6 +224,42 @@ export function pgs(root) {
|
|
|
224
224
|
return api;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
const PGS_IMPORTS = {};
|
|
228
|
+
|
|
229
|
+
function registerImportModule(name, module) {
|
|
230
|
+
const key = String(name || "").trim().replace(/^pgs[_-\s]*/i, "").toLowerCase();
|
|
228
231
|
|
|
232
|
+
if (!key) throw new TypeError("pgs.registerImport(...modules): ogni modulo deve avere name o PGS_name");
|
|
233
|
+
|
|
234
|
+
PGS_IMPORTS[key] = {
|
|
235
|
+
name,
|
|
236
|
+
module
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
pgs.registerImport = function (...modules) {
|
|
241
|
+
modules.flat().forEach(item => {
|
|
242
|
+
if (item && typeof item === "object" && !item.PGS_name && !item.name) {
|
|
243
|
+
Object.entries(item).forEach(([name, module]) => registerImportModule(name, module));
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
229
246
|
|
|
247
|
+
registerImportModule(item?.PGS_name || item?.name, item);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return pgs;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
pgs.import = function (...names) {
|
|
254
|
+
return names.flat().reduce((imports, name) => {
|
|
255
|
+
const key = String(name || "").trim().replace(/^pgs[_-\s]*/i, "").toLowerCase();
|
|
256
|
+
const item = PGS_IMPORTS[key];
|
|
257
|
+
|
|
258
|
+
if (!item) throw new Error(`pgs.import(): modulo "${name}" non registrato`);
|
|
259
|
+
|
|
260
|
+
imports[item.name] = item.module;
|
|
261
|
+
return imports;
|
|
262
|
+
}, {});
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
globalThis.pgs ??= pgs;
|
|
@@ -1,77 +1,116 @@
|
|
|
1
|
-
//= ACCORDION
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
function closeOltherAccordion() {
|
|
37
|
-
for (const otherLi of allAccordion) {
|
|
38
|
-
if (otherLi === accordion) continue;
|
|
39
|
-
|
|
40
|
-
const otherBtn = pgs(otherLi).querySelector("accordion-button");
|
|
41
|
-
const otherContent = pgs(otherLi).querySelector("accordion-content");
|
|
42
|
-
if (!otherBtn || !otherContent) continue;
|
|
43
|
-
|
|
44
|
-
pgs(otherLi).state().remove("open");
|
|
45
|
-
accordionAccessibility(false, otherBtn, otherContent);
|
|
1
|
+
//= ACCORDION
|
|
2
|
+
const API = new WeakMap();
|
|
3
|
+
|
|
4
|
+
export function PGS_accordion_init(root = document) {
|
|
5
|
+
pgs(root).querySelectorAll("accordion").forEach((accordion, index) => {
|
|
6
|
+
if (API.has(accordion)) return;
|
|
7
|
+
|
|
8
|
+
const BUTTON = pgs(accordion).querySelector("accordion-button");
|
|
9
|
+
const CONTENT = pgs(accordion).querySelector("accordion-content");
|
|
10
|
+
if (!BUTTON || !CONTENT) return;
|
|
11
|
+
|
|
12
|
+
//== ID univoci per aria-controls / aria-labelledby
|
|
13
|
+
const ID = index + 1;
|
|
14
|
+
const btnId = `acc-btn-${ID}`;
|
|
15
|
+
const panelId = `acc-panel-${ID}`;
|
|
16
|
+
|
|
17
|
+
//== Stato iniziale
|
|
18
|
+
const isOpenInit = pgs(accordion).state.contains("open");
|
|
19
|
+
|
|
20
|
+
//== Accessibilità (setup una volta)
|
|
21
|
+
BUTTON.setAttribute("role", "button");
|
|
22
|
+
BUTTON.setAttribute("tabindex", "0");
|
|
23
|
+
BUTTON.setAttribute("id", btnId);
|
|
24
|
+
BUTTON.setAttribute("aria-controls", panelId);
|
|
25
|
+
|
|
26
|
+
CONTENT.setAttribute("id", panelId);
|
|
27
|
+
CONTENT.setAttribute("role", "region");
|
|
28
|
+
CONTENT.setAttribute("aria-labelledby", btnId);
|
|
29
|
+
|
|
30
|
+
//+ Accessibility (applica stato aperto/chiuso)
|
|
31
|
+
function accordionAccessibility(isOpen, button, content) {
|
|
32
|
+
const text = (button?.textContent || "").trim().replace(/\s+/g, " ");
|
|
33
|
+
button.setAttribute("aria-label", `${isOpen ? "Chiudi" : "Apri"} ${text || "sezione"}`);
|
|
34
|
+
button.setAttribute("aria-expanded", String(isOpen));
|
|
35
|
+
content.hidden = !isOpen;
|
|
46
36
|
}
|
|
47
|
-
}
|
|
48
37
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
//+ Chiudi tutti gli altri
|
|
39
|
+
function closeOltherAccordion() {
|
|
40
|
+
for (const otherLi of pgs(document).querySelectorAll("accordion")) {
|
|
41
|
+
if (otherLi === accordion) continue;
|
|
53
42
|
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
const otherBtn = pgs(otherLi).querySelector("accordion-button");
|
|
44
|
+
const otherContent = pgs(otherLi).querySelector("accordion-content");
|
|
45
|
+
if (!otherBtn || !otherContent) continue;
|
|
56
46
|
|
|
57
|
-
|
|
47
|
+
pgs(otherLi).state().remove("open");
|
|
48
|
+
accordionAccessibility(false, otherBtn, otherContent);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//+ FN ACCORDION
|
|
53
|
+
function accordionFunction() {
|
|
54
|
+
const isOpen = pgs(accordion).state.contains("open");
|
|
55
|
+
const nowOpen = !isOpen;
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
57
|
+
pgs(accordion).state.toggle("open", nowOpen);
|
|
58
|
+
accordionAccessibility(nowOpen, BUTTON, CONTENT);
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
closeOltherAccordion();
|
|
61
|
+
|
|
62
|
+
//== scroll to view
|
|
63
|
+
if (nowOpen) setTimeout(() => accordion.scrollIntoView({ block: "nearest", inline: "nearest" }), 100);
|
|
64
|
+
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
function open() {
|
|
67
|
+
if (!pgs(accordion).state.contains("open")) accordionFunction();
|
|
68
|
+
}
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
72
|
-
e.preventDefault();
|
|
73
|
-
accordionFunction();
|
|
70
|
+
function close() {
|
|
71
|
+
if (pgs(accordion).state.contains("open")) accordionFunction();
|
|
74
72
|
}
|
|
73
|
+
|
|
74
|
+
// applica stato iniziale
|
|
75
|
+
accordionAccessibility(isOpenInit, BUTTON, CONTENT);
|
|
76
|
+
|
|
77
|
+
//- Eventi
|
|
78
|
+
BUTTON.addEventListener("click", accordionFunction);
|
|
79
|
+
|
|
80
|
+
//- Tastiera: Enter / Space
|
|
81
|
+
BUTTON.addEventListener("keydown", (e) => {
|
|
82
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
accordionFunction();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
API.set(accordion, {
|
|
89
|
+
element: accordion,
|
|
90
|
+
button: BUTTON,
|
|
91
|
+
content: CONTENT,
|
|
92
|
+
open,
|
|
93
|
+
close,
|
|
94
|
+
toggle: accordionFunction,
|
|
95
|
+
refresh: () => {
|
|
96
|
+
PGS_accordion_init(accordion.parentNode || document);
|
|
97
|
+
return API.get(accordion);
|
|
98
|
+
},
|
|
99
|
+
isOpen: () => pgs(accordion).state.contains("open"),
|
|
100
|
+
});
|
|
75
101
|
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//# INIT
|
|
105
|
+
PGS_accordion_init();
|
|
106
|
+
|
|
107
|
+
//# API
|
|
108
|
+
export function PGS_accordion_api(selector) {
|
|
109
|
+
return API.get(selector);
|
|
110
|
+
}
|
|
76
111
|
|
|
77
|
-
|
|
112
|
+
export const PGS_accordion = {
|
|
113
|
+
PGS_name: "PGS_accordion",
|
|
114
|
+
init: PGS_accordion_init,
|
|
115
|
+
api: PGS_accordion_api
|
|
116
|
+
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// + dropdown (Popover API)
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const API = new WeakMap();
|
|
3
|
+
|
|
4
|
+
export function PGS_dropdown_init(root = document) {
|
|
5
|
+
pgs(root).querySelectorAll("dropdown").forEach((DROPDOWN, index) => {
|
|
6
|
+
if (API.has(DROPDOWN)) return;
|
|
7
|
+
|
|
4
8
|
const BUTTON = pgs(DROPDOWN).querySelector("dropdown-button");
|
|
5
9
|
const CONTENT = pgs(DROPDOWN).querySelector("dropdown-content");
|
|
6
10
|
|
|
@@ -101,8 +105,49 @@ export function pgs_dropdown() {
|
|
|
101
105
|
window.addEventListener("scroll", () => {
|
|
102
106
|
if (CONTENT.matches(":popover-open")) updatePopoverPosition();
|
|
103
107
|
}, true);
|
|
108
|
+
|
|
109
|
+
function open() {
|
|
110
|
+
if (CONTENT.matches(":popover-open")) return;
|
|
111
|
+
updatePopoverPosition();
|
|
112
|
+
CONTENT.showPopover();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function close() {
|
|
116
|
+
if (!CONTENT.matches(":popover-open")) return;
|
|
117
|
+
CONTENT.hidePopover();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function toggle() {
|
|
121
|
+
CONTENT.matches(":popover-open") ? close() : open();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
API.set(DROPDOWN, {
|
|
125
|
+
element: DROPDOWN,
|
|
126
|
+
button: BUTTON,
|
|
127
|
+
content: CONTENT,
|
|
128
|
+
open,
|
|
129
|
+
close,
|
|
130
|
+
toggle,
|
|
131
|
+
updatePosition: updatePopoverPosition,
|
|
132
|
+
refresh: () => {
|
|
133
|
+
PGS_dropdown_init(DROPDOWN.parentNode || document);
|
|
134
|
+
return API.get(DROPDOWN);
|
|
135
|
+
},
|
|
136
|
+
isOpen: () => CONTENT.matches(":popover-open"),
|
|
137
|
+
});
|
|
104
138
|
});
|
|
105
139
|
}
|
|
106
140
|
|
|
107
141
|
// # INIT
|
|
108
|
-
|
|
142
|
+
PGS_dropdown_init();
|
|
143
|
+
|
|
144
|
+
// # API
|
|
145
|
+
export function PGS_dropdown_api(selector) {
|
|
146
|
+
return API.get(selector);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const PGS_dropdown = {
|
|
150
|
+
PGS_name: "PGS_dropdown",
|
|
151
|
+
init: PGS_dropdown_init,
|
|
152
|
+
api: PGS_dropdown_api
|
|
153
|
+
};
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PGS_dropdown_init, PGS_dropdown_api } from "./_dropdown";
|
|
2
|
+
|
|
3
|
+
const API = new WeakMap();
|
|
2
4
|
|
|
3
5
|
//= DROP DOWN MENU
|
|
4
|
-
export function
|
|
6
|
+
export function PGS_menu_init(root = document) {
|
|
5
7
|
|
|
6
|
-
pgs(
|
|
8
|
+
pgs(root).querySelectorAll('menu-horizontal').forEach(MENU => {
|
|
9
|
+
if (API.has(MENU)) return;
|
|
7
10
|
|
|
8
11
|
MENU.querySelectorAll('nav > ul > li.menu-item-has-children').forEach(li => {
|
|
9
12
|
if (li.querySelector("ul")) {
|
|
10
13
|
const ul = li.querySelector("ul");
|
|
14
|
+
if (pgs(li).querySelector("dropdown-button")) return;
|
|
11
15
|
|
|
12
16
|
const button = document.createElement("button");
|
|
13
17
|
button.className = "icon-down";
|
|
@@ -22,14 +26,28 @@ export function PGS_menu() {
|
|
|
22
26
|
pgs(ul).add("menu-vertical")
|
|
23
27
|
}
|
|
24
28
|
});
|
|
29
|
+
|
|
30
|
+
API.set(MENU, {
|
|
31
|
+
element: MENU,
|
|
32
|
+
type: "horizontal",
|
|
33
|
+
items: () => Array.from(MENU.querySelectorAll('nav > ul > li')),
|
|
34
|
+
submenus: () => Array.from(MENU.querySelectorAll('.menu-item-has-children > ul')),
|
|
35
|
+
dropdowns: () => Array.from(MENU.querySelectorAll('.menu-item-has-children')).map(PGS_dropdown_api).filter(Boolean),
|
|
36
|
+
refresh: () => {
|
|
37
|
+
PGS_menu_init(MENU.parentNode || document);
|
|
38
|
+
return API.get(MENU);
|
|
39
|
+
},
|
|
40
|
+
});
|
|
25
41
|
});
|
|
26
42
|
|
|
27
|
-
pgs(
|
|
43
|
+
pgs(root).querySelectorAll('menu-vertical').forEach(MENU => {
|
|
44
|
+
if (API.has(MENU)) return;
|
|
28
45
|
|
|
29
46
|
MENU.querySelectorAll('.menu-item-has-children').forEach((li, index) => {
|
|
30
47
|
const ul = li.querySelector("ul");
|
|
31
48
|
|
|
32
49
|
if (!ul) return
|
|
50
|
+
if (li.querySelector(":scope > button")) return;
|
|
33
51
|
|
|
34
52
|
const button = document.createElement("button");
|
|
35
53
|
button.className = "icon-down buttonIcon";
|
|
@@ -64,6 +82,42 @@ export function PGS_menu() {
|
|
|
64
82
|
});
|
|
65
83
|
});
|
|
66
84
|
|
|
85
|
+
function submenu(index) {
|
|
86
|
+
return MENU.querySelectorAll('.menu-item-has-children > ul')[index];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function setSubmenu(index, open) {
|
|
90
|
+
const ul = submenu(index);
|
|
91
|
+
const button = ul?.parentElement?.querySelector(":scope > button");
|
|
92
|
+
if (!ul || !button) return;
|
|
93
|
+
|
|
94
|
+
pgs(ul).state.toggle("open", open);
|
|
95
|
+
button.setAttribute("aria-expanded", String(open));
|
|
96
|
+
button.setAttribute("aria-label", open ? "Chiudi sottomenu" : "Apri sottomenu");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
API.set(MENU, {
|
|
100
|
+
element: MENU,
|
|
101
|
+
type: "vertical",
|
|
102
|
+
items: () => Array.from(MENU.querySelectorAll(':scope > li')),
|
|
103
|
+
submenus: () => Array.from(MENU.querySelectorAll('.menu-item-has-children > ul')),
|
|
104
|
+
openSubmenu: (index) => setSubmenu(index, true),
|
|
105
|
+
closeSubmenu: (index) => setSubmenu(index, false),
|
|
106
|
+
toggleSubmenu: (index) => {
|
|
107
|
+
const ul = submenu(index);
|
|
108
|
+
if (!ul) return;
|
|
109
|
+
setSubmenu(index, !pgs(ul).state.contains("open"));
|
|
110
|
+
},
|
|
111
|
+
isSubmenuOpen: (index) => {
|
|
112
|
+
const ul = submenu(index);
|
|
113
|
+
return ul ? pgs(ul).state.contains("open") : false;
|
|
114
|
+
},
|
|
115
|
+
refresh: () => {
|
|
116
|
+
PGS_menu_init(MENU.parentNode || document);
|
|
117
|
+
return API.get(MENU);
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
67
121
|
// pgs(document).querySelectorAll('menu-vertical').forEach(MENU => {
|
|
68
122
|
|
|
69
123
|
// MENU.querySelectorAll('.menu-item-has-children').forEach(li => {
|
|
@@ -85,8 +139,19 @@ export function PGS_menu() {
|
|
|
85
139
|
// });
|
|
86
140
|
// });
|
|
87
141
|
});
|
|
88
|
-
|
|
142
|
+
PGS_dropdown_init()
|
|
89
143
|
}
|
|
90
144
|
|
|
91
145
|
//# INIT PGS_menu
|
|
92
|
-
|
|
146
|
+
PGS_menu_init()
|
|
147
|
+
|
|
148
|
+
//# API
|
|
149
|
+
export function PGS_menu_api(selector) {
|
|
150
|
+
return API.get(selector);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export const PGS_menu = {
|
|
154
|
+
PGS_name: "PGS_menu",
|
|
155
|
+
init: PGS_menu_init,
|
|
156
|
+
api: PGS_menu_api
|
|
157
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
//# MODAL
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const API = new WeakMap();
|
|
3
|
+
|
|
4
|
+
export function PGS_modal_init(selector = "modal") {
|
|
4
5
|
pgs(document).querySelectorAll(selector).forEach(MODAL => {
|
|
6
|
+
if (API.has(MODAL)) return;
|
|
5
7
|
|
|
6
8
|
const BUTTON_OPEN = pgs(MODAL).querySelector("modal-button");
|
|
7
9
|
const DIALOG = MODAL.querySelector("dialog");
|
|
@@ -54,9 +56,14 @@ export function PGS_modal(selector = "modal") {
|
|
|
54
56
|
//+ FN OPEN
|
|
55
57
|
function openModal(e) {
|
|
56
58
|
e?.stopImmediatePropagation();
|
|
59
|
+
if (DIALOG.open) {
|
|
60
|
+
closeModal(e);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
if (!DIALOG.open) document.querySelectorAll("dialog[open]").forEach((dlg) => dlg.close());
|
|
58
65
|
statusModal(true);
|
|
59
|
-
|
|
66
|
+
topLevel ? DIALOG.showModal() : DIALOG.show();
|
|
60
67
|
// modalCustomEvents('modal:open', { event: e });
|
|
61
68
|
MODAL.dispatchEvent(new CustomEvent('modal:open'));
|
|
62
69
|
DIALOG.dispatchEvent(new CustomEvent('modal:open'));
|
|
@@ -72,6 +79,14 @@ export function PGS_modal(selector = "modal") {
|
|
|
72
79
|
DIALOG.dispatchEvent(new CustomEvent('modal:close'));
|
|
73
80
|
}
|
|
74
81
|
|
|
82
|
+
function forceOpen(e) {
|
|
83
|
+
if (!DIALOG.open) openModal(e);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function forceClose(e) {
|
|
87
|
+
if (DIALOG.open) closeModal(e);
|
|
88
|
+
}
|
|
89
|
+
|
|
75
90
|
//+ fn OPEN ON HISTORY
|
|
76
91
|
function openModalOnHistory() {
|
|
77
92
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -117,7 +132,34 @@ export function PGS_modal(selector = "modal") {
|
|
|
117
132
|
} catch (_) { }
|
|
118
133
|
});
|
|
119
134
|
}
|
|
135
|
+
|
|
136
|
+
API.set(MODAL, {
|
|
137
|
+
element: MODAL,
|
|
138
|
+
button: BUTTON_OPEN,
|
|
139
|
+
dialog: DIALOG,
|
|
140
|
+
closeButton: BUTTON_CLOSE,
|
|
141
|
+
open: forceOpen,
|
|
142
|
+
close: forceClose,
|
|
143
|
+
toggle: openModal,
|
|
144
|
+
refresh: () => {
|
|
145
|
+
PGS_modal_init(selector);
|
|
146
|
+
return API.get(MODAL);
|
|
147
|
+
},
|
|
148
|
+
isOpen: () => DIALOG.open,
|
|
149
|
+
});
|
|
120
150
|
});
|
|
121
151
|
}
|
|
122
152
|
|
|
123
153
|
//# INIT PGS_modal
|
|
154
|
+
PGS_modal_init()
|
|
155
|
+
|
|
156
|
+
//# API
|
|
157
|
+
export function PGS_modal_api(selector) {
|
|
158
|
+
return API.get(selector);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export const PGS_modal = {
|
|
162
|
+
PGS_name: "PGS_modal",
|
|
163
|
+
init: PGS_modal_init,
|
|
164
|
+
api: PGS_modal_api
|
|
165
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
//= PGS_notification
|
|
2
|
+
const fn_notification = {
|
|
3
|
+
_escapeHtml(value) {
|
|
4
|
+
return String(value ?? "");
|
|
5
|
+
},
|
|
6
|
+
|
|
7
|
+
_getDuration(notification) {
|
|
8
|
+
const rawDuration = notification.duration;
|
|
9
|
+
const duration = Number.parseInt(rawDuration, 10);
|
|
10
|
+
|
|
11
|
+
return Number.isNaN(duration) ? 5000 : duration;
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
_getApi(notification) {
|
|
15
|
+
const element = String(notification.element || "notification").trim();
|
|
16
|
+
|
|
17
|
+
return element === "toast" ? PGS_notification.toast : PGS_notification.alert;
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
_getType(notification, api) {
|
|
21
|
+
const type = String(notification.type || "info").trim();
|
|
22
|
+
|
|
23
|
+
return typeof api[type] === "function" ? type : "info";
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
_getData(root) {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(root.dataset.notification || "{}");
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.warn("PGS notification: dati non validi", error);
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
_getContent(title, content) {
|
|
36
|
+
const safeContent = this._escapeHtml(content);
|
|
37
|
+
const safeTitle = this._escapeHtml(title);
|
|
38
|
+
|
|
39
|
+
if (!safeTitle) return safeContent;
|
|
40
|
+
if (!safeContent) return `<span pgs="notification-element-title">${safeTitle}</span>`;
|
|
41
|
+
|
|
42
|
+
return `
|
|
43
|
+
<span pgs="notification-element-title">${safeTitle}</span>
|
|
44
|
+
<br>
|
|
45
|
+
<span pgs="notification-element-content">${safeContent}</span>
|
|
46
|
+
`;
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
initNotification(type, containerToken, icon, text, timeout, methodDelete = "replace", link = null) {
|
|
50
|
+
let containerNotification = pgs(document).querySelector(containerToken);
|
|
51
|
+
|
|
52
|
+
//== Create Container
|
|
53
|
+
if (!containerNotification) {
|
|
54
|
+
const newContainer = document.createElement("div");
|
|
55
|
+
pgs(newContainer).add(containerToken);
|
|
56
|
+
newContainer.setAttribute("aria-live", "polite");
|
|
57
|
+
newContainer.setAttribute("aria-relevant", "additions");
|
|
58
|
+
document.body.appendChild(newContainer);
|
|
59
|
+
containerNotification = newContainer;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//== Create Notification
|
|
63
|
+
const notification = document.createElement(link ? "a" : "div");
|
|
64
|
+
if (methodDelete == "replace") containerNotification.innerHTML = "";
|
|
65
|
+
if (link) notification.href = link;
|
|
66
|
+
if (timeout > 0) notification.style.setProperty("--notification-timeout", timeout + "ms");
|
|
67
|
+
pgs(notification).state.add(type);
|
|
68
|
+
pgs(notification).add("notification-element");
|
|
69
|
+
notification.setAttribute("role", type == "error" ? "alert" : "status")
|
|
70
|
+
notification.innerHTML = `${icon} <p>${text}</p>`;
|
|
71
|
+
containerNotification.appendChild(notification);
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
//+ Animation delete
|
|
75
|
+
function deleteNotification() {
|
|
76
|
+
methodDelete == "stack" ? notification.style.translate = "120%" : notification.style.opacity = "0";
|
|
77
|
+
setTimeout(() => notification.remove(), 300);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//== Timeout delete
|
|
81
|
+
if (timeout > 0) setTimeout(() => { deleteNotification() }, timeout);
|
|
82
|
+
|
|
83
|
+
//== button delete
|
|
84
|
+
const btnDelete = document.createElement("button");
|
|
85
|
+
btnDelete.type = "button";
|
|
86
|
+
btnDelete.ariaLabel = "Rimuovi notifica";
|
|
87
|
+
btnDelete.innerHTML = '<i class="fa-solid fa-xmark"></i>';
|
|
88
|
+
btnDelete.setAttribute("pgs", "buttonClose");
|
|
89
|
+
notification.insertAdjacentElement("afterbegin", btnDelete);
|
|
90
|
+
|
|
91
|
+
//== event
|
|
92
|
+
|
|
93
|
+
btnDelete.addEventListener("click", function (e) {
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
e.stopPropagation();
|
|
96
|
+
e.stopImmediatePropagation()
|
|
97
|
+
deleteNotification(e); // Esegue la tua funzione
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
deleteAll(containerToken) {
|
|
102
|
+
let containerNotification = pgs(document).querySelector(containerToken);
|
|
103
|
+
if (containerNotification) containerNotification.innerHTML = "";
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
trigger(root = document) {
|
|
107
|
+
pgs(root).querySelectorAll("notificationTrigger").forEach(element => {
|
|
108
|
+
if (!element || element.dataset.initialize === "true") return;
|
|
109
|
+
|
|
110
|
+
element.dataset.initialize = "true";
|
|
111
|
+
|
|
112
|
+
const notification = this._getData(element);
|
|
113
|
+
const title = String(notification.title || "").trim();
|
|
114
|
+
const content = String(notification.message || "").trim();
|
|
115
|
+
|
|
116
|
+
if (!title && !content) {
|
|
117
|
+
element.remove();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const link = notification.link || null;
|
|
122
|
+
const icon = notification.icon || undefined;
|
|
123
|
+
const duration = this._getDuration(notification);
|
|
124
|
+
const api = this._getApi(notification);
|
|
125
|
+
const type = this._getType(notification, api);
|
|
126
|
+
const formattedContent = this._getContent(title, content);
|
|
127
|
+
|
|
128
|
+
if (api === PGS_notification.toast) api[type](formattedContent, duration, icon);
|
|
129
|
+
else api[type](formattedContent, link, duration, icon);
|
|
130
|
+
|
|
131
|
+
element.remove();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
//# EXPORT
|
|
137
|
+
export function PGS_notificationTrigger_init(root = document) {
|
|
138
|
+
return fn_notification.trigger(root);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const PGS_notification = {
|
|
142
|
+
PGS_name: "PGS_notification",
|
|
143
|
+
trigger: PGS_notificationTrigger_init,
|
|
144
|
+
alert: {
|
|
145
|
+
error: (text = "Errore", link = null, timeout = 0, icon = '<i class="fa-solid fa-octagon-xmark"></i>') => fn_notification.initNotification("error", "notification", icon, text, timeout, "stack", link),
|
|
146
|
+
success: (text = "Aggiornato", link = null, timeout = 0, icon = '<i class="fa-solid fa-check"></i>') => fn_notification.initNotification("success", "notification", icon, text, timeout, "stack", link),
|
|
147
|
+
info: (text = "Aggiornamento", link = null, timeout = 0, icon = '<i class="fa-solid fa-circle-info"></i>',) => fn_notification.initNotification("info", "notification", icon, text, timeout, "stack", link),
|
|
148
|
+
warning: (text = "Attenzione", link = null, timeout = 0, icon = '<i class="fa-solid fa-triangle-exclamation"></i>') => fn_notification.initNotification("warning", "notification", icon, text, timeout, "stack", link),
|
|
149
|
+
deleteAll: () => fn_notification.deleteAll("notification")
|
|
150
|
+
},
|
|
151
|
+
toast: {
|
|
152
|
+
error: (text = "Errore", timeout = 4000, icon = '<i class="fa-solid fa-octagon-xmark"></i>',) => fn_notification.initNotification("error", "toast", icon, text, timeout),
|
|
153
|
+
success: (text = "Aggiornato", timeout = 4000, icon = '<i class="fa-solid fa-check"></i>',) => fn_notification.initNotification("success", "toast", icon, text, timeout),
|
|
154
|
+
info: (text = "Aggiornamento", timeout = 0, icon = '<i class="fa-solid fa-circle-info"></i>',) => fn_notification.initNotification("info", "toast", icon, text, timeout),
|
|
155
|
+
warning: (text = "Attenzione", timeout = 4000, icon = '<i class="fa-solid fa-triangle-exclamation"></i>',) => fn_notification.initNotification("warning", "toast", icon, text, timeout),
|
|
156
|
+
deleteAll: () => fn_notification.deleteAll("toast")
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
//= EXECUTE
|
|
162
|
+
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", () => PGS_notificationTrigger_init());
|
|
163
|
+
else PGS_notificationTrigger_init();
|