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.
@@ -1,6 +1,54 @@
1
1
  /******/ (() => { // webpackBootstrap
2
2
  /******/ var __webpack_modules__ = ({
3
3
 
4
+ /***/ "./assets/javascript/_imports.js"
5
+ /*!***************************************!*\
6
+ !*** ./assets/javascript/_imports.js ***!
7
+ \***************************************/
8
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
9
+
10
+ "use strict";
11
+ __webpack_require__.r(__webpack_exports__);
12
+ /* harmony import */ var _pgs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_pgs.js */ "./assets/javascript/_pgs.js");
13
+ /* harmony import */ var _components_accordion_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./components/_accordion.js */ "./assets/javascript/components/_accordion.js");
14
+ /* harmony import */ var _components_dropdown_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/_dropdown.js */ "./assets/javascript/components/_dropdown.js");
15
+ /* harmony import */ var _components_menu_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/_menu.js */ "./assets/javascript/components/_menu.js");
16
+ /* harmony import */ var _components_modals_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/_modals.js */ "./assets/javascript/components/_modals.js");
17
+ /* harmony import */ var _components_notifications_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/_notifications.js */ "./assets/javascript/components/_notifications.js");
18
+ /* harmony import */ var _components_slides_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/_slides.js */ "./assets/javascript/components/_slides.js");
19
+ /* harmony import */ var _components_stepTabs_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/_stepTabs.js */ "./assets/javascript/components/_stepTabs.js");
20
+ /* harmony import */ var _components_steps_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./components/_steps.js */ "./assets/javascript/components/_steps.js");
21
+ /* harmony import */ var _functions_formValidate_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./functions/_formValidate.js */ "./assets/javascript/functions/_formValidate.js");
22
+ /* harmony import */ var _functions_scrollY_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./functions/_scrollY.js */ "./assets/javascript/functions/_scrollY.js");
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+ _pgs_js__WEBPACK_IMPORTED_MODULE_0__.pgs.registerImport({
37
+ PGS_accordion: _components_accordion_js__WEBPACK_IMPORTED_MODULE_1__.PGS_accordion,
38
+ PGS_dropdown: _components_dropdown_js__WEBPACK_IMPORTED_MODULE_2__.PGS_dropdown,
39
+ PGS_menu: _components_menu_js__WEBPACK_IMPORTED_MODULE_3__.PGS_menu,
40
+ PGS_modal: _components_modals_js__WEBPACK_IMPORTED_MODULE_4__.PGS_modal,
41
+ PGS_notification: _components_notifications_js__WEBPACK_IMPORTED_MODULE_5__.PGS_notification,
42
+ PGS_slides: _components_slides_js__WEBPACK_IMPORTED_MODULE_6__.PGS_slides,
43
+ PGS_stepTabs: _components_stepTabs_js__WEBPACK_IMPORTED_MODULE_7__.PGS_stepTabs,
44
+ PGS_steps: _components_steps_js__WEBPACK_IMPORTED_MODULE_8__.PGS_steps,
45
+ PGS_formValidate: _functions_formValidate_js__WEBPACK_IMPORTED_MODULE_9__.PGS_formValidate,
46
+ PGS_scrollHorizontal: _functions_scrollY_js__WEBPACK_IMPORTED_MODULE_10__.PGS_scrollHorizontal,
47
+ });
48
+
49
+
50
+ /***/ },
51
+
4
52
  /***/ "./assets/javascript/_pgs.js"
5
53
  /*!***********************************!*\
6
54
  !*** ./assets/javascript/_pgs.js ***!
@@ -238,9 +286,45 @@ function pgs(root) {
238
286
  return api;
239
287
  }
240
288
 
241
- globalThis.pgs ??= pgs;
289
+ const PGS_IMPORTS = {};
290
+
291
+ function registerImportModule(name, module) {
292
+ const key = String(name || "").trim().replace(/^pgs[_-\s]*/i, "").toLowerCase();
293
+
294
+ if (!key) throw new TypeError("pgs.registerImport(...modules): ogni modulo deve avere name o PGS_name");
295
+
296
+ PGS_IMPORTS[key] = {
297
+ name,
298
+ module
299
+ };
300
+ }
242
301
 
302
+ pgs.registerImport = function (...modules) {
303
+ modules.flat().forEach(item => {
304
+ if (item && typeof item === "object" && !item.PGS_name && !item.name) {
305
+ Object.entries(item).forEach(([name, module]) => registerImportModule(name, module));
306
+ return;
307
+ }
308
+
309
+ registerImportModule(item?.PGS_name || item?.name, item);
310
+ });
243
311
 
312
+ return pgs;
313
+ };
314
+
315
+ pgs.import = function (...names) {
316
+ return names.flat().reduce((imports, name) => {
317
+ const key = String(name || "").trim().replace(/^pgs[_-\s]*/i, "").toLowerCase();
318
+ const item = PGS_IMPORTS[key];
319
+
320
+ if (!item) throw new Error(`pgs.import(): modulo "${name}" non registrato`);
321
+
322
+ imports[item.name] = item.module;
323
+ return imports;
324
+ }, {});
325
+ };
326
+
327
+ globalThis.pgs ??= pgs;
244
328
 
245
329
 
246
330
  /***/ },
@@ -432,85 +516,131 @@ document.addEventListener('DOMContentLoaded', () => {
432
516
  /*!****************************************************!*\
433
517
  !*** ./assets/javascript/components/_accordion.js ***!
434
518
  \****************************************************/
435
- () {
519
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
436
520
 
437
- //= ACCORDION
438
- const allAccordion = pgs(document).querySelectorAll("accordion")
521
+ "use strict";
522
+ __webpack_require__.r(__webpack_exports__);
523
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
524
+ /* harmony export */ PGS_accordion: () => (/* binding */ PGS_accordion),
525
+ /* harmony export */ PGS_accordion_api: () => (/* binding */ PGS_accordion_api),
526
+ /* harmony export */ PGS_accordion_init: () => (/* binding */ PGS_accordion_init)
527
+ /* harmony export */ });
528
+ //= ACCORDION
529
+ const API = new WeakMap();
439
530
 
440
- allAccordion.forEach((accordion, index) => {
531
+ function PGS_accordion_init(root = document) {
532
+ pgs(root).querySelectorAll("accordion").forEach((accordion, index) => {
533
+ if (API.has(accordion)) return;
441
534
 
442
- const BUTTON = pgs(accordion).querySelector("accordion-button");
443
- const CONTENT = pgs(accordion).querySelector("accordion-content");
535
+ const BUTTON = pgs(accordion).querySelector("accordion-button");
536
+ const CONTENT = pgs(accordion).querySelector("accordion-content");
537
+ if (!BUTTON || !CONTENT) return;
444
538
 
445
- //== ID univoci per aria-controls / aria-labelledby
446
- const ID = index + 1;
447
- const btnId = `acc-btn-${ID}`;
448
- const panelId = `acc-panel-${ID}`;
539
+ //== ID univoci per aria-controls / aria-labelledby
540
+ const ID = index + 1;
541
+ const btnId = `acc-btn-${ID}`;
542
+ const panelId = `acc-panel-${ID}`;
543
+
544
+ //== Stato iniziale
545
+ const isOpenInit = pgs(accordion).state.contains("open");
546
+
547
+ //== Accessibilità (setup una volta)
548
+ BUTTON.setAttribute("role", "button");
549
+ BUTTON.setAttribute("tabindex", "0");
550
+ BUTTON.setAttribute("id", btnId);
551
+ BUTTON.setAttribute("aria-controls", panelId);
552
+
553
+ CONTENT.setAttribute("id", panelId);
554
+ CONTENT.setAttribute("role", "region");
555
+ CONTENT.setAttribute("aria-labelledby", btnId);
556
+
557
+ //+ Accessibility (applica stato aperto/chiuso)
558
+ function accordionAccessibility(isOpen, button, content) {
559
+ const text = (button?.textContent || "").trim().replace(/\s+/g, " ");
560
+ button.setAttribute("aria-label", `${isOpen ? "Chiudi" : "Apri"} ${text || "sezione"}`);
561
+ button.setAttribute("aria-expanded", String(isOpen));
562
+ content.hidden = !isOpen;
563
+ }
449
564
 
450
- //== Stato iniziale
451
- const isOpenInit = pgs(accordion).state.contains("open");
565
+ //+ Chiudi tutti gli altri
566
+ function closeOltherAccordion() {
567
+ for (const otherLi of pgs(document).querySelectorAll("accordion")) {
568
+ if (otherLi === accordion) continue;
452
569
 
453
- //== Accessibilità (setup una volta)
454
- BUTTON.setAttribute("role", "button");
455
- BUTTON.setAttribute("tabindex", "0");
456
- BUTTON.setAttribute("id", btnId);
457
- BUTTON.setAttribute("aria-controls", panelId);
570
+ const otherBtn = pgs(otherLi).querySelector("accordion-button");
571
+ const otherContent = pgs(otherLi).querySelector("accordion-content");
572
+ if (!otherBtn || !otherContent) continue;
458
573
 
459
- CONTENT.setAttribute("id", panelId);
460
- CONTENT.setAttribute("role", "region");
461
- CONTENT.setAttribute("aria-labelledby", btnId);
574
+ pgs(otherLi).state().remove("open");
575
+ accordionAccessibility(false, otherBtn, otherContent);
576
+ }
577
+ }
462
578
 
463
- //+ Accessibility (applica stato aperto/chiuso)
464
- function accordionAccessibility(isOpen, button, content) {
465
- const text = (button?.textContent || "").trim().replace(/\s+/g, " ");
466
- button.setAttribute("aria-label", `${isOpen ? "Chiudi" : "Apri"} ${text || "sezione"}`);
467
- button.setAttribute("aria-expanded", String(isOpen));
468
- content.hidden = !isOpen;
469
- }
579
+ //+ FN ACCORDION
580
+ function accordionFunction() {
581
+ const isOpen = pgs(accordion).state.contains("open");
582
+ const nowOpen = !isOpen;
470
583
 
471
- //+ Chiudi tutti gli altri
472
- function closeOltherAccordion() {
473
- for (const otherLi of allAccordion) {
474
- if (otherLi === accordion) continue;
584
+ pgs(accordion).state.toggle("open", nowOpen);
585
+ accordionAccessibility(nowOpen, BUTTON, CONTENT);
475
586
 
476
- const otherBtn = pgs(otherLi).querySelector("accordion-button");
477
- const otherContent = pgs(otherLi).querySelector("accordion-content");
478
- if (!otherBtn || !otherContent) continue;
587
+ closeOltherAccordion();
479
588
 
480
- pgs(otherLi).state().remove("open");
481
- accordionAccessibility(false, otherBtn, otherContent);
589
+ //== scroll to view
590
+ if (nowOpen) setTimeout(() => accordion.scrollIntoView({ block: "nearest", inline: "nearest" }), 100);
482
591
  }
483
- }
484
592
 
485
- //+ FN ACCORDION
486
- function accordionFunction() {
487
- const isOpen = pgs(accordion).state.contains("open");
488
- const nowOpen = !isOpen;
489
-
490
- pgs(accordion).state.toggle("open", nowOpen);
491
- accordionAccessibility(nowOpen, BUTTON, CONTENT);
593
+ function open() {
594
+ if (!pgs(accordion).state.contains("open")) accordionFunction();
595
+ }
492
596
 
493
- closeOltherAccordion();
597
+ function close() {
598
+ if (pgs(accordion).state.contains("open")) accordionFunction();
599
+ }
494
600
 
495
- //== scroll to view
496
- if (nowOpen) setTimeout(() => accordion.scrollIntoView({ block: "nearest", inline: "nearest" }), 100);
497
- }
601
+ // applica stato iniziale
602
+ accordionAccessibility(isOpenInit, BUTTON, CONTENT);
498
603
 
499
- // applica stato iniziale
500
- accordionAccessibility(isOpenInit, BUTTON, CONTENT);
604
+ //- Eventi
605
+ BUTTON.addEventListener("click", accordionFunction);
501
606
 
502
- //- Eventi
503
- BUTTON.addEventListener("click", accordionFunction);
607
+ //- Tastiera: Enter / Space
608
+ BUTTON.addEventListener("keydown", (e) => {
609
+ if (e.key === "Enter" || e.key === " ") {
610
+ e.preventDefault();
611
+ accordionFunction();
612
+ }
613
+ });
504
614
 
505
- //- Tastiera: Enter / Space
506
- BUTTON.addEventListener("keydown", (e) => {
507
- if (e.key === "Enter" || e.key === " ") {
508
- e.preventDefault();
509
- accordionFunction();
510
- }
615
+ API.set(accordion, {
616
+ element: accordion,
617
+ button: BUTTON,
618
+ content: CONTENT,
619
+ open,
620
+ close,
621
+ toggle: accordionFunction,
622
+ refresh: () => {
623
+ PGS_accordion_init(accordion.parentNode || document);
624
+ return API.get(accordion);
625
+ },
626
+ isOpen: () => pgs(accordion).state.contains("open"),
627
+ });
511
628
  });
629
+ }
512
630
 
513
- });
631
+ //# INIT
632
+ PGS_accordion_init();
633
+
634
+ //# API
635
+ function PGS_accordion_api(selector) {
636
+ return API.get(selector);
637
+ }
638
+
639
+ const PGS_accordion = {
640
+ PGS_name: "PGS_accordion",
641
+ init: PGS_accordion_init,
642
+ api: PGS_accordion_api
643
+ };
514
644
 
515
645
 
516
646
  /***/ },
@@ -524,11 +654,17 @@ allAccordion.forEach((accordion, index) => {
524
654
  "use strict";
525
655
  __webpack_require__.r(__webpack_exports__);
526
656
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
527
- /* harmony export */ pgs_dropdown: () => (/* binding */ pgs_dropdown)
657
+ /* harmony export */ PGS_dropdown: () => (/* binding */ PGS_dropdown),
658
+ /* harmony export */ PGS_dropdown_api: () => (/* binding */ PGS_dropdown_api),
659
+ /* harmony export */ PGS_dropdown_init: () => (/* binding */ PGS_dropdown_init)
528
660
  /* harmony export */ });
529
661
  // + dropdown (Popover API)
530
- function pgs_dropdown() {
531
- pgs(document).querySelectorAll("dropdown").forEach((DROPDOWN, index) => {
662
+ const API = new WeakMap();
663
+
664
+ function PGS_dropdown_init(root = document) {
665
+ pgs(root).querySelectorAll("dropdown").forEach((DROPDOWN, index) => {
666
+ if (API.has(DROPDOWN)) return;
667
+
532
668
  const BUTTON = pgs(DROPDOWN).querySelector("dropdown-button");
533
669
  const CONTENT = pgs(DROPDOWN).querySelector("dropdown-content");
534
670
 
@@ -629,112 +765,52 @@ function pgs_dropdown() {
629
765
  window.addEventListener("scroll", () => {
630
766
  if (CONTENT.matches(":popover-open")) updatePopoverPosition();
631
767
  }, true);
632
- });
633
- }
634
768
 
635
- // # INIT
636
- pgs_dropdown();
637
-
638
-
639
- /***/ },
640
-
641
- /***/ "./assets/javascript/components/_exeNotifications.js"
642
- /*!***********************************************************!*\
643
- !*** ./assets/javascript/components/_exeNotifications.js ***!
644
- \***********************************************************/
645
- (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
646
-
647
- "use strict";
648
- __webpack_require__.r(__webpack_exports__);
649
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
650
- /* harmony export */ PGS_md_notification: () => (/* binding */ PGS_md_notification)
651
- /* harmony export */ });
652
- /* harmony import */ var _functions_notifications_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../functions/_notifications.js */ "./assets/javascript/functions/_notifications.js");
653
-
654
-
655
- function escapeHtml(value) {
656
- return String(value ?? "");
657
- }
658
-
659
- function getDuration(notification) {
660
- const rawDuration = notification.duration;
661
- const duration = Number.parseInt(rawDuration, 10);
662
-
663
- return Number.isNaN(duration) ? 5000 : duration;
664
- }
665
-
666
- function getNotificationApi(notification) {
667
- const element = String(notification.element || "notification").trim();
668
-
669
- return element === "toast" ? _functions_notifications_js__WEBPACK_IMPORTED_MODULE_0__.PGS_toast : _functions_notifications_js__WEBPACK_IMPORTED_MODULE_0__.PGS_notification;
670
- }
671
-
672
- function getNotificationType(notification, api) {
673
- const type = String(notification.type || "info").trim();
674
-
675
- return typeof api[type] === "function" ? type : "info";
676
- }
677
-
678
- function getNotificationData(root) {
679
- try {
680
- return JSON.parse(root.dataset.notification || "{}");
681
- } catch (error) {
682
- console.warn("PGS notification: dati non validi", error);
683
- return {};
684
- }
685
- }
769
+ function open() {
770
+ if (CONTENT.matches(":popover-open")) return;
771
+ updatePopoverPosition();
772
+ CONTENT.showPopover();
773
+ }
686
774
 
687
- function getNotificationContent(title, content) {
688
- const safeContent = escapeHtml(content);
689
- const safeTitle = escapeHtml(title);
775
+ function close() {
776
+ if (!CONTENT.matches(":popover-open")) return;
777
+ CONTENT.hidePopover();
778
+ }
690
779
 
691
- if (!safeTitle) return safeContent;
692
- if (!safeContent) return `<span pgs="notification-element-title">${safeTitle}</span>`;
780
+ function toggle() {
781
+ CONTENT.matches(":popover-open") ? close() : open();
782
+ }
693
783
 
694
- return `
695
- <span pgs="notification-element-title">${safeTitle}</span>
696
- <br>
697
- <span pgs="notification-element-content">${safeContent}</span>
698
- `;
784
+ API.set(DROPDOWN, {
785
+ element: DROPDOWN,
786
+ button: BUTTON,
787
+ content: CONTENT,
788
+ open,
789
+ close,
790
+ toggle,
791
+ updatePosition: updatePopoverPosition,
792
+ refresh: () => {
793
+ PGS_dropdown_init(DROPDOWN.parentNode || document);
794
+ return API.get(DROPDOWN);
795
+ },
796
+ isOpen: () => CONTENT.matches(":popover-open"),
797
+ });
798
+ });
699
799
  }
700
800
 
701
- function PGS_md_notification(root) {
702
- if (!root || root.dataset.initialize === "true") return;
703
- root.dataset.initialize = "true";
704
-
705
- const notification = getNotificationData(root);
706
- const title = String(notification.title || "").trim();
707
- const content = String(notification.message || "").trim();
708
- if (!title && !content) {
709
- root.remove();
710
- return;
711
- }
712
-
713
- const link = notification.link || null;
714
- const icon = notification.icon || undefined;
715
- const duration = getDuration(notification);
716
- const api = getNotificationApi(notification);
717
- const type = getNotificationType(notification, api);
718
- const formattedContent = getNotificationContent(title, content);
719
-
720
- if (api === _functions_notifications_js__WEBPACK_IMPORTED_MODULE_0__.PGS_toast) {
721
- api[type](formattedContent, duration, icon);
722
- } else {
723
- api[type](formattedContent, link, duration, icon);
724
- }
725
-
726
- root.remove();
727
- }
801
+ // # INIT
802
+ PGS_dropdown_init();
728
803
 
729
- function initMdNotifications() {
730
- pgs(document).querySelectorAll("notificationTrigger").forEach(PGS_md_notification);
804
+ // # API
805
+ function PGS_dropdown_api(selector) {
806
+ return API.get(selector);
731
807
  }
732
808
 
733
- if (document.readyState === "loading") {
734
- document.addEventListener("DOMContentLoaded", initMdNotifications);
735
- } else {
736
- initMdNotifications();
737
- }
809
+ const PGS_dropdown = {
810
+ PGS_name: "PGS_dropdown",
811
+ init: PGS_dropdown_init,
812
+ api: PGS_dropdown_api
813
+ };
738
814
 
739
815
 
740
816
  /***/ },
@@ -748,19 +824,25 @@ if (document.readyState === "loading") {
748
824
  "use strict";
749
825
  __webpack_require__.r(__webpack_exports__);
750
826
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
751
- /* harmony export */ PGS_menu: () => (/* binding */ PGS_menu)
827
+ /* harmony export */ PGS_menu: () => (/* binding */ PGS_menu),
828
+ /* harmony export */ PGS_menu_api: () => (/* binding */ PGS_menu_api),
829
+ /* harmony export */ PGS_menu_init: () => (/* binding */ PGS_menu_init)
752
830
  /* harmony export */ });
753
831
  /* harmony import */ var _dropdown__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_dropdown */ "./assets/javascript/components/_dropdown.js");
754
832
 
755
833
 
834
+ const API = new WeakMap();
835
+
756
836
  //= DROP DOWN MENU
757
- function PGS_menu() {
837
+ function PGS_menu_init(root = document) {
758
838
 
759
- pgs(document).querySelectorAll('menu-horizontal').forEach(MENU => {
839
+ pgs(root).querySelectorAll('menu-horizontal').forEach(MENU => {
840
+ if (API.has(MENU)) return;
760
841
 
761
842
  MENU.querySelectorAll('nav > ul > li.menu-item-has-children').forEach(li => {
762
843
  if (li.querySelector("ul")) {
763
844
  const ul = li.querySelector("ul");
845
+ if (pgs(li).querySelector("dropdown-button")) return;
764
846
 
765
847
  const button = document.createElement("button");
766
848
  button.className = "icon-down";
@@ -775,14 +857,28 @@ function PGS_menu() {
775
857
  pgs(ul).add("menu-vertical")
776
858
  }
777
859
  });
860
+
861
+ API.set(MENU, {
862
+ element: MENU,
863
+ type: "horizontal",
864
+ items: () => Array.from(MENU.querySelectorAll('nav > ul > li')),
865
+ submenus: () => Array.from(MENU.querySelectorAll('.menu-item-has-children > ul')),
866
+ dropdowns: () => Array.from(MENU.querySelectorAll('.menu-item-has-children')).map(_dropdown__WEBPACK_IMPORTED_MODULE_0__.PGS_dropdown_api).filter(Boolean),
867
+ refresh: () => {
868
+ PGS_menu_init(MENU.parentNode || document);
869
+ return API.get(MENU);
870
+ },
871
+ });
778
872
  });
779
873
 
780
- pgs(document).querySelectorAll('menu-vertical').forEach(MENU => {
874
+ pgs(root).querySelectorAll('menu-vertical').forEach(MENU => {
875
+ if (API.has(MENU)) return;
781
876
 
782
877
  MENU.querySelectorAll('.menu-item-has-children').forEach((li, index) => {
783
878
  const ul = li.querySelector("ul");
784
879
 
785
880
  if (!ul) return
881
+ if (li.querySelector(":scope > button")) return;
786
882
 
787
883
  const button = document.createElement("button");
788
884
  button.className = "icon-down buttonIcon";
@@ -817,6 +913,42 @@ function PGS_menu() {
817
913
  });
818
914
  });
819
915
 
916
+ function submenu(index) {
917
+ return MENU.querySelectorAll('.menu-item-has-children > ul')[index];
918
+ }
919
+
920
+ function setSubmenu(index, open) {
921
+ const ul = submenu(index);
922
+ const button = ul?.parentElement?.querySelector(":scope > button");
923
+ if (!ul || !button) return;
924
+
925
+ pgs(ul).state.toggle("open", open);
926
+ button.setAttribute("aria-expanded", String(open));
927
+ button.setAttribute("aria-label", open ? "Chiudi sottomenu" : "Apri sottomenu");
928
+ }
929
+
930
+ API.set(MENU, {
931
+ element: MENU,
932
+ type: "vertical",
933
+ items: () => Array.from(MENU.querySelectorAll(':scope > li')),
934
+ submenus: () => Array.from(MENU.querySelectorAll('.menu-item-has-children > ul')),
935
+ openSubmenu: (index) => setSubmenu(index, true),
936
+ closeSubmenu: (index) => setSubmenu(index, false),
937
+ toggleSubmenu: (index) => {
938
+ const ul = submenu(index);
939
+ if (!ul) return;
940
+ setSubmenu(index, !pgs(ul).state.contains("open"));
941
+ },
942
+ isSubmenuOpen: (index) => {
943
+ const ul = submenu(index);
944
+ return ul ? pgs(ul).state.contains("open") : false;
945
+ },
946
+ refresh: () => {
947
+ PGS_menu_init(MENU.parentNode || document);
948
+ return API.get(MENU);
949
+ },
950
+ });
951
+
820
952
  // pgs(document).querySelectorAll('menu-vertical').forEach(MENU => {
821
953
 
822
954
  // MENU.querySelectorAll('.menu-item-has-children').forEach(li => {
@@ -838,11 +970,23 @@ function PGS_menu() {
838
970
  // });
839
971
  // });
840
972
  });
841
- (0,_dropdown__WEBPACK_IMPORTED_MODULE_0__.pgs_dropdown)()
973
+ (0,_dropdown__WEBPACK_IMPORTED_MODULE_0__.PGS_dropdown_init)()
842
974
  }
843
975
 
844
976
  //# INIT PGS_menu
845
- PGS_menu()
977
+ PGS_menu_init()
978
+
979
+ //# API
980
+ function PGS_menu_api(selector) {
981
+ return API.get(selector);
982
+ }
983
+
984
+ const PGS_menu = {
985
+ PGS_name: "PGS_menu",
986
+ init: PGS_menu_init,
987
+ api: PGS_menu_api
988
+ };
989
+
846
990
 
847
991
  /***/ },
848
992
 
@@ -855,12 +999,16 @@ PGS_menu()
855
999
  "use strict";
856
1000
  __webpack_require__.r(__webpack_exports__);
857
1001
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
858
- /* harmony export */ PGS_modal: () => (/* binding */ PGS_modal)
1002
+ /* harmony export */ PGS_modal: () => (/* binding */ PGS_modal),
1003
+ /* harmony export */ PGS_modal_api: () => (/* binding */ PGS_modal_api),
1004
+ /* harmony export */ PGS_modal_init: () => (/* binding */ PGS_modal_init)
859
1005
  /* harmony export */ });
860
1006
  //# MODAL
861
- PGS_modal()
862
- function PGS_modal(selector = "modal") {
1007
+ const API = new WeakMap();
1008
+
1009
+ function PGS_modal_init(selector = "modal") {
863
1010
  pgs(document).querySelectorAll(selector).forEach(MODAL => {
1011
+ if (API.has(MODAL)) return;
864
1012
 
865
1013
  const BUTTON_OPEN = pgs(MODAL).querySelector("modal-button");
866
1014
  const DIALOG = MODAL.querySelector("dialog");
@@ -913,9 +1061,14 @@ function PGS_modal(selector = "modal") {
913
1061
  //+ FN OPEN
914
1062
  function openModal(e) {
915
1063
  e?.stopImmediatePropagation();
1064
+ if (DIALOG.open) {
1065
+ closeModal(e);
1066
+ return;
1067
+ }
1068
+
916
1069
  if (!DIALOG.open) document.querySelectorAll("dialog[open]").forEach((dlg) => dlg.close());
917
1070
  statusModal(true);
918
- DIALOG.open ? closeModal(e) : topLevel ? DIALOG.showModal() : DIALOG.show();
1071
+ topLevel ? DIALOG.showModal() : DIALOG.show();
919
1072
  // modalCustomEvents('modal:open', { event: e });
920
1073
  MODAL.dispatchEvent(new CustomEvent('modal:open'));
921
1074
  DIALOG.dispatchEvent(new CustomEvent('modal:open'));
@@ -931,6 +1084,14 @@ function PGS_modal(selector = "modal") {
931
1084
  DIALOG.dispatchEvent(new CustomEvent('modal:close'));
932
1085
  }
933
1086
 
1087
+ function forceOpen(e) {
1088
+ if (!DIALOG.open) openModal(e);
1089
+ }
1090
+
1091
+ function forceClose(e) {
1092
+ if (DIALOG.open) closeModal(e);
1093
+ }
1094
+
934
1095
  //+ fn OPEN ON HISTORY
935
1096
  function openModalOnHistory() {
936
1097
  const params = new URLSearchParams(window.location.search);
@@ -976,10 +1137,216 @@ function PGS_modal(selector = "modal") {
976
1137
  } catch (_) { }
977
1138
  });
978
1139
  }
1140
+
1141
+ API.set(MODAL, {
1142
+ element: MODAL,
1143
+ button: BUTTON_OPEN,
1144
+ dialog: DIALOG,
1145
+ closeButton: BUTTON_CLOSE,
1146
+ open: forceOpen,
1147
+ close: forceClose,
1148
+ toggle: openModal,
1149
+ refresh: () => {
1150
+ PGS_modal_init(selector);
1151
+ return API.get(MODAL);
1152
+ },
1153
+ isOpen: () => DIALOG.open,
1154
+ });
979
1155
  });
980
1156
  }
981
1157
 
982
1158
  //# INIT PGS_modal
1159
+ PGS_modal_init()
1160
+
1161
+ //# API
1162
+ function PGS_modal_api(selector) {
1163
+ return API.get(selector);
1164
+ }
1165
+
1166
+ const PGS_modal = {
1167
+ PGS_name: "PGS_modal",
1168
+ init: PGS_modal_init,
1169
+ api: PGS_modal_api
1170
+ };
1171
+
1172
+
1173
+ /***/ },
1174
+
1175
+ /***/ "./assets/javascript/components/_notifications.js"
1176
+ /*!********************************************************!*\
1177
+ !*** ./assets/javascript/components/_notifications.js ***!
1178
+ \********************************************************/
1179
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
1180
+
1181
+ "use strict";
1182
+ __webpack_require__.r(__webpack_exports__);
1183
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1184
+ /* harmony export */ PGS_notification: () => (/* binding */ PGS_notification),
1185
+ /* harmony export */ PGS_notificationTrigger_init: () => (/* binding */ PGS_notificationTrigger_init)
1186
+ /* harmony export */ });
1187
+ //= PGS_notification
1188
+ const fn_notification = {
1189
+ _escapeHtml(value) {
1190
+ return String(value ?? "");
1191
+ },
1192
+
1193
+ _getDuration(notification) {
1194
+ const rawDuration = notification.duration;
1195
+ const duration = Number.parseInt(rawDuration, 10);
1196
+
1197
+ return Number.isNaN(duration) ? 5000 : duration;
1198
+ },
1199
+
1200
+ _getApi(notification) {
1201
+ const element = String(notification.element || "notification").trim();
1202
+
1203
+ return element === "toast" ? PGS_notification.toast : PGS_notification.alert;
1204
+ },
1205
+
1206
+ _getType(notification, api) {
1207
+ const type = String(notification.type || "info").trim();
1208
+
1209
+ return typeof api[type] === "function" ? type : "info";
1210
+ },
1211
+
1212
+ _getData(root) {
1213
+ try {
1214
+ return JSON.parse(root.dataset.notification || "{}");
1215
+ } catch (error) {
1216
+ console.warn("PGS notification: dati non validi", error);
1217
+ return {};
1218
+ }
1219
+ },
1220
+
1221
+ _getContent(title, content) {
1222
+ const safeContent = this._escapeHtml(content);
1223
+ const safeTitle = this._escapeHtml(title);
1224
+
1225
+ if (!safeTitle) return safeContent;
1226
+ if (!safeContent) return `<span pgs="notification-element-title">${safeTitle}</span>`;
1227
+
1228
+ return `
1229
+ <span pgs="notification-element-title">${safeTitle}</span>
1230
+ <br>
1231
+ <span pgs="notification-element-content">${safeContent}</span>
1232
+ `;
1233
+ },
1234
+
1235
+ initNotification(type, containerToken, icon, text, timeout, methodDelete = "replace", link = null) {
1236
+ let containerNotification = pgs(document).querySelector(containerToken);
1237
+
1238
+ //== Create Container
1239
+ if (!containerNotification) {
1240
+ const newContainer = document.createElement("div");
1241
+ pgs(newContainer).add(containerToken);
1242
+ newContainer.setAttribute("aria-live", "polite");
1243
+ newContainer.setAttribute("aria-relevant", "additions");
1244
+ document.body.appendChild(newContainer);
1245
+ containerNotification = newContainer;
1246
+ }
1247
+
1248
+ //== Create Notification
1249
+ const notification = document.createElement(link ? "a" : "div");
1250
+ if (methodDelete == "replace") containerNotification.innerHTML = "";
1251
+ if (link) notification.href = link;
1252
+ if (timeout > 0) notification.style.setProperty("--notification-timeout", timeout + "ms");
1253
+ pgs(notification).state.add(type);
1254
+ pgs(notification).add("notification-element");
1255
+ notification.setAttribute("role", type == "error" ? "alert" : "status")
1256
+ notification.innerHTML = `${icon} <p>${text}</p>`;
1257
+ containerNotification.appendChild(notification);
1258
+
1259
+
1260
+ //+ Animation delete
1261
+ function deleteNotification() {
1262
+ methodDelete == "stack" ? notification.style.translate = "120%" : notification.style.opacity = "0";
1263
+ setTimeout(() => notification.remove(), 300);
1264
+ }
1265
+
1266
+ //== Timeout delete
1267
+ if (timeout > 0) setTimeout(() => { deleteNotification() }, timeout);
1268
+
1269
+ //== button delete
1270
+ const btnDelete = document.createElement("button");
1271
+ btnDelete.type = "button";
1272
+ btnDelete.ariaLabel = "Rimuovi notifica";
1273
+ btnDelete.innerHTML = '<i class="fa-solid fa-xmark"></i>';
1274
+ btnDelete.setAttribute("pgs", "buttonClose");
1275
+ notification.insertAdjacentElement("afterbegin", btnDelete);
1276
+
1277
+ //== event
1278
+
1279
+ btnDelete.addEventListener("click", function (e) {
1280
+ e.preventDefault();
1281
+ e.stopPropagation();
1282
+ e.stopImmediatePropagation()
1283
+ deleteNotification(e); // Esegue la tua funzione
1284
+ });
1285
+ },
1286
+
1287
+ deleteAll(containerToken) {
1288
+ let containerNotification = pgs(document).querySelector(containerToken);
1289
+ if (containerNotification) containerNotification.innerHTML = "";
1290
+ },
1291
+
1292
+ trigger(root = document) {
1293
+ pgs(root).querySelectorAll("notificationTrigger").forEach(element => {
1294
+ if (!element || element.dataset.initialize === "true") return;
1295
+
1296
+ element.dataset.initialize = "true";
1297
+
1298
+ const notification = this._getData(element);
1299
+ const title = String(notification.title || "").trim();
1300
+ const content = String(notification.message || "").trim();
1301
+
1302
+ if (!title && !content) {
1303
+ element.remove();
1304
+ return;
1305
+ }
1306
+
1307
+ const link = notification.link || null;
1308
+ const icon = notification.icon || undefined;
1309
+ const duration = this._getDuration(notification);
1310
+ const api = this._getApi(notification);
1311
+ const type = this._getType(notification, api);
1312
+ const formattedContent = this._getContent(title, content);
1313
+
1314
+ if (api === PGS_notification.toast) api[type](formattedContent, duration, icon);
1315
+ else api[type](formattedContent, link, duration, icon);
1316
+
1317
+ element.remove();
1318
+ });
1319
+ }
1320
+ };
1321
+
1322
+ //# EXPORT
1323
+ function PGS_notificationTrigger_init(root = document) {
1324
+ return fn_notification.trigger(root);
1325
+ }
1326
+
1327
+ const PGS_notification = {
1328
+ PGS_name: "PGS_notification",
1329
+ trigger: PGS_notificationTrigger_init,
1330
+ alert: {
1331
+ 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),
1332
+ 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),
1333
+ 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),
1334
+ 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),
1335
+ deleteAll: () => fn_notification.deleteAll("notification")
1336
+ },
1337
+ toast: {
1338
+ error: (text = "Errore", timeout = 4000, icon = '<i class="fa-solid fa-octagon-xmark"></i>',) => fn_notification.initNotification("error", "toast", icon, text, timeout),
1339
+ success: (text = "Aggiornato", timeout = 4000, icon = '<i class="fa-solid fa-check"></i>',) => fn_notification.initNotification("success", "toast", icon, text, timeout),
1340
+ info: (text = "Aggiornamento", timeout = 0, icon = '<i class="fa-solid fa-circle-info"></i>',) => fn_notification.initNotification("info", "toast", icon, text, timeout),
1341
+ warning: (text = "Attenzione", timeout = 4000, icon = '<i class="fa-solid fa-triangle-exclamation"></i>',) => fn_notification.initNotification("warning", "toast", icon, text, timeout),
1342
+ deleteAll: () => fn_notification.deleteAll("toast")
1343
+ }
1344
+ };
1345
+
1346
+
1347
+ //= EXECUTE
1348
+ if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", () => PGS_notificationTrigger_init());
1349
+ else PGS_notificationTrigger_init();
983
1350
 
984
1351
 
985
1352
  /***/ },
@@ -993,6 +1360,7 @@ function PGS_modal(selector = "modal") {
993
1360
  "use strict";
994
1361
  __webpack_require__.r(__webpack_exports__);
995
1362
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1363
+ /* harmony export */ PGS_slides: () => (/* binding */ PGS_slides),
996
1364
  /* harmony export */ PGS_slides_api: () => (/* binding */ PGS_slides_api),
997
1365
  /* harmony export */ PGS_slides_init: () => (/* binding */ PGS_slides_init)
998
1366
  /* harmony export */ });
@@ -1161,10 +1529,13 @@ class PGS_Slides {
1161
1529
  const last = children[children.length - 1];
1162
1530
  return last?.classList.contains("view") || false;
1163
1531
  },
1532
+ refresh: () => {
1533
+ PGS_slides_init(this.selector.parentNode || document);
1534
+ return API.get(this.selector);
1535
+ },
1164
1536
  });
1165
1537
  }
1166
1538
  }
1167
- PGS_slides_init();
1168
1539
 
1169
1540
  //# INIT
1170
1541
  function PGS_slides_init(root = document) {
@@ -1176,11 +1547,19 @@ function PGS_slides_init(root = document) {
1176
1547
  });
1177
1548
  }
1178
1549
 
1550
+ PGS_slides_init();
1551
+
1179
1552
  //# API
1180
1553
  function PGS_slides_api(selector) {
1181
1554
  return API.get(selector);
1182
1555
  }
1183
1556
 
1557
+ const PGS_slides = {
1558
+ PGS_name: "PGS_slides",
1559
+ init: PGS_slides_init,
1560
+ api: PGS_slides_api
1561
+ };
1562
+
1184
1563
 
1185
1564
  /***/ },
1186
1565
 
@@ -1194,13 +1573,13 @@ function PGS_slides_api(selector) {
1194
1573
  __webpack_require__.r(__webpack_exports__);
1195
1574
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1196
1575
  /* harmony export */ PGS_stepTabs: () => (/* binding */ PGS_stepTabs),
1197
- /* harmony export */ PGS_tabs_api: () => (/* binding */ PGS_tabs_api)
1576
+ /* harmony export */ PGS_stepTabs_api: () => (/* binding */ PGS_stepTabs_api),
1577
+ /* harmony export */ PGS_stepTabs_init: () => (/* binding */ PGS_stepTabs_init)
1198
1578
  /* harmony export */ });
1199
1579
  const API = new WeakMap();
1200
- PGS_stepTabs()
1201
1580
 
1202
- function PGS_stepTabs() {
1203
- pgs(document).querySelectorAll("stepTabs").forEach(tabsWizard => {
1581
+ function PGS_stepTabs_init(root = document) {
1582
+ pgs(root).querySelectorAll("stepTabs").forEach(tabsWizard => {
1204
1583
  if (tabsWizard.dataset.stepTabsInitialized === "true") return;
1205
1584
  tabsWizard.dataset.stepTabsInitialized = "true";
1206
1585
 
@@ -1315,21 +1694,35 @@ function PGS_stepTabs() {
1315
1694
  //-(API)
1316
1695
  // tabsWizard.addEventListener("stepTabs:reset", () => restartTab());
1317
1696
  API.set(tabsWizard, {
1697
+ element: tabsWizard,
1698
+ container: tabsContainer,
1318
1699
  restart: restartTab,
1319
1700
  goTo,
1320
1701
  next: () => goTo(current + 1),
1321
1702
  prev: () => goTo(current - 1),
1322
1703
  toggleLock: (step, lock = true) => typeof step === "number" && allTab[step] && (pgs(allTab[step]).state.toggle("is-locked", lock), goTo(current)),
1704
+ refresh: () => {
1705
+ PGS_stepTabs_init(tabsWizard.parentNode || document);
1706
+ return API.get(tabsWizard);
1707
+ },
1323
1708
  getCurrent: () => current,
1324
1709
  getState: () => ({ current, total }),
1325
1710
  });
1326
1711
  });
1327
1712
  }
1328
1713
 
1329
- function PGS_tabs_api(selector) {
1714
+ PGS_stepTabs_init()
1715
+
1716
+ function PGS_stepTabs_api(selector) {
1330
1717
  return API.get(selector);
1331
1718
  }
1332
1719
 
1720
+ const PGS_stepTabs = {
1721
+ PGS_name: "PGS_stepTabs",
1722
+ init: PGS_stepTabs_init,
1723
+ api: PGS_stepTabs_api
1724
+ };
1725
+
1333
1726
  /*
1334
1727
  / EXAMPLE
1335
1728
  // vai allo step 2
@@ -1366,11 +1759,15 @@ function PGS_tabs_api(selector) {
1366
1759
  "use strict";
1367
1760
  __webpack_require__.r(__webpack_exports__);
1368
1761
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1369
- /* harmony export */ PGS_ol: () => (/* binding */ PGS_ol)
1762
+ /* harmony export */ PGS_steps: () => (/* binding */ PGS_steps),
1763
+ /* harmony export */ PGS_steps_api: () => (/* binding */ PGS_steps_api),
1764
+ /* harmony export */ PGS_steps_init: () => (/* binding */ PGS_steps_init)
1370
1765
  /* harmony export */ });
1766
+ const API = new WeakMap();
1371
1767
 
1372
- function PGS_ol() {
1373
- pgs(document).querySelectorAll("steps").forEach(steps => {
1768
+ function PGS_steps_init(root = document) {
1769
+ pgs(root).querySelectorAll("steps").forEach(steps => {
1770
+ if (API.has(steps)) return;
1374
1771
 
1375
1772
  pgs(steps).querySelectorAll("steps-step").forEach((li, index) => {
1376
1773
 
@@ -1386,105 +1783,274 @@ function PGS_ol() {
1386
1783
  }
1387
1784
 
1388
1785
  //= line
1389
- const line = document.createElement("span");
1390
- pgs(line).add("steps-step-line")
1391
- li.insertAdjacentElement("afterbegin", line);
1786
+ if (!pgs(li).querySelector("steps-step-line")) {
1787
+ const line = document.createElement("span");
1788
+ pgs(line).add("steps-step-line")
1789
+ li.insertAdjacentElement("afterbegin", line);
1790
+ }
1791
+ });
1792
+
1793
+ API.set(steps, {
1794
+ element: steps,
1795
+ steps: () => Array.from(pgs(steps).querySelectorAll("steps-step")),
1796
+ getStep: (index) => pgs(steps).querySelectorAll("steps-step")[index],
1797
+ getTotal: () => pgs(steps).querySelectorAll("steps-step").length,
1798
+ refresh: () => {
1799
+ API.delete(steps);
1800
+ PGS_steps_init(steps.parentNode || document);
1801
+ return API.get(steps);
1802
+ },
1392
1803
  });
1393
1804
  });
1394
1805
  }
1395
1806
 
1396
1807
  //# INIT PGS_ol
1397
- PGS_ol()
1808
+ PGS_steps_init()
1809
+
1810
+ //# API
1811
+ function PGS_steps_api(selector) {
1812
+ return API.get(selector);
1813
+ }
1814
+
1815
+ const PGS_steps = {
1816
+ PGS_name: "PGS_steps",
1817
+ init: PGS_steps_init,
1818
+ api: PGS_steps_api
1819
+ };
1820
+
1398
1821
 
1399
1822
  /***/ },
1400
1823
 
1401
- /***/ "./assets/javascript/functions/_notifications.js"
1402
- /*!*******************************************************!*\
1403
- !*** ./assets/javascript/functions/_notifications.js ***!
1404
- \*******************************************************/
1824
+ /***/ "./assets/javascript/functions/_formValidate.js"
1825
+ /*!******************************************************!*\
1826
+ !*** ./assets/javascript/functions/_formValidate.js ***!
1827
+ \******************************************************/
1405
1828
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
1406
1829
 
1407
1830
  "use strict";
1408
1831
  __webpack_require__.r(__webpack_exports__);
1409
1832
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1410
- /* harmony export */ PGS_notification: () => (/* binding */ PGS_notification),
1411
- /* harmony export */ PGS_toast: () => (/* binding */ PGS_toast)
1833
+ /* harmony export */ PGS_formValidate: () => (/* binding */ PGS_formValidate)
1412
1834
  /* harmony export */ });
1413
- //# PGS_notification
1414
- function initNotification(type, containerToken, icon, text, timeout, methodDelete = "replace", link = null) {
1415
- let containerNotification = pgs(document).querySelector(containerToken);
1416
-
1417
- //== Create Container
1418
- if (!containerNotification) {
1419
- const newContainer = document.createElement("div");
1420
- pgs(newContainer).add(containerToken);
1421
- newContainer.setAttribute("aria-live", "polite");
1422
- newContainer.setAttribute("aria-relevant", "additions");
1423
- document.body.appendChild(newContainer);
1424
- containerNotification = newContainer;
1835
+ /* harmony import */ var _components_notifications_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../components/_notifications.js */ "./assets/javascript/components/_notifications.js");
1836
+
1837
+
1838
+
1839
+ class PGS_formValidate {
1840
+ constructor({ form } = {}) {
1841
+ this.container = form;
1842
+ this._rules = [];
1843
+ // pgs(this.container).add("formError");
1425
1844
  }
1426
1845
 
1427
- //== Create Notification
1428
- const notification = document.createElement(link ? "a" : "div");
1429
- if (methodDelete == "replace") containerNotification.innerHTML = "";
1430
- if (link) notification.href = link;
1431
- if (timeout > 0) notification.style.setProperty("--notification-timeout", timeout + "ms");
1432
- pgs(notification).state.add(type);
1433
- pgs(notification).add("notification-element");
1434
- notification.setAttribute("role", type == "error" ? "alert" : "status")
1435
- notification.innerHTML = `${icon} <p>${text}</p>`;
1436
- containerNotification.appendChild(notification);
1437
-
1438
-
1439
- //+ Animation delete
1440
- function deleteNotification() {
1441
- methodDelete == "stack" ? notification.style.translate = "120%" : notification.style.opacity = "0";
1442
- setTimeout(() => notification.remove(), 300);
1846
+ //+ ADD
1847
+ addError(field, i) {
1848
+ field.setAttribute("data-form-field-status", "error");
1849
+ if (i == 0) field.scrollIntoView();
1850
+
1851
+ let message = field.getAttribute("data-form-field-message");
1852
+
1853
+ if (i == 0 && message) _components_notifications_js__WEBPACK_IMPORTED_MODULE_0__.PGS_notification.toast.error(message);
1854
+ else if (i == 0) _components_notifications_js__WEBPACK_IMPORTED_MODULE_0__.PGS_notification.toast.error("Compila tutti i campi!");
1443
1855
  }
1444
1856
 
1445
- //== Timeout delete
1446
- if (timeout > 0) setTimeout(() => { deleteNotification() }, timeout);
1857
+ //+ REMOVE
1858
+ removeError(field) {
1859
+ field.setAttribute("data-form-field-status", "");
1860
+ }
1447
1861
 
1448
- //== button delete
1449
- const btnDelete = document.createElement("button");
1450
- btnDelete.type = "button";
1451
- btnDelete.ariaLabel = "Rimuovi notifica";
1452
- btnDelete.innerHTML = '<i class="fa-solid fa-xmark"></i>';
1453
- btnDelete.setAttribute("pgs", "buttonClose");
1454
- notification.insertAdjacentElement("afterbegin", btnDelete);
1862
+ #removeErrorOnClick(allFields) {
1863
+ allFields.forEach(element => {
1864
+ element.addEventListener("click", e => this.removeError(element))
1865
+ });
1866
+ }
1455
1867
 
1456
- //== event
1457
- btnDelete.addEventListener("click", function (e) {
1458
- e.preventDefault();
1459
- e.stopPropagation();
1460
- e.stopImmediatePropagation()
1461
- deleteNotification(e); // Esegue la tua funzione
1462
- });
1463
- }
1868
+ // + --------------------------
1869
+ // + Helpers
1870
+ // + --------------------------
1871
+ help = {
1872
+ // supporta sia required nativo, sia data-required="true"
1873
+ isRequired(field) {
1874
+ if (!field) return false;
1875
+
1876
+ const required = field.required === true || field?.dataset?.required === "true" || field?.getAttribute('aria-required') == "true";
1877
+ return required && !field.hidden; // solo attributo/proprietà "hidden"
1878
+ },
1879
+ // input (non speciali), textarea
1880
+ isEmptyTextLike(field) { return !String(field?.value ?? "").trim(); },
1881
+ // select: vuoto se value == "" o null
1882
+ isEmptySelect(field) { return !String(field?.value ?? "").trim(); },
1883
+ // recupera name in modo sicuro
1884
+ getGroupName(field) { return field?.name || field?.getAttribute?.("name") || ""; }
1885
+ };
1464
1886
 
1465
- function deleteALl(containerToken) {
1466
- let containerNotification = pgs(document).querySelector(containerToken);
1467
- if (containerNotification) containerNotification.innerHTML = "";
1468
- }
1469
1887
 
1888
+ // + --------------------------
1889
+ // + input + altri elementi.
1890
+ // + --------------------------
1891
+ #inputValue(container) {
1470
1892
 
1893
+ //++ add rule
1894
+ const ruleInvalidFields = [];
1895
+ for (const rule of this._rules) {
1896
+ const res = rule(container);
1471
1897
 
1472
- let PGS_notification = {
1473
- error: (text = "Errore", link = null, timeout = 0, icon = '<i class="fa-solid fa-octagon-xmark"></i>') => initNotification("error", "notification", icon, text, timeout, "stack", link),
1474
- success: (text = "Aggiornato", link = null, timeout = 0, icon = '<i class="fa-solid fa-check"></i>') => initNotification("success", "notification", icon, text, timeout, "stack", link),
1475
- info: (text = "Aggiornamento", link = null, timeout = 0, icon = '<i class="fa-solid fa-circle-info"></i>',) => initNotification("info", "notification", icon, text, timeout, "stack", link),
1476
- warning: (text = "Attenzione", link = null, timeout = 0, icon = '<i class="fa-solid fa-triangle-exclamation"></i>') => initNotification("warning", "notification", icon, text, timeout, "stack", link),
1477
- deleteAllNotification: () => deleteALl("notification")
1478
- }
1898
+ // la rule può tornare:
1899
+ // null/undefined => ok
1900
+ // un elemento => invalido
1901
+ // un array di elementi => invalidi
1902
+ if (!res) continue;
1903
+
1904
+ if (Array.isArray(res)) ruleInvalidFields.push(...res);
1905
+ else ruleInvalidFields.push(res);
1906
+ }
1907
+
1908
+ //== INPUT
1909
+ // "testuali" (esclude hidden/disabled/checkbox/radio/file come nel tuo snippet)
1910
+ const textInputs = Array.from(container.querySelectorAll("input")).filter((input) => {
1911
+ if (input.disabled) return false;
1912
+ if (input.type === "hidden") return false;
1913
+ if (input.type === "checkbox" || input.type === "radio" || input.type === "file") return false;
1914
+
1915
+ // valida solo se required (o data-required="true")
1916
+ if (!this.help.isRequired(input)) return false;
1917
+
1918
+ return this.help.isEmptyTextLike(input);
1919
+ });
1920
+
1921
+ //== TEXTAREA
1922
+ // required vuote
1923
+ const textareas = Array.from(container.querySelectorAll("textarea")).filter((ta) => {
1924
+ if (ta.disabled) return false;
1925
+ if (!this.help.isRequired(ta)) return false;
1926
+ return this.help.isEmptyTextLike(ta);
1927
+ });
1928
+
1929
+ //== SELECT
1930
+ // required vuoti
1931
+ const selects = Array.from(container.querySelectorAll("select")).filter((sel) => {
1932
+ if (sel.disabled) return false;
1933
+ if (!this.help.isRequired(sel)) return false;
1934
+ return this.help.isEmptySelect(sel);
1935
+ });
1936
+
1937
+ //== RADIO
1938
+ // required: se in un gruppo required non ce n'è uno checked => errore sul "primo" radio del gruppo
1939
+ const radios = Array.from(container.querySelectorAll('input[type="radio"]')).filter((r) => !r.disabled);
1940
+ const requiredRadioGroups = new Map(); // name -> [elements]
1941
+ for (const r of radios) {
1942
+ if (!this.help.isRequired(r)) continue;
1943
+ const name = this.help.getGroupName(r);
1944
+ if (!name) continue;
1945
+ if (!requiredRadioGroups.has(name)) requiredRadioGroups.set(name, []);
1946
+ requiredRadioGroups.get(name).push(r);
1947
+ }
1948
+ const radioGroupErrors = [];
1949
+ for (const [name, group] of requiredRadioGroups.entries()) {
1950
+ const anyChecked = group.some((r) => r.checked);
1951
+ if (!anyChecked) {
1952
+ // scegli dove mettere l'errore: tipicamente sul primo radio del gruppo
1953
+ radioGroupErrors.push(group[0]);
1954
+ }
1955
+ }
1956
+
1957
+ //== CHECKBOX
1958
+ // required: può essere singola checkbox required (checked obbligatorio)
1959
+ // oppure gruppo di checkbox (stesso name) con almeno una selezionata
1960
+ const checkboxes = Array.from(container.querySelectorAll('input[type="checkbox"]')).filter((c) => !c.disabled);
1961
+ const requiredCheckboxSingles = [];
1962
+ const requiredCheckboxGroups = new Map(); // name -> [elements]
1963
+ for (const c of checkboxes) {
1964
+ if (!this.help.isRequired(c)) continue;
1965
+
1966
+ const name = this.help.getGroupName(c);
1967
+ if (!name) {
1968
+ // checkbox senza name: trattala come singola required
1969
+ if (!c.checked) requiredCheckboxSingles.push(c);
1970
+ continue;
1971
+ }
1972
+
1973
+ // se vuoi trattare come gruppo, raggruppa per name
1974
+ if (!requiredCheckboxGroups.has(name)) requiredCheckboxGroups.set(name, []);
1975
+ requiredCheckboxGroups.get(name).push(c);
1976
+ }
1977
+ const checkboxGroupErrors = [];
1978
+ for (const [name, group] of requiredCheckboxGroups.entries()) {
1979
+ // se è un gruppo (>=2) richiedi almeno una spuntata
1980
+ // se è 1 sola, si comporta come singola
1981
+ const anyChecked = group.some((c) => c.checked);
1982
+ if (!anyChecked) checkboxGroupErrors.push(group[0]);
1983
+ }
1984
+
1985
+ //== FILE
1986
+ // required: se vuoi includerlo
1987
+ const fileInputs = Array.from(container.querySelectorAll('input[type="file"]')).filter((f) => {
1988
+ if (f.disabled) return false;
1989
+ if (!this.help.isRequired(f)) return false;
1990
+ return !(f.files && f.files.length > 0);
1991
+ });
1479
1992
 
1480
- let PGS_toast = {
1481
- error: (text = "Errore", timeout = 4000, icon = '<i class="fa-solid fa-octagon-xmark"></i>',) => initNotification("error", "toast", icon, text, timeout),
1482
- success: (text = "Aggiornato", timeout = 4000, icon = '<i class="fa-solid fa-check"></i>',) => initNotification("success", "toast", icon, text, timeout),
1483
- info: (text = "Aggiornamento", timeout = 0, icon = '<i class="fa-solid fa-circle-info"></i>',) => initNotification("info", "toast", icon, text, timeout),
1484
- warning: (text = "Attenzione", timeout = 4000, icon = '<i class="fa-solid fa-triangle-exclamation"></i>',) => initNotification("warning", "toast", icon, text, timeout),
1485
- deleteTost: () => deleteALl("toast")
1993
+ //== risultato finale: tutti i campi da marcare come errore
1994
+ const invalidFields = [
1995
+ textInputs,
1996
+ textareas,
1997
+ selects,
1998
+ radioGroupErrors,
1999
+ requiredCheckboxSingles,
2000
+ checkboxGroupErrors,
2001
+ fileInputs,
2002
+ ruleInvalidFields
2003
+ ];
2004
+
2005
+ return invalidFields.flat();
2006
+ }
2007
+
2008
+ // + -------------------------
2009
+ // + VALIDATE
2010
+ // + -------------------------
2011
+ validate() {
2012
+ const invalid = this.#inputValue(this.container);
2013
+ const allFields = this.container.querySelectorAll("input, textarea, select")
2014
+
2015
+ //== pulizia/aggiornamento errori:
2016
+ // prima rimuovo errori dai campi "non più invalidi"
2017
+ Array.from(allFields).filter((el) => !el.disabled);
2018
+
2019
+ //== per radio/checkbox in gruppo:
2020
+ // rimuovi l'errore solo sull'elemento che lo ospita (qui: se presente)
2021
+ for (const el of allFields) { if (!invalid.includes(el)) this.removeError(el); }
2022
+
2023
+ //== aggiungo errori dove serve
2024
+ invalid.forEach((el, i) => this.addError(el, i))
2025
+
2026
+ //== rimuove l'errore al click
2027
+ this.#removeErrorOnClick(allFields)
2028
+
2029
+ //== status form
2030
+ if (invalid.length) {
2031
+ this.container.setAttribute("data-form-status", "error");
2032
+ return false;
2033
+ } else {
2034
+ this.container.setAttribute("data-form-status", "success");
2035
+ return true;
2036
+ }
2037
+ }
2038
+
2039
+ ifSuccess(text = "Inviato con successo") {
2040
+ if (this.validate() == true) _components_notifications_js__WEBPACK_IMPORTED_MODULE_0__.PGS_notification.toast.success(text)
2041
+ }
2042
+
2043
+ // + -------------------------
2044
+ // + ADD RULE
2045
+ // + -------------------------
2046
+ addNewRule(container) {
2047
+ if (typeof container !== "function") throw new Error("Rule must be a function");
2048
+ this._rules.push(container);
2049
+ return this;
2050
+ }
1486
2051
  }
1487
2052
 
2053
+
1488
2054
  /***/ },
1489
2055
 
1490
2056
  /***/ "./assets/javascript/functions/_scrollY.js"
@@ -1802,13 +2368,8 @@ document.addEventListener('DOMContentLoaded', function () {
1802
2368
  /*!***********************************************!*\
1803
2369
  !*** ./assets/javascript/patterns/_header.js ***!
1804
2370
  \***********************************************/
1805
- (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
2371
+ () {
1806
2372
 
1807
- "use strict";
1808
- __webpack_require__.r(__webpack_exports__);
1809
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1810
- /* harmony export */ PGS_header: () => (/* binding */ PGS_header)
1811
- /* harmony export */ });
1812
2373
  //# HEADER
1813
2374
  const header = pgs(document).querySelector("header");
1814
2375
  const headerElements = pgs(header).querySelectorAll("header-element");
@@ -2028,26 +2589,31 @@ var __webpack_exports__ = {};
2028
2589
  !*** ./assets/javascript/index.js ***!
2029
2590
  \************************************/
2030
2591
  __webpack_require__.r(__webpack_exports__);
2592
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2593
+ /* harmony export */ pgs: () => (/* reexport safe */ _pgs_js__WEBPACK_IMPORTED_MODULE_0__.pgs)
2594
+ /* harmony export */ });
2031
2595
  /* harmony import */ var _pgs_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_pgs.js */ "./assets/javascript/_pgs.js");
2032
2596
  /* harmony import */ var _base_darkmode_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./base/_darkmode.js */ "./assets/javascript/base/_darkmode.js");
2033
2597
  /* harmony import */ var _base_darkmode_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_base_darkmode_js__WEBPACK_IMPORTED_MODULE_1__);
2034
2598
  /* harmony import */ var _base_object_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./base/_object.js */ "./assets/javascript/base/_object.js");
2035
2599
  /* harmony import */ var _base_object_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_base_object_js__WEBPACK_IMPORTED_MODULE_2__);
2036
2600
  /* harmony import */ var _components_accordion_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/_accordion.js */ "./assets/javascript/components/_accordion.js");
2037
- /* harmony import */ var _components_accordion_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_components_accordion_js__WEBPACK_IMPORTED_MODULE_3__);
2038
2601
  /* harmony import */ var _components_dropdown_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/_dropdown.js */ "./assets/javascript/components/_dropdown.js");
2039
- /* harmony import */ var _components_exeNotifications_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/_exeNotifications.js */ "./assets/javascript/components/_exeNotifications.js");
2040
- /* harmony import */ var _components_menu_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/_menu.js */ "./assets/javascript/components/_menu.js");
2041
- /* harmony import */ var _components_modals_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/_modals.js */ "./assets/javascript/components/_modals.js");
2042
- /* harmony import */ var _components_slides_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./components/_slides.js */ "./assets/javascript/components/_slides.js");
2043
- /* harmony import */ var _components_steps_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./components/_steps.js */ "./assets/javascript/components/_steps.js");
2044
- /* harmony import */ var _components_stepTabs_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./components/_stepTabs.js */ "./assets/javascript/components/_stepTabs.js");
2045
- /* harmony import */ var _patterns_header_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./patterns/_header.js */ "./assets/javascript/patterns/_header.js");
2046
- /* harmony import */ var _patterns_cookieConsent_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./patterns/_cookieConsent.js */ "./assets/javascript/patterns/_cookieConsent.js");
2047
- /* harmony import */ var _patterns_cookieConsent_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_patterns_cookieConsent_js__WEBPACK_IMPORTED_MODULE_12__);
2602
+ /* harmony import */ var _components_menu_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/_menu.js */ "./assets/javascript/components/_menu.js");
2603
+ /* harmony import */ var _components_modals_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/_modals.js */ "./assets/javascript/components/_modals.js");
2604
+ /* harmony import */ var _components_slides_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/_slides.js */ "./assets/javascript/components/_slides.js");
2605
+ /* harmony import */ var _components_steps_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./components/_steps.js */ "./assets/javascript/components/_steps.js");
2606
+ /* harmony import */ var _components_stepTabs_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./components/_stepTabs.js */ "./assets/javascript/components/_stepTabs.js");
2607
+ /* harmony import */ var _components_notifications_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./components/_notifications.js */ "./assets/javascript/components/_notifications.js");
2608
+ /* harmony import */ var _imports_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./_imports.js */ "./assets/javascript/_imports.js");
2609
+ /* harmony import */ var _patterns_header_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./patterns/_header.js */ "./assets/javascript/patterns/_header.js");
2610
+ /* harmony import */ var _patterns_header_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_patterns_header_js__WEBPACK_IMPORTED_MODULE_12__);
2611
+ /* harmony import */ var _patterns_cookieConsent_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./patterns/_cookieConsent.js */ "./assets/javascript/patterns/_cookieConsent.js");
2612
+ /* harmony import */ var _patterns_cookieConsent_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(_patterns_cookieConsent_js__WEBPACK_IMPORTED_MODULE_13__);
2048
2613
  //= PGS
2049
2614
 
2050
2615
 
2616
+
2051
2617
  //= BASE
2052
2618
 
2053
2619
 
@@ -2062,8 +2628,10 @@ __webpack_require__.r(__webpack_exports__);
2062
2628
 
2063
2629
 
2064
2630
 
2065
- //= patterns
2631
+ //= IMPORT REGISTRY
2632
+
2066
2633
 
2634
+ //= PATTERNS
2067
2635
 
2068
2636
 
2069
2637
  })();