@cagovweb/state-template 6.3.0 → 6.3.1-beta2

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,4 +1,4 @@
1
- var StateTemplateNpmPackageVersion="6.3.0";
1
+ var StateTemplateNpmPackageVersion="6.3.1-beta2";
2
2
  /*!
3
3
  * Bootstrap v5.3.0 (https://getbootstrap.com/)
4
4
  * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
@@ -6864,6 +6864,8 @@ window.addEventListener("load", () => {
6864
6864
  * License MIT: https://github.com/nico3333fr/van11y-accessible-accordion-aria/blob/master/LICENSE
6865
6865
  */
6866
6866
  (() => {
6867
+ const isDesktopWidth = () => window.innerWidth > 991; //Maximum px for mobile width
6868
+
6867
6869
  /**
6868
6870
  * @param {Object} obj
6869
6871
  * @param {String} key
@@ -7200,8 +7202,8 @@ window.addEventListener("load", () => {
7200
7202
  // making sure all second level links are not tabable
7201
7203
  accordionPanel
7202
7204
  .querySelectorAll(".second-level-link")
7203
- .forEach(item => {
7204
- item.setAttribute("tabindex", "-1");
7205
+ .forEach((/** @type {HTMLElement} **/ item) => {
7206
+ item.tabIndex = -1;
7205
7207
  });
7206
7208
  }
7207
7209
  });
@@ -7282,7 +7284,10 @@ window.addEventListener("load", () => {
7282
7284
  // adding tabindex to links to make sure they are not tabable if sub nav panel is closed
7283
7285
  destination
7284
7286
  .querySelectorAll(".second-level-link")
7285
- .forEach(item => item.setAttribute("tabindex", "-1"));
7287
+ .forEach(
7288
+ (/** @type {HTMLElement} **/ item) =>
7289
+ (item.tabIndex = -1)
7290
+ );
7286
7291
  }
7287
7292
 
7288
7293
  if (!mobileView()) {
@@ -7301,7 +7306,10 @@ window.addEventListener("load", () => {
7301
7306
  //Added fix to make closed panels non-tabbable
7302
7307
  destinationPanel
7303
7308
  .querySelectorAll(".second-level-link")
7304
- .forEach(item => item.setAttribute("tabindex", "-1"));
7309
+ .forEach(
7310
+ (/** @type {HTMLElement} **/ item) =>
7311
+ (item.tabIndex = -1)
7312
+ );
7305
7313
  }
7306
7314
  });
7307
7315
  }
@@ -7323,31 +7331,28 @@ window.addEventListener("load", () => {
7323
7331
  return plugin;
7324
7332
  };
7325
7333
 
7334
+ // reset navigation function
7326
7335
  const NavReset = () => {
7327
7336
  //RESET
7328
7337
  document
7329
7338
  .querySelectorAll(".first-level-btn")
7330
- .forEach(el => el.setAttribute("aria-expanded", "false"));
7339
+ .forEach(el => (el.ariaExpanded = "false")); //Must be false and not blank for CSS
7340
+
7331
7341
  document.querySelectorAll(".sub-nav").forEach(el => {
7332
- el.setAttribute("aria-hidden", "true");
7342
+ el.ariaHidden = "true";
7333
7343
  el.classList.remove("open");
7334
7344
  });
7345
+
7335
7346
  document
7336
7347
  .querySelectorAll(".second-level-link")
7337
- .forEach(el => el.setAttribute("tabindex", "-1"));
7348
+ .forEach((/**@type {HTMLElement} */ el) => (el.tabIndex = -1));
7338
7349
 
7339
- if (window.innerWidth <= 991) {
7340
- document
7341
- .querySelectorAll(".rotate")
7342
- .forEach(
7343
- (/**@type {HTMLElement} */ el) => (el.style.display = "block")
7344
- );
7345
- } else {
7346
- document
7347
- .querySelectorAll(".rotate")
7348
- .forEach((/**@type {HTMLElement} */ el) => (el.style.display = "none"));
7349
- document.querySelector("#navigation")?.removeAttribute("aria-hidden");
7350
- }
7350
+ document
7351
+ .querySelectorAll(".rotate")
7352
+ .forEach(
7353
+ (/**@type {HTMLElement} */ el) =>
7354
+ (el.style.display = isDesktopWidth() ? "none" : "block")
7355
+ );
7351
7356
  };
7352
7357
 
7353
7358
  // Remove href if <a> has a link
@@ -7426,11 +7431,11 @@ window.addEventListener("load", () => {
7426
7431
 
7427
7432
  const carrot = document.createElement("span");
7428
7433
  carrot.classList.add("ca-gov-icon-caret-down", "carrot");
7429
- carrot.setAttribute("aria-hidden", "true");
7434
+ carrot.ariaHidden = "true";
7430
7435
 
7431
7436
  const toggleSubNav = document.createElement("div");
7432
7437
  toggleSubNav.classList.add("ca-gov-icon-caret-right", "rotate");
7433
- toggleSubNav.setAttribute("aria-hidden", "true");
7438
+ toggleSubNav.ariaHidden = "true";
7434
7439
  toggleSubNav.style.display = mobileView() ? "block" : "none";
7435
7440
 
7436
7441
  el.appendChild(toggleSubNav);
@@ -7441,22 +7446,6 @@ window.addEventListener("load", () => {
7441
7446
  addActive();
7442
7447
  });
7443
7448
 
7444
- // Do Navigation Reset function on window resize.
7445
- window.addEventListener("resize", () => {
7446
- document
7447
- .querySelector(".toggle-menu")
7448
- ?.setAttribute("aria-expanded", "false");
7449
-
7450
- //Collapse the nav when narrow
7451
- //const nav = document.querySelector("#navigation");
7452
- //if (nav) {
7453
- //nav.classList.remove("show"); //This was causing the desktop menu to stay hidden when resizing from mobile.
7454
- //nav.setAttribute("aria-hidden", "true");
7455
- //}
7456
-
7457
- NavReset();
7458
- });
7459
-
7460
7449
  // Reset on escape
7461
7450
  document.addEventListener("keyup", e => {
7462
7451
  // keyCode has been deprecated
@@ -8667,162 +8656,203 @@ cagov-pagination .cagov-pagination__item:has(.cagov-pagination__link-inactive) {
8667
8656
  //@ts-check
8668
8657
 
8669
8658
  window.addEventListener("load", () => {
8659
+ const isDesktopWidth = () => window.innerWidth > 991; //Maximum px for mobile width
8660
+
8661
+ /** @type {HTMLButtonElement} */
8662
+ const navToggleBtn = document.querySelector(".toggle-menu");
8663
+ if (!navToggleBtn) return;
8664
+
8665
+ // create container for drawer mobile nav items
8666
+ const mobileItemsCont = document.createElement("div");
8667
+ mobileItemsCont.className = "nav-drawer";
8668
+
8669
+ // Create close mobile meu button
8670
+ const navMobileMenuToggleBtn = document.createElement("button");
8671
+ navMobileMenuToggleBtn.classList.add("mobile-control", "toggle-menu");
8672
+ navMobileMenuToggleBtn.ariaExpanded = "false";
8673
+ navMobileMenuToggleBtn.setAttribute("aria-controls", "navigation");
8674
+ navMobileMenuToggleBtn.tabIndex = -1;
8675
+
8676
+ const navCloseBtnSpans = [0, 1, 2, 3, 4].map(() =>
8677
+ document.createElement("span")
8678
+ );
8679
+
8680
+ navCloseBtnSpans[4].classList.add("sr-only");
8681
+ navCloseBtnSpans[4].innerText = "Menu";
8682
+ navMobileMenuToggleBtn.append(...navCloseBtnSpans);
8683
+ mobileItemsCont.append(navMobileMenuToggleBtn);
8684
+
8685
+ /** @type {HTMLElement} */
8686
+ const mainNav = document.querySelector(".main-navigation");
8687
+
8670
8688
  // VARIABLES
8671
- const navButton = document.querySelector(".toggle-menu");
8672
- if (!navButton) return;
8689
+ /** @type {HTMLDivElement} */
8690
+ const navSearchCont = document.querySelector(".navigation-search");
8691
+ if (!navSearchCont) return;
8673
8692
 
8674
- const getAllNavLinks = () =>
8675
- document.querySelectorAll(
8676
- '.navigation-search a.first-level-link, .navigation-search button.first-level-btn, .navigation-search input, .navigation-search button, .navigation-search [tabindex]:not([tabindex="-1"])'
8677
- );
8693
+ const mobileCntls = document.querySelector(".global-header .mobile-controls");
8694
+ const mobileControlsDisplay = mobileCntls
8695
+ ? window.getComputedStyle(mobileCntls).display
8696
+ : "";
8678
8697
 
8679
- const getAllUtilityLinks = () =>
8680
- document.querySelectorAll(
8681
- '.settings-links a, .settings-links button, .settings-links input, .settings-links select, .settings-links [tabindex]:not([tabindex="-1"])'
8682
- );
8698
+ //Used for hiding/showing main elements
8699
+ const mainElements = document.querySelectorAll(
8700
+ ".main-content, footer, .site-footer, .utility-header, .branding, header"
8701
+ );
8702
+
8703
+ const regularHeader = document.querySelector("header");
8704
+
8705
+ /**
8706
+ * True if child is descendant of the parent
8707
+ * @param {HTMLElement} parent
8708
+ * @param {HTMLElement} child
8709
+ * @returns {boolean}
8710
+ */
8711
+ const checkParent = (parent, child) =>
8712
+ child?.parentElement
8713
+ ? child.parentElement === parent
8714
+ ? true
8715
+ : checkParent(parent, child.parentElement)
8716
+ : false;
8717
+
8718
+ // reset navigation function
8719
+ const NavReset = () => {
8720
+ //RESET
8721
+ document
8722
+ .querySelectorAll(".first-level-btn")
8723
+ .forEach(el => (el.ariaExpanded = "false")); //Must be false and not blank for CSS
8724
+
8725
+ document.querySelectorAll(".sub-nav").forEach(el => {
8726
+ el.ariaHidden = "true";
8727
+ el.classList.remove("open");
8728
+ });
8729
+
8730
+ document
8731
+ .querySelectorAll(".second-level-link")
8732
+ .forEach((/**@type {HTMLElement} */ el) => (el.tabIndex = -1));
8733
+
8734
+ document
8735
+ .querySelectorAll(".rotate")
8736
+ .forEach(
8737
+ (/**@type {HTMLElement} */ el) =>
8738
+ (el.style.display = isDesktopWidth() ? "none" : "block")
8739
+ );
8683
8740
 
8684
- // all focusable elements other than navigation
8685
- const getAllBodyLinks = () =>
8686
- document.querySelectorAll(
8687
- '.utility-header .social-media-links a, .utility-header .social-media-links input, .utility-header .social-media-links button, .utility-header .social-media-links [tabindex]:not([tabindex="-1"]), .branding a, .branding button, .branding input, .branding select, .main-content a[href], .main-content button, .main-content input, .main-content textarea, .main-content select, .main-content details, .main-content [tabindex]:not([tabindex="-1"]), .site-footer a[href], .site-footer button, .site-footer input, .site-footer textarea, .site-footer select, .site-footer details, .site-footer [tabindex]:not([tabindex="-1"]), footer a[href], footer button, footer input, footer textarea, footer select, footer details, footer [tabindex]:not([tabindex="-1"])'
8741
+ const targetAriaHidden = isDesktopWidth() ? null : "true";
8742
+
8743
+ if (navSearchCont.ariaHidden != targetAriaHidden)
8744
+ navSearchCont.ariaHidden = targetAriaHidden;
8745
+ };
8746
+
8747
+ const getAllNavLinks = () =>
8748
+ /** @type { NodeListOf<HTMLElement>} */ (
8749
+ navSearchCont.querySelectorAll(
8750
+ 'a.first-level-link, button.first-level-btn, input, button, [tabindex]:not([tabindex="-1"])'
8751
+ )
8688
8752
  );
8689
8753
 
8690
- // create container for drawer mobile nav items
8691
- const mobileItemsCont = document.createElement("div");
8692
- mobileItemsCont.setAttribute("class", "nav-drawer");
8754
+ // Escape key event listener
8755
+ document.addEventListener("keydown", e => {
8756
+ if (navSearchCont.classList.contains("visible")) {
8757
+ if (e.key === "Escape") {
8758
+ e.stopPropagation();
8759
+ closeMenu();
8760
+ }
8761
+ }
8762
+ });
8693
8763
 
8694
- // move mobile navigation toggle button back into mobile controls container
8695
- const moveNavToggleButtonToMobileControlsContainer = () => {
8696
- const navButtonCont = document.querySelector(
8697
- ".mobile-controls .main-nav-icons"
8764
+ const checkIfMobileView = () => {
8765
+ const mobileElement = document.querySelector(
8766
+ ".global-header .mobile-controls"
8698
8767
  );
8699
- setTimeout(() => {
8700
- navButton.setAttribute("aria-expanded", "false");
8701
- navButtonCont?.append(navButton);
8702
- }, 300);
8768
+ return mobileElement
8769
+ ? getComputedStyle(mobileElement)["display"] !== "none"
8770
+ : false;
8703
8771
  };
8704
8772
 
8705
- const setHidden = (/** @type {boolean} */ hide) => {
8706
- const mainCont = document.querySelector(".main-content");
8707
- const footerGlobal = document.querySelector("footer");
8708
- const footerSite = document.querySelector(".site-footer");
8709
- const headerutility = document.querySelector(".utility-header");
8710
- const siteBranding = document.querySelector(".branding");
8711
- const regularHeader = document.querySelector("header");
8712
-
8713
- if (hide) {
8714
- mainCont?.setAttribute("aria-hidden", "true");
8715
- footerGlobal?.setAttribute("aria-hidden", "true");
8716
- footerSite?.setAttribute("aria-hidden", "true");
8717
- headerutility?.setAttribute("aria-hidden", "true");
8718
- siteBranding?.setAttribute("aria-hidden", "true");
8719
- regularHeader?.classList.add("nav-overlay");
8720
- } else {
8721
- //show
8722
- mainCont?.removeAttribute("aria-hidden");
8723
- footerGlobal?.removeAttribute("aria-hidden");
8724
- footerSite?.removeAttribute("aria-hidden");
8725
- headerutility?.removeAttribute("aria-hidden");
8726
- siteBranding?.removeAttribute("aria-hidden");
8727
- regularHeader?.classList.remove("nav-overlay");
8773
+ // Close menu on focusout (tabbing out) event (if target is outside of mobile menu and ignore if focus target is navToggleBtn button)
8774
+ navSearchCont.addEventListener("focusout", e => {
8775
+ if (checkIfMobileView()) {
8776
+ if (
8777
+ !checkParent(
8778
+ /** @type {HTMLElement} **/ (e.currentTarget),
8779
+ /** @type {HTMLElement} **/ (e.relatedTarget)
8780
+ )
8781
+ ) {
8782
+ closeMenu();
8783
+ }
8728
8784
  }
8729
- };
8785
+ });
8730
8786
 
8731
- // Button click open and close menu function
8787
+ // Button click open menu function
8732
8788
  const openMenu = () => {
8733
- mobileItemsCont.append(navButton);
8734
- const navSearchCont = document.querySelector(".navigation-search");
8735
- if (!navSearchCont) return;
8736
- navSearchCont.classList.toggle("visible");
8737
- navSearchCont.classList.toggle("not-visible");
8738
- // Open
8739
- if (navSearchCont.classList.contains("visible")) {
8740
- navButton.setAttribute("aria-expanded", "true");
8741
- document.body.classList.add("overflow-hidden");
8742
- navSearchCont.setAttribute("aria-hidden", "false");
8743
- // make links focusable
8744
- getAllNavLinks().forEach(el => el.removeAttribute("tabindex"));
8745
- getAllUtilityLinks().forEach(el => el.removeAttribute("tabindex"));
8746
- // make all the rest of the links not focusable
8747
- getAllBodyLinks().forEach(el => el.setAttribute("tabindex", "-1"));
8748
- // Hide all the website areas (add aria-hidden)
8749
- setHidden(true);
8750
-
8751
- // Close
8752
- } else {
8753
- navButton.setAttribute("aria-expanded", "false");
8754
- document.body.classList.remove("overflow-hidden");
8755
- navSearchCont.setAttribute("aria-hidden", "true");
8756
- // removing focus
8757
- getAllNavLinks().forEach(el => el.setAttribute("tabindex", "-1"));
8758
- getAllUtilityLinks().forEach(el => el.setAttribute("tabindex", "-1"));
8759
- getAllBodyLinks().forEach(el => el.removeAttribute("tabindex"));
8760
- // remove aria hidden for the rest of the site
8761
- setHidden(false);
8762
- moveNavToggleButtonToMobileControlsContainer();
8763
- }
8789
+ navSearchCont.classList.add("visible");
8790
+ navSearchCont.classList.remove("not-visible");
8791
+ document.body.classList.add("overflow-hidden");
8792
+ navToggleBtn.ariaExpanded = "true";
8793
+ setOpen();
8794
+ // Hide all the website areas (add aria-hidden)
8795
+ mainElements.forEach(x => (x.ariaHidden = "true"));
8796
+
8797
+ regularHeader?.classList.add("nav-overlay");
8798
+ navMobileMenuToggleBtn.focus();
8764
8799
  };
8765
8800
 
8766
- // Default state for mobile
8767
- const mobileNavDefault = () => {
8768
- moveNavToggleButtonToMobileControlsContainer();
8769
- const mainNav = document.querySelector(".main-navigation");
8770
- const utilityLinks = document.querySelector(".settings-links");
8771
- if (mainNav && utilityLinks) mainNav.before(utilityLinks);
8772
- document.body.classList.remove("overflow-hidden");
8801
+ const setOpen = () => {
8802
+ navMobileMenuToggleBtn.ariaExpanded = "true";
8803
+ navSearchCont.ariaHidden = null;
8804
+ // make links focusable
8805
+ getAllNavLinks().forEach(el => el.removeAttribute("tabindex"));
8806
+ // desktop
8807
+ if (
8808
+ mobileControlsDisplay !== "block" &&
8809
+ navToggleBtn.ariaExpanded !== "false"
8810
+ ) {
8811
+ navToggleBtn.ariaExpanded = "false";
8812
+ }
8813
+ };
8773
8814
 
8774
- const navSearchCont = document.querySelector(".navigation-search");
8775
- if (!navSearchCont) return;
8776
- navSearchCont.classList.add("not-visible");
8815
+ // Button click close menu function
8816
+ const closeMenu = () => {
8777
8817
  navSearchCont.classList.remove("visible");
8778
- navSearchCont.setAttribute("aria-hidden", "true");
8779
- // removing focus
8780
- getAllNavLinks().forEach(el => el.setAttribute("tabindex", "-1"));
8781
- getAllUtilityLinks().forEach(el => el.setAttribute("tabindex", "-1"));
8782
- getAllBodyLinks().forEach(el => el.removeAttribute("tabindex"));
8783
- // remove aria hidden for the rest of the site
8784
- setHidden(false);
8818
+ navSearchCont.classList.add("not-visible");
8819
+
8820
+ setClosed();
8821
+
8822
+ navToggleBtn.focus();
8785
8823
  };
8786
8824
 
8787
- // Default state for desktop
8788
- const desktopNavDefault = () => {
8789
- moveNavToggleButtonToMobileControlsContainer();
8790
- const utilityLinks = document.querySelector(".settings-links");
8791
- const headerutilityLinksCont = document.querySelector(
8792
- ".utility-header .container .flex-row"
8793
- );
8794
- if (utilityLinks && headerutilityLinksCont)
8795
- headerutilityLinksCont.append(utilityLinks);
8796
- document.body.classList.remove("overflow-hidden");
8797
- const navSearchCont = document.querySelector(".navigation-search");
8798
- if (!navSearchCont) return;
8799
- navSearchCont.classList.remove("visible");
8800
- navSearchCont.classList.remove("not-visible");
8801
- navSearchCont.setAttribute("aria-hidden", "false");
8802
- getAllNavLinks().forEach(el => el.removeAttribute("tabindex"));
8803
- getAllUtilityLinks().forEach(el => el.removeAttribute("tabindex"));
8804
- getAllBodyLinks().forEach(el => el.removeAttribute("tabindex"));
8825
+ const setClosed = () => {
8826
+ if (navToggleBtn.ariaExpanded !== "false") {
8827
+ navToggleBtn.ariaExpanded = "false";
8828
+ }
8829
+ if (navMobileMenuToggleBtn.ariaExpanded !== "false") {
8830
+ navMobileMenuToggleBtn.ariaExpanded = "false";
8831
+ }
8832
+ if (mainNav) document.body.classList.remove("overflow-hidden");
8833
+
8834
+ // removing focus
8835
+ getAllNavLinks().forEach(el => (el.tabIndex = -1));
8805
8836
  // remove aria hidden for the rest of the site
8806
- setHidden(false);
8837
+ mainElements.forEach(x => (x.ariaHidden = null));
8838
+ regularHeader?.classList.remove("nav-overlay");
8839
+
8840
+ NavReset();
8807
8841
  };
8808
8842
 
8809
8843
  // Button Click event
8810
- navButton.addEventListener("click", openMenu);
8844
+ navToggleBtn.addEventListener("click", openMenu);
8845
+ // Button Click event
8846
+ navMobileMenuToggleBtn.addEventListener("click", closeMenu);
8811
8847
 
8812
8848
  const mobileCheck = () => {
8813
- const mobileCntls = document.querySelector(
8814
- ".global-header .mobile-controls"
8815
- );
8816
-
8817
- const mobileControlsDisplay = mobileCntls
8818
- ? window.getComputedStyle(mobileCntls).display
8819
- : "";
8820
-
8821
8849
  if (mobileControlsDisplay == "block") {
8822
- mobileNavDefault();
8823
- // if desktop
8850
+ // mobile
8851
+ setClosed();
8824
8852
  } else {
8825
- desktopNavDefault();
8853
+ // desktop
8854
+ setOpen();
8855
+ NavReset();
8826
8856
  }
8827
8857
  };
8828
8858