mypgs 1.3.2 → 1.3.3

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 (73) hide show
  1. package/AI_GUIDELINES.md +353 -0
  2. package/README.md +483 -53
  3. package/assets/javascript/_imports.js +12 -11
  4. package/assets/javascript/_pgs.js +16 -1
  5. package/assets/javascript/components/_accordion.js +18 -9
  6. package/assets/javascript/components/_dropdown.js +176 -120
  7. package/assets/javascript/components/_menu.js +15 -116
  8. package/assets/javascript/components/_modals.js +0 -1
  9. package/assets/javascript/components/_notifications.js +2 -3
  10. package/assets/javascript/components/_slides.js +0 -1
  11. package/assets/javascript/components/_stepTabs.js +0 -1
  12. package/assets/javascript/components/_steps.js +0 -1
  13. package/assets/javascript/patterns/_cookieConsent.js +8 -2
  14. package/assets/javascript/pgs.d.ts +12 -1
  15. package/assets/scss/base/_html.scss +23 -1
  16. package/assets/scss/components/_dropdown.scss +24 -88
  17. package/assets/scss/components/_menu.scss +129 -15
  18. package/assets/scss/components/_modals.scss +15 -3
  19. package/assets/scss/components/_notification.scss +11 -14
  20. package/assets/scss/components/_tooltip.scss +2 -9
  21. package/assets/scss/index.scss +0 -1
  22. package/assets/scss/layout/_gap.scss +7 -1
  23. package/assets/scss/layout/_layout.scss +0 -12
  24. package/assets/scss/layout/_pageShell.scss +104 -105
  25. package/assets/scss/mixin/_mx-form.scss +1 -3
  26. package/assets/scss/mixin/_mx-responsive.scss +2 -2
  27. package/assets/scss/mixin/_mx-semantic.scss +0 -60
  28. package/assets/scss/mixin/mixin.scss +0 -1
  29. package/assets/scss/patterns/_footer.scss +1 -0
  30. package/assets/scss/patterns/_header.scss +20 -18
  31. package/dist/css/index.css +324 -1160
  32. package/dist/css/index.css.map +1 -1
  33. package/dist/css/index.min.css +1 -1
  34. package/dist/index.d.ts +12 -1
  35. package/dist/javascript/index.js +277 -272
  36. package/dist/javascript/index.js.map +1 -1
  37. package/dist/javascript/index.min.js +1 -1
  38. package/package.json +1 -1
  39. package/templates/components/{md-accordion.html → accordion.html} +2 -2
  40. package/templates/components/dropdown.html +91 -0
  41. package/templates/components/menu.html +41 -0
  42. package/templates/components/modal.html +78 -0
  43. package/templates/components/notification.html +35 -0
  44. package/templates/components/{md-slides.html → slides.html} +5 -5
  45. package/templates/components/{md-steps.html → steps.html} +7 -7
  46. package/templates/components/{md-tooltip.html → tooltip.html} +4 -2
  47. package/templates/demo.css +18 -0
  48. package/templates/demo.html +4 -5
  49. package/templates/demo.js +53 -52
  50. package/templates/layout/flex.html +89 -0
  51. package/templates/layout/grid.html +89 -0
  52. package/templates/layout/pageShell.html +59 -0
  53. package/templates/layout/section.html +40 -0
  54. package/templates/{layout/md-footer.html → patterns/footer.html} +1 -0
  55. package/templates/{layout/md-header.html → patterns/header.html} +6 -9
  56. package/assets/scss/base/_reset.scss +0 -15
  57. package/assets/scss/mixin/_mx-menu.scss +0 -154
  58. package/templates/components/md-dropdown.html +0 -16
  59. package/templates/components/md-menu.html +0 -40
  60. package/templates/components/md-modal.html +0 -19
  61. package/templates/components/md-notification.html +0 -13
  62. package/templates/layout/md-pageShell.html +0 -22
  63. package/templates/layout/md-section.html +0 -25
  64. /package/templates/components/{md-breadcumbs.html → breadcumbs.html} +0 -0
  65. /package/templates/components/{md-button.html → button.html} +0 -0
  66. /package/templates/components/{md-card.html → card.html} +0 -0
  67. /package/templates/components/{md-form.html → form.html} +0 -0
  68. /package/templates/components/{md-logo.html → logo.html} +0 -0
  69. /package/templates/components/{md-searchbar.html → searchbar.html} +0 -0
  70. /package/templates/components/{md-stepTabs.html → stepTabs.html} +0 -0
  71. /package/templates/components/{md-table.html → table.html} +0 -0
  72. /package/templates/layout/{md-body.html → body.html} +0 -0
  73. /package/templates/{layout/md-cookieConsent.html → patterns/cookieConsent.html} +0 -0
@@ -1,16 +1,26 @@
1
1
  //= ACCORDION
2
2
  const API = new WeakMap();
3
+ let accordionId = 0;
4
+
5
+ function nextAccordionId() {
6
+ accordionId += 1;
7
+ return accordionId;
8
+ }
9
+
10
+ function directPgsChild(element, token) {
11
+ return Array.from(element.children).find(child => pgs(child).contains(token));
12
+ }
3
13
 
4
14
  export function PGS_accordion_init(root = document) {
5
- pgs(root).querySelectorAll("accordion").forEach((accordion, index) => {
15
+ pgs(root).querySelectorAll("accordion").forEach((accordion) => {
6
16
  if (API.has(accordion)) return;
7
17
 
8
- const BUTTON = pgs(accordion).querySelector("accordion-button");
9
- const CONTENT = pgs(accordion).querySelector("accordion-content");
18
+ const BUTTON = directPgsChild(accordion, "accordion-button");
19
+ const CONTENT = directPgsChild(accordion, "accordion-content");
10
20
  if (!BUTTON || !CONTENT) return;
11
21
 
12
22
  //== ID univoci per aria-controls / aria-labelledby
13
- const ID = index + 1;
23
+ const ID = nextAccordionId();
14
24
  const btnId = `acc-btn-${ID}`;
15
25
  const panelId = `acc-panel-${ID}`;
16
26
 
@@ -20,12 +30,12 @@ export function PGS_accordion_init(root = document) {
20
30
  //== Accessibilità (setup una volta)
21
31
  BUTTON.setAttribute("role", "button");
22
32
  BUTTON.setAttribute("tabindex", "0");
23
- BUTTON.setAttribute("id", btnId);
24
- BUTTON.setAttribute("aria-controls", panelId);
33
+ if (!BUTTON.id) BUTTON.setAttribute("id", btnId);
25
34
 
26
- CONTENT.setAttribute("id", panelId);
35
+ if (!CONTENT.id) CONTENT.setAttribute("id", panelId);
36
+ BUTTON.setAttribute("aria-controls", CONTENT.id);
27
37
  CONTENT.setAttribute("role", "region");
28
- CONTENT.setAttribute("aria-labelledby", btnId);
38
+ CONTENT.setAttribute("aria-labelledby", BUTTON.id);
29
39
 
30
40
  //+ Accessibility (applica stato aperto/chiuso)
31
41
  function accordionAccessibility(isOpen, button, content) {
@@ -110,7 +120,6 @@ export function PGS_accordion_api(selector) {
110
120
  }
111
121
 
112
122
  export const PGS_accordion = {
113
- PGS_name: "PGS_accordion",
114
123
  init: PGS_accordion_init,
115
124
  api: PGS_accordion_api
116
125
  };
@@ -1,153 +1,209 @@
1
- // + dropdown (Popover API)
1
+ // + dropdown
2
2
  const API = new WeakMap();
3
+ const OPEN_DROPDOWNS = new Set();
4
+ const VIEWPORT_GAP = 8;
5
+ let dropdownId = 0;
3
6
 
4
- export function PGS_dropdown_init(root = document) {
5
- pgs(root).querySelectorAll("dropdown").forEach((DROPDOWN, index) => {
6
- if (API.has(DROPDOWN)) return;
7
+ function nextDropdownId() {
8
+ dropdownId += 1;
9
+ return dropdownId;
10
+ }
7
11
 
8
- const BUTTON = pgs(DROPDOWN).querySelector("dropdown-button");
9
- const CONTENT = pgs(DROPDOWN).querySelector("dropdown-content");
10
-
11
- if (!BUTTON || !CONTENT) return;
12
-
13
- // = INIT
14
- if (DROPDOWN.getAttribute("data-initialize") === "true") return;
15
- DROPDOWN.setAttribute("data-initialize", "true");
16
-
17
- // == CSS dropdown-anchor
18
- const ANCHOR_NAME = `--dropdown-anchor-${index}`;
19
- DROPDOWN.style.setProperty("--dropdown-anchor", ANCHOR_NAME);
20
-
21
- // == IDs + ACCESSIBILITY
22
- if (!BUTTON.id) BUTTON.id = `dropdown-btn-${index}`;
23
- if (!CONTENT.id) CONTENT.id = `dropdown-panel-${index}`;
24
- BUTTON.setAttribute("type", "button");
25
- BUTTON.setAttribute("aria-haspopup", "true");
26
- BUTTON.setAttribute("aria-controls", CONTENT.id);
27
- BUTTON.setAttribute("aria-expanded", "false");
28
- CONTENT.setAttribute("aria-labelledby", BUTTON.id);
29
-
30
- // == POPVER SETUP
31
- if (!CONTENT.hasAttribute("popover")) CONTENT.setAttribute("popover", "auto");
32
- BUTTON.setAttribute("popovertarget", CONTENT.id);
33
- BUTTON.setAttribute("popovertargetaction", "toggle");
34
-
35
- //-( Safari / legacy fallback: popover is in the top layer, so fixed coords are viewport-based.
36
- const HAS_ANCHOR_POSITIONING =
37
- CSS.supports("anchor-name: --dropdown-anchor") &&
38
- CSS.supports("position-anchor: --dropdown-anchor") &&
39
- CSS.supports("position-area: bottom") &&
40
- CSS.supports("top: anchor(bottom)");
41
- const USE_FALLBACK_POSITIONING = pgs(DROPDOWN).contains("tooltip") || !HAS_ANCHOR_POSITIONING;
42
-
43
- const updatePopoverPosition = () => {
44
- if (!USE_FALLBACK_POSITIONING) return;
45
-
46
- const buttonRect = BUTTON.getBoundingClientRect();
47
- const style = getComputedStyle(DROPDOWN);
48
- const offset = parseFloat(style.getPropertyValue("--dropdown-offset")) || 10;
49
- const padding = parseFloat(style.getPropertyValue("--dropdown-padding")) || 0;
50
- const arrowSize = parseFloat(style.getPropertyValue("--dropdown-arrow-size")) || 12;
51
- const viewportGap = 8;
52
- const viewportWidth = window.innerWidth;
53
- const maxWidth = viewportWidth - viewportGap * 2;
54
- const contentStyle = getComputedStyle(CONTENT);
55
- const cssMaxWidth = parseFloat(contentStyle.maxWidth);
56
- const dropdownMaxWidth = Number.isFinite(cssMaxWidth) ? Math.min(cssMaxWidth, maxWidth) : maxWidth;
57
- const contentWidth = Math.min(
58
- Math.max(CONTENT.scrollWidth + padding * 2, buttonRect.width),
59
- dropdownMaxWidth
60
- );
61
- const top = buttonRect.bottom + offset;
62
- const centeredLeft = buttonRect.left + buttonRect.width / 2 - contentWidth / 2;
63
- const left = Math.min(
64
- Math.max(centeredLeft, viewportGap),
65
- viewportWidth - contentWidth - viewportGap
66
- );
67
- const buttonCenter = buttonRect.left + buttonRect.width / 2;
68
- const arrowLeft = Math.min(
69
- Math.max(buttonCenter - left, padding + arrowSize),
70
- contentWidth - padding - arrowSize
71
- );
72
-
73
- DROPDOWN.style.setProperty("--dropdown-fallback-top", `${top}px`);
74
- DROPDOWN.style.setProperty("--dropdown-fallback-left", `${left}px`);
75
- DROPDOWN.style.setProperty("--dropdown-arrow-left", `${arrowLeft}px`);
76
- };
12
+ function isDropdownContent(element) {
13
+ return element instanceof Element && pgs(element).contains("dropdown-content");
14
+ }
77
15
 
78
- BUTTON.addEventListener("click", e => {
79
- if (!USE_FALLBACK_POSITIONING) return;
16
+ function getDropdownTrigger(dropdown, content) {
17
+ const children = Array.from(dropdown.children).filter(child => child !== content);
18
+ const dropdownButton = children.find(child => pgs(child).contains("dropdown-button"));
80
19
 
81
- e.preventDefault();
82
- if (CONTENT.matches(":popover-open")) {
83
- CONTENT.hidePopover();
84
- return;
85
- }
20
+ return dropdownButton || children.find(child => !isDropdownContent(child)) || dropdown;
21
+ }
86
22
 
87
- updatePopoverPosition();
88
- CONTENT.showPopover();
89
- });
23
+ function getDropdownContent(dropdown) {
24
+ return Array.from(dropdown.children).find(isDropdownContent) || pgs(dropdown).querySelector("dropdown-content");
25
+ }
90
26
 
91
- // == sync ARIA + data-open quando apre/chiude
92
- CONTENT.addEventListener("toggle", e => {
93
- const open = CONTENT.matches(":popover-open");
94
- BUTTON.setAttribute("aria-expanded", open ? "true" : "false");
95
- pgs(DROPDOWN).state.toggle("open", open);
96
- if (open) {
97
- updatePopoverPosition();
98
- CONTENT.querySelector('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])')?.focus();
99
- }
100
- });
27
+ function getDropdowns(root) {
28
+ const dropdowns = root instanceof Element && pgs(root).contains("dropdown") ? [root] : [];
29
+ dropdowns.push(...pgs(root).querySelectorAll("dropdown"));
30
+ return dropdowns;
31
+ }
101
32
 
102
- window.addEventListener("resize", () => {
103
- if (CONTENT.matches(":popover-open")) updatePopoverPosition();
104
- });
105
- window.addEventListener("scroll", () => {
106
- if (CONTENT.matches(":popover-open")) updatePopoverPosition();
107
- }, true);
108
-
109
- function open() {
110
- if (CONTENT.matches(":popover-open")) return;
111
- updatePopoverPosition();
112
- CONTENT.showPopover();
113
- }
33
+ function getposition(dropdown) {
34
+ const option = pgs(dropdown).option;
35
+ const optionValue = option.getValueBrackets("position");
36
+ const raw = (optionValue || "bottom center").trim().toLowerCase();
37
+ const parts = raw.split(/\s+/).filter(Boolean);
38
+ const side = parts.find(part => ["top", "right", "bottom", "left"].includes(part)) || "bottom";
39
+ const align = parts.find(part => ["top", "right", "bottom", "left", "center"].includes(part) && part !== side) || "center";
114
40
 
115
- function close() {
116
- if (!CONTENT.matches(":popover-open")) return;
117
- CONTENT.hidePopover();
118
- }
41
+ return { side, align };
42
+ }
43
+
44
+ function clamp(value, min, max) {
45
+ return Math.min(Math.max(value, min), max);
46
+ }
47
+
48
+ function updateposition(dropdown) {
49
+ const data = API.get(dropdown);
50
+ if (!data || !data.isOpen()) return;
51
+
52
+ const { trigger, content } = data;
53
+ const { side, align } = getposition(dropdown);
54
+ const triggerRect = trigger.getBoundingClientRect();
55
+ const contentRect = content.getBoundingClientRect();
56
+ const viewportWidth = document.documentElement.clientWidth;
57
+ const maxLeft = Math.max(VIEWPORT_GAP, viewportWidth - contentRect.width - VIEWPORT_GAP);
58
+ let left = triggerRect.left + (triggerRect.width - contentRect.width) / 2;
59
+ let top = triggerRect.bottom + VIEWPORT_GAP;
60
+
61
+ if (side === "top" || side === "bottom") {
62
+ top = side === "top"
63
+ ? triggerRect.top - contentRect.height - VIEWPORT_GAP
64
+ : triggerRect.bottom + VIEWPORT_GAP;
65
+
66
+ if (align === "left") left = triggerRect.left;
67
+ if (align === "right") left = triggerRect.right - contentRect.width;
68
+ }
69
+
70
+ if (side === "left" || side === "right") {
71
+ left = side === "left"
72
+ ? triggerRect.left - contentRect.width - VIEWPORT_GAP
73
+ : triggerRect.right + VIEWPORT_GAP;
74
+ top = triggerRect.top + (triggerRect.height - contentRect.height) / 2;
75
+
76
+ if (align === "top") top = triggerRect.top;
77
+ if (align === "bottom") top = triggerRect.bottom - contentRect.height;
78
+ }
79
+
80
+ if (side === "left" && left < VIEWPORT_GAP) {
81
+ left = triggerRect.right + VIEWPORT_GAP;
82
+ }
83
+
84
+ if (side === "right" && left + contentRect.width > viewportWidth - VIEWPORT_GAP) {
85
+ left = triggerRect.left - contentRect.width - VIEWPORT_GAP;
86
+ }
87
+
88
+ left = clamp(left, VIEWPORT_GAP, maxLeft);
89
+
90
+ content.style.setProperty("--dropdown-left", `${Math.round(left)}px`);
91
+ content.style.setProperty("--dropdown-top", `${Math.round(top)}px`);
92
+ }
93
+
94
+ function updateOpenDropdowns() {
95
+ OPEN_DROPDOWNS.forEach(updateposition);
96
+ }
97
+
98
+ function closeDropdown(dropdown) {
99
+ const data = API.get(dropdown);
100
+ if (!data || !data.isOpen()) return;
101
+
102
+ pgs(dropdown).state.remove("open");
103
+ data.trigger.setAttribute("aria-expanded", "false");
104
+ OPEN_DROPDOWNS.delete(dropdown);
105
+ }
106
+
107
+ function openDropdown(dropdown) {
108
+ const data = API.get(dropdown);
109
+ if (!data || data.isOpen()) return;
119
110
 
120
- function toggle() {
121
- CONTENT.matches(":popover-open") ? close() : open();
111
+ OPEN_DROPDOWNS.forEach(item => {
112
+ if (item !== dropdown) closeDropdown(item);
113
+ });
114
+
115
+ pgs(dropdown).state.add("open");
116
+ data.trigger.setAttribute("aria-expanded", "true");
117
+ OPEN_DROPDOWNS.add(dropdown);
118
+ updateposition(dropdown);
119
+ }
120
+
121
+ function toggleDropdown(dropdown) {
122
+ const data = API.get(dropdown);
123
+ if (!data) return;
124
+
125
+ if (data.isOpen()) closeDropdown(dropdown);
126
+ else openDropdown(dropdown);
127
+ }
128
+
129
+ function isInsideAnyDropdown(target) {
130
+ return Array.from(OPEN_DROPDOWNS).some(dropdown => dropdown.contains(target));
131
+ }
132
+
133
+ function PGS_dropdown_init(root = document) {
134
+ getDropdowns(root).forEach((DROPDOWN) => {
135
+ if (API.has(DROPDOWN)) return;
136
+
137
+ const CONTENT = getDropdownContent(DROPDOWN);
138
+ if (!CONTENT) return;
139
+
140
+ const TRIGGER = getDropdownTrigger(DROPDOWN, CONTENT);
141
+ const id = nextDropdownId();
142
+
143
+ if (!TRIGGER.id) TRIGGER.id = `dropdown-btn-${id}`;
144
+ if (!CONTENT.id) CONTENT.id = `dropdown-panel-${id}`;
145
+
146
+ if (TRIGGER.matches("button") && !TRIGGER.hasAttribute("type")) {
147
+ TRIGGER.setAttribute("type", "button");
122
148
  }
123
149
 
124
- API.set(DROPDOWN, {
150
+ TRIGGER.setAttribute("aria-haspopup", "true");
151
+ TRIGGER.setAttribute("aria-controls", CONTENT.id);
152
+ TRIGGER.setAttribute("aria-expanded", String(pgs(DROPDOWN).state.contains("open")));
153
+ CONTENT.setAttribute("aria-labelledby", TRIGGER.id);
154
+
155
+ const data = {
125
156
  element: DROPDOWN,
126
- button: BUTTON,
157
+ trigger: TRIGGER,
127
158
  content: CONTENT,
128
- open,
129
- close,
130
- toggle,
131
- updatePosition: updatePopoverPosition,
159
+ open: () => openDropdown(DROPDOWN),
160
+ close: () => closeDropdown(DROPDOWN),
161
+ toggle: () => toggleDropdown(DROPDOWN),
132
162
  refresh: () => {
133
163
  PGS_dropdown_init(DROPDOWN.parentNode || document);
164
+ updateposition(DROPDOWN);
134
165
  return API.get(DROPDOWN);
135
166
  },
136
- isOpen: () => CONTENT.matches(":popover-open"),
167
+ isOpen: () => pgs(DROPDOWN).state.contains("open")
168
+ };
169
+
170
+ TRIGGER.addEventListener("click", (event) => {
171
+ if (isDropdownContent(event.target)) return;
172
+ event.preventDefault();
173
+ event.stopPropagation();
174
+ toggleDropdown(DROPDOWN);
137
175
  });
176
+
177
+ CONTENT.addEventListener("click", event => event.stopPropagation());
178
+ API.set(DROPDOWN, data);
179
+
180
+ if (data.isOpen()) OPEN_DROPDOWNS.add(DROPDOWN);
181
+ updateposition(DROPDOWN);
138
182
  });
139
183
  }
140
184
 
185
+ document.addEventListener("click", (event) => {
186
+ if (isInsideAnyDropdown(event.target)) return;
187
+ OPEN_DROPDOWNS.forEach(closeDropdown);
188
+ });
189
+
190
+ document.addEventListener("keydown", (event) => {
191
+ if (event.key !== "Escape") return;
192
+ OPEN_DROPDOWNS.forEach(closeDropdown);
193
+ });
194
+
195
+ window.addEventListener("resize", updateOpenDropdowns);
196
+ window.addEventListener("scroll", updateOpenDropdowns, true);
197
+
141
198
  // # INIT
142
199
  PGS_dropdown_init();
143
200
 
144
201
  // # API
145
- export function PGS_dropdown_api(selector) {
202
+ function PGS_dropdown_api(selector) {
146
203
  return API.get(selector);
147
204
  }
148
205
 
149
206
  export const PGS_dropdown = {
150
- PGS_name: "PGS_dropdown",
151
207
  init: PGS_dropdown_init,
152
208
  api: PGS_dropdown_api
153
209
  };
@@ -1,157 +1,56 @@
1
- import { PGS_dropdown_init, PGS_dropdown_api } from "./_dropdown";
1
+ import { PGS_dropdown } from "./_dropdown";
2
2
 
3
3
  const API = new WeakMap();
4
4
 
5
5
  //= DROP DOWN MENU
6
- export function PGS_menu_init(root = document) {
6
+ function PGS_menu_init(root = document) {
7
7
 
8
- pgs(root).querySelectorAll('menu-horizontal').forEach(MENU => {
8
+ pgs(root).querySelectorAll('menu').forEach(MENU => {
9
9
  if (API.has(MENU)) return;
10
10
 
11
- MENU.querySelectorAll('nav > ul > li.menu-item-has-children').forEach(li => {
12
- if (li.querySelector("ul")) {
13
- const ul = li.querySelector("ul");
14
- if (pgs(li).querySelector("dropdown-button")) return;
11
+ MENU.querySelectorAll('li').forEach(li => {
12
+ const ul = li.querySelector("ul");
13
+
14
+ if (ul) {
15
15
 
16
16
  const button = document.createElement("button");
17
- button.className = "icon-down";
18
17
  button.type = "button";
19
18
  button.innerHTML = "<span>&#9207;</span>";
19
+ pgs(button).add("menu-buttonIcon");
20
20
  li.querySelector("a").insertAdjacentElement("afterend", button);
21
21
 
22
22
  pgs(li).add("dropdown")
23
23
  pgs(button).add("dropdown-button")
24
24
  pgs(button).add("buttonNohover")
25
25
  pgs(ul).add("dropdown-content")
26
- pgs(ul).add("menu-vertical")
26
+
27
27
  }
28
28
  });
29
29
 
30
30
  API.set(MENU, {
31
31
  element: MENU,
32
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),
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
36
  refresh: () => {
37
37
  PGS_menu_init(MENU.parentNode || document);
38
38
  return API.get(MENU);
39
39
  },
40
40
  });
41
+ PGS_dropdown.init(MENU);
41
42
  });
42
43
 
43
- pgs(root).querySelectorAll('menu-vertical').forEach(MENU => {
44
- if (API.has(MENU)) return;
45
-
46
- MENU.querySelectorAll('.menu-item-has-children').forEach((li, index) => {
47
- const ul = li.querySelector("ul");
48
-
49
- if (!ul) return
50
- if (li.querySelector(":scope > button")) return;
51
-
52
- const button = document.createElement("button");
53
- button.className = "icon-down buttonIcon";
54
- button.type = "button";
55
-
56
- // ID unico per aria-controls
57
- const submenuId = `vertical-submenu-${index}`;
58
- ul.id = submenuId;
59
-
60
- // Stato iniziale
61
- pgs(button).add("buttonIcon")
62
- button.setAttribute("aria-expanded", "false");
63
- button.setAttribute("aria-controls", submenuId);
64
- button.setAttribute("aria-label", "Apri sottomenu");
65
- button.innerHTML = "<span aria-hidden='true'>&#9207;</span>";
66
- li.querySelector("a").insertAdjacentElement("afterend", button);
67
-
68
- function toggleMenu() {
69
- // const isOpena = ul.classList.toggle("open");
70
- const isOpen = pgs(ul).state.toggle("open");
71
- button.setAttribute("aria-expanded", isOpen);
72
- button.setAttribute("aria-label", isOpen ? "Chiudi sottomenu" : "Apri sottomenu");
73
- };
74
-
75
- // Click
76
- button.addEventListener("click", toggleMenu);
77
- button.addEventListener("keydown", (e) => {
78
- if (e.key === "Enter" || e.key === " ") {
79
- e.preventDefault();
80
- toggleMenu();
81
- }
82
- });
83
- });
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
-
121
- // pgs(document).querySelectorAll('menu-vertical').forEach(MENU => {
122
-
123
- // MENU.querySelectorAll('.menu-item-has-children').forEach(li => {
124
- // if (li.querySelector("ul")) {
125
- // const ul = li.querySelector("ul");
126
-
127
- // const button = document.createElement("button");
128
- // button.className = "icon-down";
129
- // button.type = "button";
130
- // button.innerHTML = "<span>&#9207;</span>";
131
- // li.querySelector("a").insertAdjacentElement("afterend", button);
132
-
133
-
134
- // pgs(button).add("buttonIcon")
135
- // button.addEventListener("click", () => {
136
- // ul.classList.toggle("open")
137
- // })
138
- // }
139
- // });
140
- // });
141
- });
142
- PGS_dropdown_init()
143
44
  }
144
45
 
145
- //# INIT PGS_menu
146
46
  PGS_menu_init()
147
47
 
148
- //# API
149
- export function PGS_menu_api(selector) {
48
+ function PGS_menu_api(selector) {
150
49
  return API.get(selector);
151
50
  }
152
51
 
52
+ //# EXPORT
153
53
  export const PGS_menu = {
154
- PGS_name: "PGS_menu",
155
54
  init: PGS_menu_init,
156
55
  api: PGS_menu_api
157
56
  };
@@ -159,7 +159,6 @@ export function PGS_modal_api(selector) {
159
159
  }
160
160
 
161
161
  export const PGS_modal = {
162
- PGS_name: "PGS_modal",
163
162
  init: PGS_modal_init,
164
163
  api: PGS_modal_api
165
164
  };
@@ -139,17 +139,16 @@ export function PGS_notificationTrigger_init(root = document) {
139
139
  }
140
140
 
141
141
  export const PGS_notification = {
142
- PGS_name: "PGS_notification",
143
142
  trigger: PGS_notificationTrigger_init,
144
143
  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),
144
+ error: (text = "Errore", link = null, timeout = 0, icon = '<i class="fa-solid fa-circle-xmark"></i>') => fn_notification.initNotification("error", "notification", icon, text, timeout, "stack", link),
146
145
  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
146
  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
147
  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
148
  deleteAll: () => fn_notification.deleteAll("notification")
150
149
  },
151
150
  toast: {
152
- error: (text = "Errore", timeout = 4000, icon = '<i class="fa-solid fa-octagon-xmark"></i>',) => fn_notification.initNotification("error", "toast", icon, text, timeout),
151
+ error: (text = "Errore", timeout = 4000, icon = '<i class="fa-solid fa-circle-xmark"></i>',) => fn_notification.initNotification("error", "toast", icon, text, timeout),
153
152
  success: (text = "Aggiornato", timeout = 4000, icon = '<i class="fa-solid fa-check"></i>',) => fn_notification.initNotification("success", "toast", icon, text, timeout),
154
153
  info: (text = "Aggiornamento", timeout = 0, icon = '<i class="fa-solid fa-circle-info"></i>',) => fn_notification.initNotification("info", "toast", icon, text, timeout),
155
154
  warning: (text = "Attenzione", timeout = 4000, icon = '<i class="fa-solid fa-triangle-exclamation"></i>',) => fn_notification.initNotification("warning", "toast", icon, text, timeout),
@@ -188,7 +188,6 @@ export function PGS_slides_api(selector) {
188
188
  }
189
189
 
190
190
  export const PGS_slides = {
191
- PGS_name: "PGS_slides",
192
191
  init: PGS_slides_init,
193
192
  api: PGS_slides_api
194
193
  };
@@ -140,7 +140,6 @@ export function PGS_stepTabs_api(selector) {
140
140
  }
141
141
 
142
142
  export const PGS_stepTabs = {
143
- PGS_name: "PGS_stepTabs",
144
143
  init: PGS_stepTabs_init,
145
144
  api: PGS_stepTabs_api
146
145
  };
@@ -48,7 +48,6 @@ export function PGS_steps_api(selector) {
48
48
  }
49
49
 
50
50
  export const PGS_steps = {
51
- PGS_name: "PGS_steps",
52
51
  init: PGS_steps_init,
53
52
  api: PGS_steps_api
54
53
  };
@@ -96,7 +96,7 @@ function assignCookieRuntimeAttributes({ root, analyticsToggle, acceptAllButton,
96
96
  }
97
97
 
98
98
  //= CookieConsent
99
- document.addEventListener('DOMContentLoaded', function () {
99
+ function initCookieConsent() {
100
100
  const root = pgs(document).querySelector('cookieConsent');
101
101
  if (!root) return;
102
102
 
@@ -206,4 +206,10 @@ document.addEventListener('DOMContentLoaded', function () {
206
206
  } else {
207
207
  setBannerVisibility(true);
208
208
  }
209
- });
209
+ }
210
+
211
+ if (document.readyState === 'loading') {
212
+ document.addEventListener('DOMContentLoaded', initCookieConsent);
213
+ } else {
214
+ initCookieConsent();
215
+ }
@@ -31,7 +31,6 @@ declare global {
31
31
  value: string | null;
32
32
  state: PgsStateApi;
33
33
  option: PgsOptionApi;
34
- modules: PgsOptionApi;
35
34
  }
36
35
 
37
36
  interface PgsDocumentApi extends PgsQueryableApi {
@@ -45,7 +44,19 @@ declare global {
45
44
  (root: Element): PgsElementApi;
46
45
  (root: Document | Element): PgsApi;
47
46
  registerImport(...modules: unknown[]): PgsFunction;
47
+ registerModules(modules: Record<string, any>): PgsFunction;
48
48
  import(...names: string[]): Record<string, any>;
49
+ accordion?: any;
50
+ dropdown?: any;
51
+ menu?: any;
52
+ modal?: any;
53
+ notification?: any;
54
+ slides?: any;
55
+ stepTabs?: any;
56
+ steps?: any;
57
+ formValidate?: any;
58
+ scrollHorizontal?: any;
59
+ [moduleName: string]: any;
49
60
  }
50
61
 
51
62
  interface PgsBag extends PgsElementApi {}