mypgs 1.5.1 → 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.
Files changed (108) hide show
  1. package/AGENTS.md +8 -5
  2. package/README.md +1 -1
  3. package/assets/javascript/_imports.js +4 -0
  4. package/assets/javascript/_pgs.js +58 -0
  5. package/assets/javascript/base/_darkmode.js +27 -105
  6. package/assets/javascript/base/_svg.js +103 -0
  7. package/assets/javascript/components/_accordion.js +2 -2
  8. package/assets/javascript/components/_menu.js +1 -3
  9. package/assets/javascript/components/_modals.js +159 -136
  10. package/assets/javascript/components/_notifications.js +19 -9
  11. package/assets/javascript/components/_search.js +391 -0
  12. package/assets/javascript/components/_slides.js +66 -32
  13. package/assets/javascript/components/_stepTabs.js +4 -4
  14. package/assets/javascript/components/_steps.js +2 -2
  15. package/assets/javascript/components/_summary.js +2 -2
  16. package/assets/javascript/functions/_formValidate.js +97 -53
  17. package/assets/javascript/functions/_scrollY.js +10 -10
  18. package/assets/javascript/index.js +2 -0
  19. package/assets/javascript/layout/_header.js +29 -7
  20. package/assets/scss/base/_color.scss +5 -5
  21. package/assets/scss/base/_html.scss +2 -2
  22. package/assets/scss/base/_variables.scss +4 -2
  23. package/assets/scss/components/_dropdown.scss +2 -1
  24. package/assets/scss/components/_form.scss +2 -2
  25. package/assets/scss/components/_logo.scss +2 -2
  26. package/assets/scss/components/_menu.scss +20 -27
  27. package/assets/scss/components/_modals.scss +11 -1
  28. package/assets/scss/components/_notification.scss +23 -30
  29. package/assets/scss/components/_search.scss +140 -0
  30. package/assets/scss/index.scss +2 -2
  31. package/assets/scss/layout/_header.scss +1 -1
  32. package/assets/scss/layout/_pageShell.scss +19 -15
  33. package/assets/scss/mixin/_mx-form.scss +7 -7
  34. package/{templates/html → demo}/demo.html +1 -1
  35. package/demo/demo.js +240 -0
  36. package/dist/css/index.css +188 -125
  37. package/dist/css/index.css.map +1 -1
  38. package/dist/css/index.min.css +1 -1
  39. package/dist/index.d.ts +70 -0
  40. package/dist/javascript/index.js +1038 -405
  41. package/dist/javascript/index.js.map +1 -1
  42. package/dist/javascript/index.min.js +1 -1
  43. package/docs/componenti-e-markup.md +62 -27
  44. package/docs/components/accordion.md +61 -0
  45. package/docs/components/badges.md +67 -0
  46. package/docs/components/breadcumbs.md +43 -0
  47. package/docs/components/button.md +59 -0
  48. package/docs/components/card.md +50 -0
  49. package/docs/components/dropdown.md +135 -0
  50. package/docs/components/form.md +113 -0
  51. package/docs/components/logo.md +36 -0
  52. package/docs/components/menu.md +90 -0
  53. package/docs/components/modal.md +131 -0
  54. package/docs/components/notification.md +81 -0
  55. package/docs/components/search.md +117 -0
  56. package/docs/components/slides.md +85 -0
  57. package/docs/components/stepTabs.md +93 -0
  58. package/docs/components/steps.md +56 -0
  59. package/docs/components/summary.md +49 -0
  60. package/docs/components/table.md +42 -0
  61. package/docs/components/tooltip.md +53 -0
  62. package/docs/helper-javascript.md +71 -3
  63. package/docs/layout/body.md +41 -0
  64. package/docs/layout/flex.md +116 -0
  65. package/docs/layout/footer.md +71 -0
  66. package/docs/layout/grid.md +116 -0
  67. package/docs/layout/header.md +116 -0
  68. package/docs/layout/pageShell.md +94 -0
  69. package/docs/layout/section.md +69 -0
  70. package/docs/patterns/cookieConsent.md +89 -0
  71. package/package.json +2 -1
  72. package/scripts/generate-component-docs.js +557 -0
  73. package/templates/html/components/accordion.html +33 -4
  74. package/templates/html/components/badges.html +23 -0
  75. package/templates/html/components/breadcumbs.html +14 -0
  76. package/templates/html/components/button.html +22 -0
  77. package/templates/html/components/card.html +20 -0
  78. package/templates/html/components/dropdown.html +34 -0
  79. package/templates/html/components/form.html +82 -4
  80. package/templates/html/components/logo.html +22 -1
  81. package/templates/html/components/menu.html +40 -1
  82. package/templates/html/components/modal.html +44 -0
  83. package/templates/html/components/notification.html +68 -32
  84. package/templates/html/components/search.html +107 -0
  85. package/templates/html/components/slides.html +43 -0
  86. package/templates/html/components/stepTabs.html +47 -0
  87. package/templates/html/components/steps.html +24 -0
  88. package/templates/html/components/summary.html +27 -0
  89. package/templates/html/components/table.html +12 -0
  90. package/templates/html/components/tooltip.html +35 -0
  91. package/templates/html/layout/body.html +20 -5
  92. package/templates/html/layout/flex.html +20 -0
  93. package/templates/html/layout/footer.html +29 -1
  94. package/templates/html/layout/grid.html +20 -0
  95. package/templates/html/layout/header.html +52 -5
  96. package/templates/html/layout/pageShell.html +19 -0
  97. package/templates/html/layout/section.html +32 -10
  98. package/templates/html/patterns/cookieConsent.html +31 -0
  99. package/templates/react/components/form.jsx +3 -3
  100. package/templates/react/components/logo.jsx +1 -1
  101. package/templates/react/components/notification.jsx +4 -4
  102. package/templates/react/components/{searchbar.jsx → search.jsx} +9 -7
  103. package/templates/react/patterns/footer.jsx +1 -1
  104. package/templates/react/patterns/header.jsx +16 -10
  105. package/assets/scss/components/_searchbar.scss +0 -70
  106. package/templates/html/components/searchbar.html +0 -29
  107. package/templates/html/demo.js +0 -137
  108. /package/{templates/html → demo}/demo.css +0 -0
@@ -1,161 +1,184 @@
1
1
  //# MODAL
2
2
  const API = new WeakMap();
3
3
 
4
- export function PGS_modal_init(selector = "modal") {
5
- pgs(document).querySelectorAll(selector).forEach(MODAL => {
6
- if (API.has(MODAL)) return;
7
-
8
- const BUTTON_OPEN = pgs(MODAL).querySelector("modal-button");
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
- //+ FN STATUS
51
- function statusModal(status = true) {
52
- BUTTON_OPEN?.setAttribute("aria-expanded", status);
53
- DIALOG?.setAttribute("aria-expanded", status);
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
- //+ FN OPEN
57
- function openModal(e) {
58
- e?.stopImmediatePropagation();
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
- function forceOpen(e) {
83
- if (!DIALOG.open) openModal(e);
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
- function forceClose(e) {
87
- if (DIALOG.open) closeModal(e);
88
- }
32
+ //== OPTION ATTRIBUTES DIALOG
33
+ const topLevel = pgs(DIALOG).option.contains("topLevel");
89
34
 
90
- //+ fn OPEN ON HISTORY
91
- function openModalOnHistory() {
92
- const params = new URLSearchParams(window.location.search);
93
- if (params.get('modal') !== BUTTON_OPEN.id) return;
94
- document.getElementById(BUTTON_OPEN.id)?.scrollIntoView({ behavior: 'smooth' });
95
- openModal();
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
- //= OPEN
100
- BUTTON_OPEN.addEventListener("click", (e) => openModal(e));
101
- BUTTON_OPEN.addEventListener("keypress", (e) => !DIALOG.open && (e.key === "Enter" || e.key === " ") && openModal(e));
102
-
103
- //= CLOSE
104
- DIALOG.addEventListener("close", () => statusModal(false));
105
- DIALOG.addEventListener("click", e => { if (e.target == DIALOG && !disableBackdropClose) closeModal(e) });
106
- BUTTON_CLOSE?.addEventListener("click", e => closeModal(e));
107
-
108
- //= UPDATE HISTORY
109
- if (data_history && BUTTON_OPEN.id) {
110
- setTimeout(openModalOnHistory, 1);
111
-
112
- //== Aggiorna URL quando cambia l'attributo "open" del dialog
113
- const obs = new MutationObserver(() => {
114
- let isOpen = DIALOG.hasAttribute("open");
115
- try {
116
- const url = new URL(window.location.href);
117
- const params = new URLSearchParams(url.search);
118
- isOpen ? params.set('modal', BUTTON_OPEN.id) : params.delete('modal');
119
- url.search = params.toString() ? `?${params.toString()}` : "";
120
- window.history.pushState({ modal: BUTTON_OPEN.id, open: isOpen }, "", url);
121
- } catch (_) { }
122
- });
123
- obs.observe(DIALOG, { attributes: true, attributeFilter: ["open"] });
124
-
125
- //== Gestisce back/forward del browser per aprire/chiudere il dialog coerentemente
126
- window.addEventListener("popstate", () => {
127
- try {
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
- 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,
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
- export function PGS_modal_api(selector) {
158
- return API.get(selector);
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(root.dataset.notification || "{}");
30
+ return JSON.parse(rawNotification);
29
31
  } catch (error) {
30
- console.warn("PGS notification: dati non validi", error);
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
- initNotification(type, containerToken, icon, text, timeout, methodDelete = "replace", link = null) {
50
- let containerNotification = pgs(document).querySelector(containerToken);
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(containerToken);
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(containerToken) {
102
- let containerNotification = pgs(document).querySelector(containerToken);
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
- //# EXPORT
137
- export function PGS_notificationTrigger_init(root = document) {
146
+ //# TRIGGER
147
+ function PGS_notificationTrigger_init(root = document) {
138
148
  return fn_notification.trigger(root);
139
149
  }
140
150