mypgs 1.6.0 → 2.0.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/AGENTS.md +2 -2
- package/assets/javascript/components/_accordion.js +2 -2
- package/assets/javascript/components/_modals.js +159 -136
- package/assets/javascript/components/_notifications.js +19 -9
- package/assets/javascript/components/_search.js +2 -2
- package/assets/javascript/components/_slides.js +66 -32
- package/assets/javascript/components/_stepTabs.js +4 -4
- package/assets/javascript/components/_steps.js +2 -2
- package/assets/javascript/components/_summary.js +2 -2
- package/assets/javascript/functions/_formValidate.js +97 -53
- package/assets/javascript/functions/_scrollY.js +10 -10
- package/assets/javascript/layout/_header.js +3 -0
- package/assets/scss/base/_html.scss +2 -2
- package/assets/scss/base/_variables.scss +2 -2
- package/assets/scss/components/_form.scss +2 -2
- package/assets/scss/components/_notification.scss +23 -30
- package/assets/scss/components/_search.scss +27 -21
- package/assets/scss/layout/_pageShell.scss +18 -15
- package/assets/scss/mixin/_mx-form.scss +7 -7
- package/{templates/html → demo}/demo.html +1 -1
- package/demo/demo.js +240 -0
- package/dist/css/index.css +86 -92
- package/dist/css/index.css.map +1 -1
- package/dist/css/index.min.css +1 -1
- package/dist/javascript/index.js +356 -255
- package/dist/javascript/index.js.map +1 -1
- package/dist/javascript/index.min.js +1 -1
- package/docs/componenti-e-markup.md +26 -27
- package/docs/components/accordion.md +61 -0
- package/docs/components/badges.md +67 -0
- package/docs/components/breadcumbs.md +43 -0
- package/docs/components/button.md +59 -0
- package/docs/components/card.md +50 -0
- package/docs/components/dropdown.md +135 -0
- package/docs/components/form.md +113 -0
- package/docs/components/logo.md +36 -0
- package/docs/components/menu.md +90 -0
- package/docs/components/modal.md +131 -0
- package/docs/components/notification.md +81 -0
- package/docs/components/search.md +117 -0
- package/docs/components/slides.md +85 -0
- package/docs/components/stepTabs.md +93 -0
- package/docs/components/steps.md +56 -0
- package/docs/components/summary.md +49 -0
- package/docs/components/table.md +42 -0
- package/docs/components/tooltip.md +53 -0
- package/docs/helper-javascript.md +68 -3
- package/docs/layout/body.md +41 -0
- package/docs/layout/flex.md +116 -0
- package/docs/layout/footer.md +71 -0
- package/docs/layout/grid.md +116 -0
- package/docs/layout/header.md +116 -0
- package/docs/layout/pageShell.md +94 -0
- package/docs/layout/section.md +69 -0
- package/docs/patterns/cookieConsent.md +89 -0
- package/package.json +2 -1
- package/scripts/generate-component-docs.js +557 -0
- package/templates/html/components/accordion.html +33 -4
- package/templates/html/components/badges.html +23 -0
- package/templates/html/components/breadcumbs.html +14 -0
- package/templates/html/components/button.html +22 -0
- package/templates/html/components/card.html +20 -0
- package/templates/html/components/dropdown.html +34 -0
- package/templates/html/components/form.html +82 -4
- package/templates/html/components/logo.html +21 -0
- package/templates/html/components/menu.html +33 -6
- package/templates/html/components/modal.html +44 -0
- package/templates/html/components/notification.html +68 -32
- package/templates/html/components/search.html +76 -0
- package/templates/html/components/slides.html +43 -0
- package/templates/html/components/stepTabs.html +47 -0
- package/templates/html/components/steps.html +24 -0
- package/templates/html/components/summary.html +27 -0
- package/templates/html/components/table.html +12 -0
- package/templates/html/components/tooltip.html +35 -0
- package/templates/html/layout/body.html +20 -5
- package/templates/html/layout/flex.html +20 -0
- package/templates/html/layout/footer.html +29 -1
- package/templates/html/layout/grid.html +20 -0
- package/templates/html/layout/header.html +41 -0
- package/templates/html/layout/pageShell.html +19 -0
- package/templates/html/layout/section.html +32 -10
- package/templates/html/patterns/cookieConsent.html +31 -0
- package/templates/react/components/form.jsx +3 -3
- package/templates/react/components/notification.jsx +4 -4
- package/templates/react/patterns/footer.jsx +1 -1
- package/templates/html/demo.js +0 -130
- /package/{templates/html → demo}/demo.css +0 -0
package/AGENTS.md
CHANGED
|
@@ -71,7 +71,7 @@ Patterns found:
|
|
|
71
71
|
|
|
72
72
|
- `pgs` is the main attribute: tokens are separated by spaces, for example `pgs="button modal-button"`.
|
|
73
73
|
- `assets/scss/index.scss` imports base, layout, components, and patterns; layouts/components/patterns are almost all scoped under `[pgs~=initP]`.
|
|
74
|
-
- The main markup must enable the library with `htmlBase initP`, and the body with base body tokens. Use `
|
|
74
|
+
- The main markup must enable the library with `htmlBase initP`, and the body with base body tokens. Use `demo/demo.html` and `templates/html/layout/body.html` as the canonical references.
|
|
75
75
|
- Components use a root token and child tokens with a consistent prefix. Use `templates/html/components/` as the canonical markup source.
|
|
76
76
|
|
|
77
77
|
- Runtime states use `pgs-state`, for example `open`, `is-active`, `is-completed`, `is-locked`, `success`, `error`, `warning`, and `info`.
|
|
@@ -229,7 +229,7 @@ Canonical template references:
|
|
|
229
229
|
- Layouts: `templates/html/layout/body.html`, `templates/html/layout/flex.html`, `templates/html/layout/grid.html`, `templates/html/layout/pageShell.html`, `templates/html/layout/section.html`
|
|
230
230
|
- Components: `templates/html/components/accordion.html`, `templates/html/components/breadcumbs.html`, `templates/html/components/button.html`, `templates/html/components/card.html`, `templates/html/components/dropdown.html`, `templates/html/components/form.html`, `templates/html/components/logo.html`, `templates/html/components/menu.html`, `templates/html/components/modal.html`, `templates/html/components/notification.html`, `templates/html/components/search.html`, `templates/html/components/slides.html`, `templates/html/components/stepTabs.html`, `templates/html/components/steps.html`, `templates/html/components/table.html`, `templates/html/components/tooltip.html`
|
|
231
231
|
- Patterns: `templates/html/patterns/cookieConsent.html`, `templates/html/patterns/footer.html`, `templates/html/patterns/header.html`
|
|
232
|
-
- Complete demo assembly. DO NOT use this for inspiration. It is only used to show all the modules: `
|
|
232
|
+
- Complete demo assembly. DO NOT use this for inspiration. It is only used to show all the modules: `demo/demo.html`
|
|
233
233
|
|
|
234
234
|
Before creating markup, open the relevant template and reuse its current structure, tokens, ARIA attributes, and `pgs-option` syntax.
|
|
235
235
|
|
|
@@ -11,7 +11,7 @@ function directPgsChild(element, token) {
|
|
|
11
11
|
return Array.from(element.children).find(child => pgs(child).contains(token));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
function PGS_accordion_init(root = document) {
|
|
15
15
|
pgs(root).querySelectorAll("accordion").forEach((accordion) => {
|
|
16
16
|
if (API.has(accordion)) return;
|
|
17
17
|
|
|
@@ -115,7 +115,7 @@ export function PGS_accordion_init(root = document) {
|
|
|
115
115
|
PGS_accordion_init();
|
|
116
116
|
|
|
117
117
|
//# API
|
|
118
|
-
|
|
118
|
+
function PGS_accordion_api(selector) {
|
|
119
119
|
return API.get(selector);
|
|
120
120
|
}
|
|
121
121
|
|
|
@@ -1,161 +1,184 @@
|
|
|
1
1
|
//# MODAL
|
|
2
2
|
const API = new WeakMap();
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
pgs(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const DIALOG = MODAL.querySelector("dialog");
|
|
10
|
-
if (!BUTTON_OPEN || !DIALOG) return;
|
|
11
|
-
|
|
12
|
-
//== SELECTOR
|
|
13
|
-
const DOMButtonClose = '<button pgs="buttonClose modal-close" type="button" tabindex="0" aria-label="Chiudi"><i class="fa-solid fa-close"></i></button>';
|
|
14
|
-
const modalContentHeader = pgs(MODAL)?.querySelector("modal-dialog-content-header")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
//== OPTION ATTRIBUTES MODAL
|
|
18
|
-
const disableBackdropClose = pgs(MODAL).option.contains("disableBackdropClose")
|
|
19
|
-
const data_history = pgs(MODAL).option.contains("history");
|
|
20
|
-
const data_container = pgs(MODAL).option.getValueBrackets("containerID");
|
|
21
|
-
const data_containerPGS = pgs(MODAL).option.getValueBrackets("containerPGS");
|
|
22
|
-
|
|
23
|
-
//== OPTION ATTRIBUTES DIALOG
|
|
24
|
-
const topLevel = pgs(DIALOG).option.contains("topLevel")
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
//== BUTTON CLOSE
|
|
28
|
-
if (pgs(MODAL).querySelector("modal-close")) null
|
|
29
|
-
else if (modalContentHeader) modalContentHeader.insertAdjacentHTML("beforeend", DOMButtonClose)
|
|
30
|
-
else DIALOG.insertAdjacentHTML("beforeend", DOMButtonClose)
|
|
31
|
-
const BUTTON_CLOSE = pgs(MODAL).querySelector("modal-close")
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
//== SET
|
|
35
|
-
pgs(DIALOG).add("dialog modal-dialog");
|
|
36
|
-
|
|
37
|
-
//== BUTTON OPEN
|
|
38
|
-
BUTTON_OPEN.setAttribute("role", "button");
|
|
39
|
-
BUTTON_OPEN.setAttribute("aria-label", "apri modale");
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
//== POSITION
|
|
43
|
-
if(!topLevel){
|
|
44
|
-
if (data_container) document.querySelector("#" + data_container)?.append(DIALOG);
|
|
45
|
-
else if (data_containerPGS) pgs(document).querySelector(data_containerPGS)?.append(DIALOG);
|
|
46
|
-
else document.body.append(DIALOG);
|
|
47
|
-
}
|
|
4
|
+
function getModals(root) {
|
|
5
|
+
const modals = root instanceof Element && pgs(root).contains("modal") ? [root] : [];
|
|
6
|
+
modals.push(...pgs(root).querySelectorAll("modal"));
|
|
7
|
+
return modals;
|
|
8
|
+
}
|
|
48
9
|
|
|
10
|
+
function initializeModal(MODAL, existingDialog = null) {
|
|
11
|
+
if (API.has(MODAL)) return;
|
|
49
12
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
13
|
+
const BUTTON_OPEN = pgs(MODAL).querySelector("modal-button");
|
|
14
|
+
const DIALOG = existingDialog || MODAL.querySelector("dialog");
|
|
15
|
+
if (!BUTTON_OPEN || !DIALOG) return;
|
|
16
|
+
const eventController = new AbortController();
|
|
17
|
+
const { signal } = eventController;
|
|
18
|
+
let historyObserver = null;
|
|
19
|
+
let historyTimeout = null;
|
|
55
20
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (DIALOG.open) {
|
|
60
|
-
closeModal(e);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (!DIALOG.open) document.querySelectorAll("dialog[open]").forEach((dlg) => dlg.close());
|
|
65
|
-
statusModal(true);
|
|
66
|
-
topLevel ? DIALOG.showModal() : DIALOG.show();
|
|
67
|
-
// modalCustomEvents('modal:open', { event: e });
|
|
68
|
-
MODAL.dispatchEvent(new CustomEvent('modal:open'));
|
|
69
|
-
DIALOG.dispatchEvent(new CustomEvent('modal:open'));
|
|
70
|
-
}
|
|
21
|
+
//== SELECTOR
|
|
22
|
+
const DOMButtonClose = '<button pgs="buttonClose modal-close" type="button" tabindex="0" aria-label="Chiudi"><i class="fa-solid fa-close"></i></button>';
|
|
23
|
+
const modalContentHeader = pgs(DIALOG).querySelector("modal-dialog-content-header");
|
|
71
24
|
|
|
72
|
-
//+ FN CLOSE
|
|
73
|
-
function closeModal(e) {
|
|
74
|
-
e?.stopImmediatePropagation()
|
|
75
|
-
statusModal(false);
|
|
76
|
-
DIALOG.close();
|
|
77
|
-
// modalCustomEvents('modal:close', { event: e });
|
|
78
|
-
MODAL.dispatchEvent(new CustomEvent('modal:close'));
|
|
79
|
-
DIALOG.dispatchEvent(new CustomEvent('modal:close'));
|
|
80
|
-
}
|
|
81
25
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
26
|
+
//== OPTION ATTRIBUTES MODAL
|
|
27
|
+
const disableBackdropClose = pgs(MODAL).option.contains("disableBackdropClose");
|
|
28
|
+
const data_history = pgs(MODAL).option.contains("history");
|
|
29
|
+
const data_container = pgs(MODAL).option.getValueBrackets("containerID");
|
|
30
|
+
const data_containerPGS = pgs(MODAL).option.getValueBrackets("containerPGS");
|
|
85
31
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
32
|
+
//== OPTION ATTRIBUTES DIALOG
|
|
33
|
+
const topLevel = pgs(DIALOG).option.contains("topLevel");
|
|
89
34
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
35
|
+
|
|
36
|
+
//== BUTTON CLOSE
|
|
37
|
+
if (!pgs(DIALOG).querySelector("modal-close") && !pgs(MODAL).querySelector("modal-close")) {
|
|
38
|
+
if (modalContentHeader) modalContentHeader.insertAdjacentHTML("beforeend", DOMButtonClose);
|
|
39
|
+
else DIALOG.insertAdjacentHTML("beforeend", DOMButtonClose);
|
|
40
|
+
}
|
|
41
|
+
const BUTTON_CLOSE = pgs(DIALOG).querySelector("modal-close") || pgs(MODAL).querySelector("modal-close");
|
|
97
42
|
|
|
98
43
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const params = new URLSearchParams(window.location.search);
|
|
129
|
-
const shouldOpen = params.get('modal') === BUTTON_OPEN.id;
|
|
130
|
-
if (shouldOpen && !DIALOG.open) DIALOG.showModal();
|
|
131
|
-
if (!shouldOpen && DIALOG.open) closeModal()
|
|
132
|
-
} catch (_) { }
|
|
133
|
-
});
|
|
44
|
+
//== SET
|
|
45
|
+
pgs(DIALOG).add("dialog modal-dialog");
|
|
46
|
+
|
|
47
|
+
//== BUTTON OPEN
|
|
48
|
+
BUTTON_OPEN.setAttribute("role", "button");
|
|
49
|
+
BUTTON_OPEN.setAttribute("aria-label", "apri modale");
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
//== POSITION
|
|
53
|
+
if (topLevel && !MODAL.contains(DIALOG)) MODAL.append(DIALOG);
|
|
54
|
+
else if (!topLevel) {
|
|
55
|
+
if (data_container) document.querySelector("#" + data_container)?.append(DIALOG);
|
|
56
|
+
else if (data_containerPGS) pgs(document).querySelector(data_containerPGS)?.append(DIALOG);
|
|
57
|
+
else document.body.append(DIALOG);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
//+ FN STATUS
|
|
62
|
+
function statusModal(status = true) {
|
|
63
|
+
BUTTON_OPEN?.setAttribute("aria-expanded", status);
|
|
64
|
+
DIALOG?.setAttribute("aria-expanded", status);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//+ FN OPEN
|
|
68
|
+
function openModal(e) {
|
|
69
|
+
e?.stopImmediatePropagation();
|
|
70
|
+
if (DIALOG.open) {
|
|
71
|
+
closeModal(e);
|
|
72
|
+
return;
|
|
134
73
|
}
|
|
135
74
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
75
|
+
if (!DIALOG.open) document.querySelectorAll("dialog[open]").forEach((dlg) => dlg.close());
|
|
76
|
+
statusModal(true);
|
|
77
|
+
topLevel ? DIALOG.showModal() : DIALOG.show();
|
|
78
|
+
// modalCustomEvents('modal:open', { event: e });
|
|
79
|
+
MODAL.dispatchEvent(new CustomEvent('modal:open'));
|
|
80
|
+
DIALOG.dispatchEvent(new CustomEvent('modal:open'));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//+ FN CLOSE
|
|
84
|
+
function closeModal(e) {
|
|
85
|
+
e?.stopImmediatePropagation()
|
|
86
|
+
statusModal(false);
|
|
87
|
+
DIALOG.close();
|
|
88
|
+
// modalCustomEvents('modal:close', { event: e });
|
|
89
|
+
MODAL.dispatchEvent(new CustomEvent('modal:close'));
|
|
90
|
+
DIALOG.dispatchEvent(new CustomEvent('modal:close'));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function forceOpen(e) {
|
|
94
|
+
if (!DIALOG.open) openModal(e);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function forceClose(e) {
|
|
98
|
+
if (DIALOG.open) closeModal(e);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//+ fn OPEN ON HISTORY
|
|
102
|
+
function openModalOnHistory() {
|
|
103
|
+
const params = new URLSearchParams(window.location.search);
|
|
104
|
+
if (params.get('modal') !== BUTTON_OPEN.id) return;
|
|
105
|
+
document.getElementById(BUTTON_OPEN.id)?.scrollIntoView({ behavior: 'smooth' });
|
|
106
|
+
openModal();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
//= OPEN
|
|
111
|
+
BUTTON_OPEN.addEventListener("click", (e) => openModal(e), { signal });
|
|
112
|
+
BUTTON_OPEN.addEventListener("keypress", (e) => !DIALOG.open && (e.key === "Enter" || e.key === " ") && openModal(e), { signal });
|
|
113
|
+
|
|
114
|
+
//= CLOSE
|
|
115
|
+
DIALOG.addEventListener("close", () => statusModal(false), { signal });
|
|
116
|
+
DIALOG.addEventListener("click", e => { if (e.target == DIALOG && !disableBackdropClose) closeModal(e) }, { signal });
|
|
117
|
+
BUTTON_CLOSE?.addEventListener("click", e => closeModal(e), { signal });
|
|
118
|
+
|
|
119
|
+
//= UPDATE HISTORY
|
|
120
|
+
if (data_history && BUTTON_OPEN.id) {
|
|
121
|
+
historyTimeout = window.setTimeout(openModalOnHistory, 1);
|
|
122
|
+
|
|
123
|
+
//== Aggiorna URL quando cambia l'attributo "open" del dialog
|
|
124
|
+
historyObserver = new MutationObserver(() => {
|
|
125
|
+
let isOpen = DIALOG.hasAttribute("open");
|
|
126
|
+
try {
|
|
127
|
+
const url = new URL(window.location.href);
|
|
128
|
+
const params = new URLSearchParams(url.search);
|
|
129
|
+
isOpen ? params.set('modal', BUTTON_OPEN.id) : params.delete('modal');
|
|
130
|
+
url.search = params.toString() ? `?${params.toString()}` : "";
|
|
131
|
+
window.history.pushState({ modal: BUTTON_OPEN.id, open: isOpen }, "", url);
|
|
132
|
+
} catch (_) { }
|
|
149
133
|
});
|
|
134
|
+
historyObserver.observe(DIALOG, { attributes: true, attributeFilter: ["open"] });
|
|
135
|
+
|
|
136
|
+
//== Gestisce back/forward del browser per aprire/chiudere il dialog coerentemente
|
|
137
|
+
window.addEventListener("popstate", () => {
|
|
138
|
+
try {
|
|
139
|
+
const params = new URLSearchParams(window.location.search);
|
|
140
|
+
const shouldOpen = params.get('modal') === BUTTON_OPEN.id;
|
|
141
|
+
if (shouldOpen && !DIALOG.open) DIALOG.showModal();
|
|
142
|
+
if (!shouldOpen && DIALOG.open) closeModal()
|
|
143
|
+
} catch (_) { }
|
|
144
|
+
}, { signal });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function destroy() {
|
|
148
|
+
eventController.abort();
|
|
149
|
+
historyObserver?.disconnect();
|
|
150
|
+
if (historyTimeout !== null) window.clearTimeout(historyTimeout);
|
|
151
|
+
API.delete(MODAL);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
API.set(MODAL, {
|
|
155
|
+
element: MODAL,
|
|
156
|
+
button: BUTTON_OPEN,
|
|
157
|
+
dialog: DIALOG,
|
|
158
|
+
closeButton: BUTTON_CLOSE,
|
|
159
|
+
open: forceOpen,
|
|
160
|
+
close: forceClose,
|
|
161
|
+
toggle: openModal,
|
|
162
|
+
refresh: () => {
|
|
163
|
+
const nextDialog = MODAL.querySelector("dialog") || DIALOG;
|
|
164
|
+
destroy();
|
|
165
|
+
initializeModal(MODAL, nextDialog);
|
|
166
|
+
return API.get(MODAL);
|
|
167
|
+
},
|
|
168
|
+
isOpen: () => DIALOG.open,
|
|
150
169
|
});
|
|
151
170
|
}
|
|
152
171
|
|
|
172
|
+
function PGS_modal_init(root = document) {
|
|
173
|
+
getModals(root).forEach(MODAL => initializeModal(MODAL));
|
|
174
|
+
}
|
|
175
|
+
|
|
153
176
|
//# INIT PGS_modal
|
|
154
177
|
PGS_modal_init()
|
|
155
178
|
|
|
156
179
|
//# API
|
|
157
|
-
|
|
158
|
-
return API.get(
|
|
180
|
+
function PGS_modal_api(element) {
|
|
181
|
+
return API.get(element);
|
|
159
182
|
}
|
|
160
183
|
|
|
161
184
|
export const PGS_modal = {
|
|
@@ -24,10 +24,12 @@ const fn_notification = {
|
|
|
24
24
|
},
|
|
25
25
|
|
|
26
26
|
_getData(root) {
|
|
27
|
+
const rawNotification = pgs(root).option.getValueBrackets("notification") || "{}";
|
|
28
|
+
|
|
27
29
|
try {
|
|
28
|
-
return JSON.parse(
|
|
30
|
+
return JSON.parse(rawNotification);
|
|
29
31
|
} catch (error) {
|
|
30
|
-
console.warn("PGS notification:
|
|
32
|
+
console.warn("PGS notification: configurazione JSON non valida", error);
|
|
31
33
|
return {};
|
|
32
34
|
}
|
|
33
35
|
},
|
|
@@ -46,13 +48,21 @@ const fn_notification = {
|
|
|
46
48
|
`;
|
|
47
49
|
},
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
_getContainer(containerType) {
|
|
52
|
+
return Array.from(pgs(document).querySelectorAll("notification")).find(container => {
|
|
53
|
+
const isToast = pgs(container).option.contains("toast");
|
|
54
|
+
return containerType === "toast" ? isToast : !isToast;
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
initNotification(type, containerType, icon, text, timeout, methodDelete = "replace", link = null) {
|
|
59
|
+
let containerNotification = this._getContainer(containerType);
|
|
51
60
|
|
|
52
61
|
//== Create Container
|
|
53
62
|
if (!containerNotification) {
|
|
54
63
|
const newContainer = document.createElement("div");
|
|
55
|
-
pgs(newContainer).add(
|
|
64
|
+
pgs(newContainer).add("notification");
|
|
65
|
+
if (containerType === "toast") pgs(newContainer).option.add("toast");
|
|
56
66
|
newContainer.setAttribute("aria-live", "polite");
|
|
57
67
|
newContainer.setAttribute("aria-relevant", "additions");
|
|
58
68
|
document.body.appendChild(newContainer);
|
|
@@ -98,8 +108,8 @@ const fn_notification = {
|
|
|
98
108
|
});
|
|
99
109
|
},
|
|
100
110
|
|
|
101
|
-
deleteAll(
|
|
102
|
-
let containerNotification =
|
|
111
|
+
deleteAll(containerType) {
|
|
112
|
+
let containerNotification = this._getContainer(containerType);
|
|
103
113
|
if (containerNotification) containerNotification.innerHTML = "";
|
|
104
114
|
},
|
|
105
115
|
|
|
@@ -133,8 +143,8 @@ const fn_notification = {
|
|
|
133
143
|
}
|
|
134
144
|
};
|
|
135
145
|
|
|
136
|
-
//#
|
|
137
|
-
|
|
146
|
+
//# TRIGGER
|
|
147
|
+
function PGS_notificationTrigger_init(root = document) {
|
|
138
148
|
return fn_notification.trigger(root);
|
|
139
149
|
}
|
|
140
150
|
|
|
@@ -5,7 +5,7 @@ let searchId = 0;
|
|
|
5
5
|
const DEFAULT_OPTIONS = {
|
|
6
6
|
minLength: 2,
|
|
7
7
|
debounce: 200,
|
|
8
|
-
limit:
|
|
8
|
+
limit: 6,
|
|
9
9
|
submitOnSelect: false,
|
|
10
10
|
searchOnFocus: true,
|
|
11
11
|
source: null,
|
|
@@ -381,7 +381,7 @@ document.addEventListener("pointerdown", event => {
|
|
|
381
381
|
|
|
382
382
|
PGS_search_init();
|
|
383
383
|
|
|
384
|
-
|
|
384
|
+
function PGS_search_api(selector) {
|
|
385
385
|
return API.get(selector);
|
|
386
386
|
}
|
|
387
387
|
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { PGS_scrollHorizontal } from "../functions/_scrollY"
|
|
1
|
+
import { PGS_scrollHorizontal } from "../functions/_scrollY.js";
|
|
2
2
|
const API = new WeakMap();
|
|
3
3
|
|
|
4
|
+
function getSlides(root) {
|
|
5
|
+
const slides = root instanceof Element && pgs(root).contains("slides") ? [root] : [];
|
|
6
|
+
slides.push(...pgs(root).querySelectorAll("slides"));
|
|
7
|
+
return slides;
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
class PGS_Slides {
|
|
5
11
|
//- CONSTRUCTOR
|
|
6
|
-
constructor({
|
|
7
|
-
this.
|
|
12
|
+
constructor({ element, viewRatio = 0.97, optionIntersectionObserver = {}, scrollOptions = {} } = {}) {
|
|
13
|
+
this.element = element;
|
|
8
14
|
this.viewRatio = viewRatio;
|
|
9
15
|
|
|
10
16
|
this.optionIntersectionObserver = {
|
|
@@ -21,28 +27,36 @@ class PGS_Slides {
|
|
|
21
27
|
...scrollOptions,
|
|
22
28
|
};
|
|
23
29
|
|
|
24
|
-
this.container = this.
|
|
30
|
+
this.container = this.element ? pgs(this.element).querySelector("slides-container") : null;
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
//+ CREATE BUTTON
|
|
28
34
|
#createButtonsAndDots() {
|
|
29
|
-
const EL = this.
|
|
35
|
+
const EL = this.element;
|
|
30
36
|
|
|
31
37
|
//== PULSANTI
|
|
32
|
-
if (!pgs(EL).querySelector('slides-prec')
|
|
38
|
+
if (!pgs(EL).querySelector('slides-prec')) {
|
|
33
39
|
EL.insertAdjacentHTML("afterbegin", `<button pgs="slides-prec buttonIcon" type="button" class="precButton" aria-label="slide precedente"> <span> <i class="fa-solid fa-arrow-left"></i></span></button>`);
|
|
40
|
+
}
|
|
41
|
+
if (!pgs(EL).querySelector('slides-next')) {
|
|
34
42
|
EL.insertAdjacentHTML("beforeend", `<button pgs="slides-next buttonIcon" type="button" class="nextButton" aria-label="prossima slide"> <span> <i class="fa-solid fa-arrow-right"></i></span></button>`);
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
//== DOTS
|
|
38
46
|
if (!pgs(EL).querySelector('slides-dots')) {
|
|
39
47
|
EL.insertAdjacentHTML("beforeend", `<div pgs="slides-dots" class="slides-dots"></div>`);
|
|
48
|
+
}
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
const dotsContainer = pgs(EL).querySelector('slides-dots');
|
|
51
|
+
while (dotsContainer.children.length < this.container.children.length) {
|
|
52
|
+
dotsContainer.insertAdjacentHTML("beforeend", `<button type="button" class="slide-dot"></button>`);
|
|
53
|
+
}
|
|
54
|
+
while (dotsContainer.children.length > this.container.children.length) {
|
|
55
|
+
dotsContainer.lastElementChild.remove();
|
|
45
56
|
}
|
|
57
|
+
Array.from(dotsContainer.children).forEach((dot, index) => {
|
|
58
|
+
dot.setAttribute("aria-label", `vai alla slide ${index + 1}`);
|
|
59
|
+
});
|
|
46
60
|
}
|
|
47
61
|
|
|
48
62
|
//+ PREV
|
|
@@ -51,7 +65,7 @@ class PGS_Slides {
|
|
|
51
65
|
let current;
|
|
52
66
|
|
|
53
67
|
|
|
54
|
-
if (pgs(this.
|
|
68
|
+
if (pgs(this.element).option.contains('singleScroll')) current = currents[currents.length - 1];
|
|
55
69
|
else current = currents[0];
|
|
56
70
|
|
|
57
71
|
const prev = current?.previousElementSibling;
|
|
@@ -67,19 +81,17 @@ class PGS_Slides {
|
|
|
67
81
|
|
|
68
82
|
|
|
69
83
|
|
|
70
|
-
if (pgs(this.
|
|
84
|
+
if (pgs(this.element).option.contains('singleScroll')) current = currents[0];
|
|
71
85
|
else current = currents[currents.length - 1];
|
|
72
86
|
|
|
73
87
|
const next = current?.nextElementSibling;
|
|
74
|
-
console.log(current, next);
|
|
75
|
-
|
|
76
88
|
next?.scrollIntoView(this.scrollOptions);
|
|
77
89
|
next?.focus({ preventScroll: true });
|
|
78
90
|
}
|
|
79
91
|
|
|
80
92
|
//+ GO TO NUMBER SLIDE
|
|
81
93
|
#goToNumberSlide(index) {
|
|
82
|
-
this.container.children[index]
|
|
94
|
+
this.container.children[index]?.scrollIntoView(this.scrollOptions);
|
|
83
95
|
}
|
|
84
96
|
|
|
85
97
|
//+ CALLBACK
|
|
@@ -118,8 +130,10 @@ class PGS_Slides {
|
|
|
118
130
|
|
|
119
131
|
//= EXECUTE
|
|
120
132
|
execute() {
|
|
121
|
-
const slides = this.
|
|
122
|
-
if (!this.container) return
|
|
133
|
+
const slides = this.element;
|
|
134
|
+
if (!this.container) return;
|
|
135
|
+
const eventController = new AbortController();
|
|
136
|
+
const { signal } = eventController;
|
|
123
137
|
|
|
124
138
|
//== elements
|
|
125
139
|
this.#createButtonsAndDots();
|
|
@@ -131,12 +145,14 @@ class PGS_Slides {
|
|
|
131
145
|
const notScrollWithMouse = pgs(slides).option.contains('notScrollWithMouse');
|
|
132
146
|
|
|
133
147
|
//== scroll
|
|
134
|
-
|
|
148
|
+
const removeHorizontalScroll = notScrollWithMouse
|
|
149
|
+
? null
|
|
150
|
+
: PGS_scrollHorizontal(this.container, 5);
|
|
135
151
|
|
|
136
152
|
//==Listener: DOT, PREC, NEXT
|
|
137
|
-
dots.forEach((dot, index) => dot.addEventListener("click",
|
|
138
|
-
precButton.addEventListener("click",
|
|
139
|
-
nextButton.addEventListener("click",
|
|
153
|
+
dots.forEach((dot, index) => dot.addEventListener("click", () => this.#goToNumberSlide(index), { signal }));
|
|
154
|
+
precButton.addEventListener("click", () => this.#previousSlide(), { passive: true, signal });
|
|
155
|
+
nextButton.addEventListener("click", () => this.#nextSlide(), { passive: true, signal });
|
|
140
156
|
|
|
141
157
|
//== observer
|
|
142
158
|
const observer = new IntersectionObserver(
|
|
@@ -146,9 +162,18 @@ class PGS_Slides {
|
|
|
146
162
|
Array.from(this.container.children).forEach(allLi => observer.observe(allLi));
|
|
147
163
|
|
|
148
164
|
|
|
165
|
+
let api;
|
|
166
|
+
const destroy = () => {
|
|
167
|
+
if (API.get(this.element) !== api) return;
|
|
168
|
+
eventController.abort();
|
|
169
|
+
observer.disconnect();
|
|
170
|
+
removeHorizontalScroll?.();
|
|
171
|
+
API.delete(this.element);
|
|
172
|
+
};
|
|
173
|
+
|
|
149
174
|
//- API
|
|
150
|
-
|
|
151
|
-
element: this.
|
|
175
|
+
api = {
|
|
176
|
+
element: this.element,
|
|
152
177
|
container: this.container,
|
|
153
178
|
previous: () => this.#previousSlide(),
|
|
154
179
|
next: () => this.#nextSlide(),
|
|
@@ -163,19 +188,28 @@ class PGS_Slides {
|
|
|
163
188
|
return last?.classList.contains("view") || false;
|
|
164
189
|
},
|
|
165
190
|
refresh: () => {
|
|
166
|
-
|
|
167
|
-
|
|
191
|
+
if (API.get(this.element) !== api) return API.get(this.element);
|
|
192
|
+
destroy();
|
|
193
|
+
const instance = new PGS_Slides({
|
|
194
|
+
element: this.element,
|
|
195
|
+
viewRatio: this.viewRatio,
|
|
196
|
+
optionIntersectionObserver: this.optionIntersectionObserver,
|
|
197
|
+
scrollOptions: this.scrollOptions,
|
|
198
|
+
});
|
|
199
|
+
instance.execute();
|
|
200
|
+
return API.get(this.element);
|
|
168
201
|
},
|
|
169
|
-
}
|
|
202
|
+
};
|
|
203
|
+
API.set(this.element, api);
|
|
170
204
|
}
|
|
171
205
|
}
|
|
172
206
|
|
|
173
207
|
//# INIT
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (API.has(
|
|
208
|
+
function PGS_slides_init(root = document) {
|
|
209
|
+
getSlides(root).forEach(element => {
|
|
210
|
+
if (API.has(element)) return;
|
|
177
211
|
|
|
178
|
-
const instance = new PGS_Slides({
|
|
212
|
+
const instance = new PGS_Slides({ element });
|
|
179
213
|
instance.execute();
|
|
180
214
|
});
|
|
181
215
|
}
|
|
@@ -183,8 +217,8 @@ export function PGS_slides_init(root = document) {
|
|
|
183
217
|
PGS_slides_init();
|
|
184
218
|
|
|
185
219
|
//# API
|
|
186
|
-
|
|
187
|
-
return API.get(
|
|
220
|
+
function PGS_slides_api(element) {
|
|
221
|
+
return API.get(element);
|
|
188
222
|
}
|
|
189
223
|
|
|
190
224
|
export const PGS_slides = {
|