@cagovweb/state-template 6.5.1 → 6.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
- var StateTemplateNpmPackageVersion="6.5.1";
1
+ var StateTemplateNpmPackageVersion="6.5.3";
2
2
  /*!
3
- * Bootstrap v5.3.3 (https://getbootstrap.com/)
4
- * Copyright 2011-2024 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
3
+ * Bootstrap v5.3.8 (https://getbootstrap.com/)
4
+ * Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
5
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6
6
  */
7
7
  (function (global, factory) {
@@ -205,7 +205,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
205
205
  * @param {HTMLElement} element
206
206
  * @return void
207
207
  *
208
- * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
208
+ * @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
209
209
  */
210
210
  const reflow = element => {
211
211
  element.offsetHeight; // eslint-disable-line no-unused-expressions
@@ -250,7 +250,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
250
250
  });
251
251
  };
252
252
  const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
253
- return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue;
253
+ return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
254
254
  };
255
255
  const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
256
256
  if (!waitForTransition) {
@@ -572,7 +572,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
572
572
  const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));
573
573
  for (const key of bsKeys) {
574
574
  let pureKey = key.replace(/^bs/, '');
575
- pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length);
575
+ pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1);
576
576
  attributes[pureKey] = normalizeData(element.dataset[key]);
577
577
  }
578
578
  return attributes;
@@ -647,7 +647,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
647
647
  * Constants
648
648
  */
649
649
 
650
- const VERSION = '5.3.3';
650
+ const VERSION = '5.3.8';
651
651
 
652
652
  /**
653
653
  * Class definition
@@ -673,6 +673,8 @@ var StateTemplateNpmPackageVersion="6.5.1";
673
673
  this[propertyName] = null;
674
674
  }
675
675
  }
676
+
677
+ // Private
676
678
  _queueCallback(callback, element, isAnimated = true) {
677
679
  executeAfterTransition(callback, element, isAnimated);
678
680
  }
@@ -1604,11 +1606,11 @@ var StateTemplateNpmPackageVersion="6.5.1";
1604
1606
  this._element.style[dimension] = '';
1605
1607
  this._queueCallback(complete, this._element, true);
1606
1608
  }
1609
+
1610
+ // Private
1607
1611
  _isShown(element = this._element) {
1608
1612
  return element.classList.contains(CLASS_NAME_SHOW$7);
1609
1613
  }
1610
-
1611
- // Private
1612
1614
  _configAfterMerge(config) {
1613
1615
  config.toggle = Boolean(config.toggle); // Coerce string values
1614
1616
  config.parent = getElement(config.parent);
@@ -2666,7 +2668,6 @@ var StateTemplateNpmPackageVersion="6.5.1";
2666
2668
  var popperOffsets = computeOffsets({
2667
2669
  reference: referenceClientRect,
2668
2670
  element: popperRect,
2669
- strategy: 'absolute',
2670
2671
  placement: placement
2671
2672
  });
2672
2673
  var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));
@@ -2994,7 +2995,6 @@ var StateTemplateNpmPackageVersion="6.5.1";
2994
2995
  state.modifiersData[name] = computeOffsets({
2995
2996
  reference: state.rects.reference,
2996
2997
  element: state.rects.popper,
2997
- strategy: 'absolute',
2998
2998
  placement: state.placement
2999
2999
  });
3000
3000
  } // eslint-disable-next-line import/no-unused-modules
@@ -3701,7 +3701,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
3701
3701
  }
3702
3702
  _createPopper() {
3703
3703
  if (typeof Popper === 'undefined') {
3704
- throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)');
3704
+ throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)');
3705
3705
  }
3706
3706
  let referenceElement = this._element;
3707
3707
  if (this._config.reference === 'parent') {
@@ -3780,7 +3780,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
3780
3780
  }
3781
3781
  return {
3782
3782
  ...defaultBsPopperConfig,
3783
- ...execute(this._config.popperConfig, [defaultBsPopperConfig])
3783
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
3784
3784
  };
3785
3785
  }
3786
3786
  _selectMenuItem({
@@ -4802,7 +4802,6 @@ var StateTemplateNpmPackageVersion="6.5.1";
4802
4802
  *
4803
4803
  * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38
4804
4804
  */
4805
- // eslint-disable-next-line unicorn/better-regex
4806
4805
  const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;
4807
4806
  const allowedAttribute = (attribute, allowedAttributeList) => {
4808
4807
  const attributeName = attribute.nodeName.toLowerCase();
@@ -4967,7 +4966,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
4967
4966
  return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;
4968
4967
  }
4969
4968
  _resolvePossibleFunction(arg) {
4970
- return execute(arg, [this]);
4969
+ return execute(arg, [undefined, this]);
4971
4970
  }
4972
4971
  _putElementInTemplate(element, templateElement) {
4973
4972
  if (this._config.html) {
@@ -5066,7 +5065,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
5066
5065
  class Tooltip extends BaseComponent {
5067
5066
  constructor(element, config) {
5068
5067
  if (typeof Popper === 'undefined') {
5069
- throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
5068
+ throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)');
5070
5069
  }
5071
5070
  super(element, config);
5072
5071
 
@@ -5112,7 +5111,6 @@ var StateTemplateNpmPackageVersion="6.5.1";
5112
5111
  if (!this._isEnabled) {
5113
5112
  return;
5114
5113
  }
5115
- this._activeTrigger.click = !this._activeTrigger.click;
5116
5114
  if (this._isShown()) {
5117
5115
  this._leave();
5118
5116
  return;
@@ -5300,7 +5298,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
5300
5298
  return offset;
5301
5299
  }
5302
5300
  _resolvePossibleFunction(arg) {
5303
- return execute(arg, [this._element]);
5301
+ return execute(arg, [this._element, this._element]);
5304
5302
  }
5305
5303
  _getPopperConfig(attachment) {
5306
5304
  const defaultBsPopperConfig = {
@@ -5338,7 +5336,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
5338
5336
  };
5339
5337
  return {
5340
5338
  ...defaultBsPopperConfig,
5341
- ...execute(this._config.popperConfig, [defaultBsPopperConfig])
5339
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
5342
5340
  };
5343
5341
  }
5344
5342
  _setListeners() {
@@ -5347,6 +5345,7 @@ var StateTemplateNpmPackageVersion="6.5.1";
5347
5345
  if (trigger === 'click') {
5348
5346
  EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => {
5349
5347
  const context = this._initializeOnDelegatedTarget(event);
5348
+ context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK]);
5350
5349
  context.toggle();
5351
5350
  });
5352
5351
  } else if (trigger !== TRIGGER_MANUAL) {
@@ -6212,7 +6211,6 @@ var StateTemplateNpmPackageVersion="6.5.1";
6212
6211
  }
6213
6212
 
6214
6213
  // Private
6215
-
6216
6214
  _maybeScheduleHide() {
6217
6215
  if (!this._config.autohide) {
6218
6216
  return;
@@ -6318,17 +6316,18 @@ var StateTemplateNpmPackageVersion="6.5.1";
6318
6316
  window.addEventListener("load", () => {
6319
6317
  const doc = document.documentElement;
6320
6318
 
6321
- let prevScroll = window.scrollY || doc.scrollTop;
6322
- let curScroll;
6323
- let direction = 0;
6324
- let prevDirection = 0;
6325
-
6326
- const headerAlert = document.querySelector("header .alert");
6319
+ const headerAlert = document.querySelectorAll("header .alert");
6327
6320
  const header = document.querySelector(".utility-header");
6328
6321
  const mainheader = document.querySelector("header");
6329
6322
  if (!header || !mainheader) return;
6330
6323
 
6331
- window.addEventListener("scroll", () => {
6324
+ let prevScroll;
6325
+ let curScroll;
6326
+ let direction = 0;
6327
+ let prevDirection = 0;
6328
+ let ticking = false;
6329
+
6330
+ const updateHeader = () => {
6332
6331
  /*
6333
6332
  ** Find the direction of scroll
6334
6333
  ** 0 - initial, 1 - up, 2 - down
@@ -6346,26 +6345,33 @@ window.addEventListener("load", () => {
6346
6345
  if (direction !== prevDirection) {
6347
6346
  // Toggle Header
6348
6347
  if (direction === 2 && curScroll > 40) {
6349
- const hiddenheight =
6350
- header.clientHeight + (headerAlert?.clientHeight || 0);
6348
+ // Add all the alert heights to the hidden height
6349
+ let alertHeight = 0;
6350
+ headerAlert.forEach(alert => {
6351
+ alertHeight += alert.clientHeight;
6352
+ });
6351
6353
 
6354
+ const hiddenheight = header.clientHeight + alertHeight;
6352
6355
  mainheader.style.top = `-${hiddenheight}px`;
6353
6356
  prevDirection = direction;
6354
6357
  } else if (direction === 1 && curScroll < 40) {
6355
- // mainheader.classList.remove('scrolled');
6356
- // header.classList.remove('is-hidden');
6357
- // header.removeAttribute("style");
6358
6358
  mainheader.style.removeProperty("top");
6359
6359
  prevDirection = direction;
6360
6360
  }
6361
6361
  }
6362
6362
 
6363
6363
  prevScroll = curScroll;
6364
+ ticking = false;
6365
+ };
6366
+
6367
+ window.addEventListener("scroll", () => {
6368
+ if (!ticking) {
6369
+ requestAnimationFrame(updateHeader);
6370
+ ticking = true;
6371
+ }
6364
6372
  });
6365
6373
  });
6366
6374
 
6367
- // retain scroll position
6368
-
6369
6375
  //@ts-check
6370
6376
 
6371
6377
  window.addEventListener("load", () => {
@@ -6872,12 +6878,15 @@ window.addEventListener("load", () => {
6872
6878
  * License MIT: https://github.com/nico3333fr/van11y-accessible-accordion-aria/blob/master/LICENSE
6873
6879
  */
6874
6880
  (() => {
6875
- const isDesktopWidth = () => window.innerWidth > 991; //Maximum px for mobile width
6881
+ const isDesktopWidth = () =>
6882
+ getComputedStyle(document.documentElement)
6883
+ .getPropertyValue("--is-mobile")
6884
+ .trim() === "0";
6876
6885
 
6877
6886
  /**
6878
- * @param {Object} obj
6879
- * @param {String} key
6880
- * @param {String | Number} value
6887
+ * @param {object} obj
6888
+ * @param {string} key
6889
+ * @param {string | number} value
6881
6890
  */
6882
6891
  const _defineProperty = (obj, key, value) => {
6883
6892
  if (key in obj) {
@@ -6897,8 +6906,8 @@ window.addEventListener("load", () => {
6897
6906
  const CACHE = {};
6898
6907
 
6899
6908
  /**
6900
- * @param {String | Number} id
6901
- * @param {Object} config
6909
+ * @param {string | number} id
6910
+ * @param {object} config
6902
6911
  */
6903
6912
  const set = (id, config) => {
6904
6913
  CACHE[id] = config;
@@ -6906,7 +6915,7 @@ window.addEventListener("load", () => {
6906
6915
 
6907
6916
  /**
6908
6917
  *
6909
- * @param {String | Number} id
6918
+ * @param {string | number} id
6910
6919
  */
6911
6920
  const get = id => {
6912
6921
  return CACHE[id];
@@ -6914,7 +6923,7 @@ window.addEventListener("load", () => {
6914
6923
 
6915
6924
  /**
6916
6925
  *
6917
- * @param {String | Number} id
6926
+ * @param {string | number} id
6918
6927
  */
6919
6928
  const remove = id => {
6920
6929
  return CACHE[id];
@@ -6931,10 +6940,11 @@ window.addEventListener("load", () => {
6931
6940
 
6932
6941
  const pluginConfig = loadConfig();
6933
6942
 
6934
- /** Find an element based on an Id
6935
- * @param {String} id Id to find
6936
- * @param {String} hash hash id (not mandatory)
6937
- * @return {Element | null} the element with the specified id
6943
+ /**
6944
+ * Find an element based on an Id
6945
+ * @param {string} id Id to find
6946
+ * @param {string} hash hash id (not mandatory)
6947
+ * @returns {Element | null} the element with the specified id
6938
6948
  */
6939
6949
  const findById = (id, hash) =>
6940
6950
  document.querySelector(`#${id}[${DATA_HASH_ID}="${hash}"]`);
@@ -6949,10 +6959,11 @@ window.addEventListener("load", () => {
6949
6959
  });
6950
6960
  };
6951
6961
 
6952
- /** search if element is or is contained in another element with attribute data-nav-id
6962
+ /**
6963
+ * search if element is or is contained in another element with attribute data-nav-id
6953
6964
  * @param {Element | null} el element (node)
6954
- * @param {String} hashId the attribute data-hashtooltip-id
6955
- * @return {String | null} the value of attribute data-hashtooltip-id
6965
+ * @param {string} hashId the attribute data-hashtooltip-id
6966
+ * @returns {string | null} the value of attribute data-hashtooltip-id
6956
6967
  */
6957
6968
  const searchParentHashId = (el, hashId) => {
6958
6969
  let parentElement = el;
@@ -6968,8 +6979,8 @@ window.addEventListener("load", () => {
6968
6979
 
6969
6980
  /**
6970
6981
  * @param {Element | null} el
6971
- * @param {String} parentClass
6972
- * @param {String} hashId
6982
+ * @param {string} parentClass
6983
+ * @param {string} hashId
6973
6984
  */
6974
6985
  const searchParent = (el, parentClass, hashId) => {
6975
6986
  let parentElement = el;
@@ -6986,16 +6997,6 @@ window.addEventListener("load", () => {
6986
6997
  return "";
6987
6998
  };
6988
6999
 
6989
- const mobileView = () => {
6990
- const mobileElement = document.querySelector(
6991
- ".global-header .mobile-controls"
6992
- );
6993
-
6994
- return mobileElement
6995
- ? getComputedStyle(mobileElement)["display"] !== "none"
6996
- : false;
6997
- };
6998
-
6999
7000
  /**
7000
7001
  * @param {...any} pluginArgs
7001
7002
  */
@@ -7093,7 +7094,7 @@ window.addEventListener("load", () => {
7093
7094
  // Init attributes accordion
7094
7095
  accordion_node.setAttribute(
7095
7096
  CONFIG.ATTR_MULTISELECTABLE,
7096
- mobileView() ? "true" : "false"
7097
+ !isDesktopWidth() ? "true" : "false"
7097
7098
  );
7098
7099
 
7099
7100
  accordion_node.setAttribute(DATA_HASH_ID, HASH_ID);
@@ -7298,7 +7299,7 @@ window.addEventListener("load", () => {
7298
7299
  );
7299
7300
  }
7300
7301
 
7301
- if (!mobileView()) {
7302
+ if (isDesktopWidth()) {
7302
7303
  accordionAllHeaders.forEach(header_node => {
7303
7304
  //Close all the other panels
7304
7305
 
@@ -7438,13 +7439,13 @@ window.addEventListener("load", () => {
7438
7439
  el.classList.add("has-sub");
7439
7440
 
7440
7441
  const carrot = document.createElement("span");
7441
- carrot.classList.add("ca-gov-icon-caret-down", "carrot");
7442
+ carrot.classList.add("carrot");
7442
7443
  carrot.ariaHidden = "true";
7443
7444
 
7444
7445
  const toggleSubNav = document.createElement("div");
7445
- toggleSubNav.classList.add("ca-gov-icon-caret-right", "rotate");
7446
+ toggleSubNav.classList.add("rotate");
7446
7447
  toggleSubNav.ariaHidden = "true";
7447
- toggleSubNav.style.display = mobileView() ? "block" : "none";
7448
+ toggleSubNav.style.display = isDesktopWidth() ? "none" : "block";
7448
7449
 
7449
7450
  el.appendChild(toggleSubNav);
7450
7451
  el.appendChild(carrot);
@@ -7485,6 +7486,11 @@ window.addEventListener("load", () => {
7485
7486
  ----------------------------------------- */
7486
7487
 
7487
7488
  window.addEventListener("load", () => {
7489
+ const isDesktopWidth = () =>
7490
+ getComputedStyle(document.documentElement)
7491
+ .getPropertyValue("--is-mobile")
7492
+ .trim() === "0";
7493
+
7488
7494
  const setSearchContainerAriaHidden = () => {
7489
7495
  if (searchContainer) {
7490
7496
  if (featuredsearch) {
@@ -7500,18 +7506,6 @@ window.addEventListener("load", () => {
7500
7506
  }
7501
7507
  };
7502
7508
 
7503
- const mobileControlVisible = () => {
7504
- const mobileElement = document.querySelector(
7505
- ".global-header .mobile-controls"
7506
- );
7507
-
7508
- if (mobileElement) {
7509
- return getComputedStyle(mobileElement)["display"] !== "none";
7510
- } else {
7511
- return false; // or whatever is supposed to be returned when there is no header
7512
- }
7513
- };
7514
-
7515
7509
  const removeSearchResults = () => {
7516
7510
  document.body.classList.remove("active-search");
7517
7511
  if (searchText) searchText.value = "";
@@ -7540,7 +7534,7 @@ window.addEventListener("load", () => {
7540
7534
 
7541
7535
  // document.dispatchEvent('cagov.searchresults.hide'); // ???
7542
7536
 
7543
- if (mobileControlVisible()) setSearchContainerAriaHidden();
7537
+ if (!isDesktopWidth()) setSearchContainerAriaHidden();
7544
7538
  };
7545
7539
 
7546
7540
  /** @type {HTMLInputElement | null} */
@@ -7568,34 +7562,31 @@ window.addEventListener("load", () => {
7568
7562
  ".search-container:not(.featured-search)"
7569
7563
  ); // only on subpages, unique, same as #head-search
7570
7564
 
7571
- // header, contains nav, search form, etc, unique
7572
- const headerHeight = /** @type {HTMLElement} */ (
7573
- document.querySelector(".global-header")
7574
- )?.offsetHeight; // header height
7575
-
7576
- /** @type {HTMLElement | null} */
7577
- const utility = document.querySelector(".utility-header"); // utility header, unique
7578
- const utilityHeight = utility?.offsetHeight || 0;
7579
- // utility header height
7580
-
7581
- /** @type {NodeListOf<HTMLElement>} */
7582
- const alertBanner = document.querySelectorAll(".alert-banner"); // page can have multiple
7565
+ const getSearchTop = () => {
7566
+ /** @type {HTMLElement} */
7567
+ const header = document.querySelector(".global-header");
7568
+ /** @type {HTMLElement} */
7569
+ const utility = document.querySelector(".utility-header");
7570
+ /** @type {NodeListOf<HTMLElement>} */
7571
+ const alertBanners = document.querySelectorAll(".alert-banner");
7583
7572
 
7584
- let alertbannerHeight = 0;
7585
- // taking into account multiple alert banners
7586
- alertBanner.forEach(oneBanner => {
7587
- alertbannerHeight += oneBanner.offsetHeight;
7588
- });
7573
+ const headerHeight = header?.offsetHeight || 0;
7574
+ const utilityHeight = utility?.offsetHeight || 0;
7575
+ const alertBannerHeight = Array.from(alertBanners).reduce(
7576
+ (sum, banner) => sum + (banner.offsetHeight || 0),
7577
+ 0
7578
+ );
7589
7579
 
7590
- //const fullnav = document.querySelector(".top-level-nav"); // navigation ul tag, unique
7580
+ // contains navigation and search form, unique
7581
+ // Full width navigation
7582
+ const navigationHeight = document
7583
+ .querySelector(".navigation-search")
7584
+ ?.classList.contains("full-width-nav")
7585
+ ? 82
7586
+ : 0;
7591
7587
 
7592
- // contains navigation and search form, unique
7593
- // Full width navigation
7594
- const navigationHeight = document
7595
- .querySelector(".navigation-search")
7596
- ?.classList.contains("full-width-nav")
7597
- ? 82
7598
- : 0;
7588
+ return headerHeight - utilityHeight - alertBannerHeight - navigationHeight;
7589
+ };
7599
7590
 
7600
7591
  if (searchText && searchContainer) {
7601
7592
  // Unfreeze search width when blured.
@@ -7623,15 +7614,14 @@ window.addEventListener("load", () => {
7623
7614
  }
7624
7615
 
7625
7616
  // search box top position
7626
- // TODO: Really close to searchTop() except for top size
7627
- if (!mobileControlVisible()) {
7617
+ const setSearchTop = () => {
7618
+ if (!searchbox) return;
7619
+
7628
7620
  // calulation search box top position
7629
- const searchtop =
7630
- headerHeight - utilityHeight - alertbannerHeight - navigationHeight;
7631
- if (!mobileControlVisible() && searchbox) {
7632
- searchbox.style.top = `${Math.max(searchtop, 82)}px`;
7621
+ if (isDesktopWidth()) {
7622
+ searchbox.style.top = `${Math.max(getSearchTop(), 55)}px`;
7633
7623
  }
7634
- }
7624
+ };
7635
7625
 
7636
7626
  // have the close button remove search results and the applied classes
7637
7627
  //resultsContainer.find('.close').on('click', removeSearchResults);
@@ -7727,46 +7717,18 @@ window.addEventListener("load", () => {
7727
7717
  }
7728
7718
  }
7729
7719
 
7730
- const setSearchTop = () => {
7731
- // calulation search box top position
7732
- const searchtop =
7733
- headerHeight - utilityHeight - alertbannerHeight - navigationHeight;
7734
- if (!mobileControlVisible() && searchbox) {
7735
- searchbox.style.top = `${Math.max(searchtop, 55)}px`;
7736
- }
7737
- };
7738
-
7739
7720
  // on alert close event
7740
7721
  document.querySelectorAll(".alert-banner .close").forEach(oneClose => {
7741
7722
  oneClose.addEventListener("click", setSearchTop);
7742
7723
  });
7743
7724
 
7744
- // Calculation search box top property on the scroll for the fixed nav
7745
- window.addEventListener("scroll", () => {
7746
- if (!mobileControlVisible()) {
7747
- // setting timeout before calculating the search box top property otherwise it can take into account transitional values.
7748
- setTimeout(setSearchTop, 400);
7749
-
7750
- // remove featured search on scroll in desktop
7751
- const FeaturedSearch = document.querySelector("nav ~ #head-search");
7752
- if (FeaturedSearch) {
7753
- if (
7754
- document.body.scrollTop >= 100 ||
7755
- document.documentElement.scrollTop >= 100
7756
- ) {
7757
- FeaturedSearch.classList.add("hidden-up");
7758
- } else {
7759
- FeaturedSearch.classList.remove("hidden-up");
7760
- }
7761
- }
7762
- }
7763
- });
7764
-
7765
- // search box top position if browser window is resized
7766
- window.addEventListener("resize", () => {
7767
- setSearchTop();
7768
- setSearchContainerAriaHidden();
7769
- });
7725
+ if (searchContainer || searchbox) {
7726
+ // search box top position if browser window is resized
7727
+ window.addEventListener("resize", () => {
7728
+ setSearchTop();
7729
+ setSearchContainerAriaHidden();
7730
+ });
7731
+ }
7770
7732
 
7771
7733
  setSearchContainerAriaHidden();
7772
7734
  });
@@ -7958,70 +7920,61 @@ window.addEventListener("load", () => {
7958
7920
  /**
7959
7921
  * @typedef {Object} ScrollCounter_Properties
7960
7922
  * @property {boolean} counterAlreadyFired
7961
- * @property {number} counterSpeed
7962
- * @property {number} counterTarget
7963
- * @property {number} counterCount
7964
- * @property {number} counterStep
7965
7923
  * @property {()=>void} updateCounter
7966
7924
  * @typedef {HTMLElement & ScrollCounter_Properties} ScrollCounter
7967
7925
  */
7968
7926
 
7969
7927
  document.addEventListener("DOMContentLoaded", () => {
7970
- // You can change this class to specify which elements are going to behave as counters.
7971
7928
  /** @type {NodeListOf<ScrollCounter>} */
7972
7929
  const elements = document.querySelectorAll(".scroll-counter");
7973
7930
 
7974
7931
  elements.forEach(item => {
7975
- // Add new attributes to the elements with the '.scroll-counter' HTML class
7976
7932
  item.counterAlreadyFired = false;
7977
- item.counterSpeed = Number(item.getAttribute("data-counter-time")) / 45;
7978
- item.counterTarget = +item.innerText;
7979
- item.counterCount = 0;
7980
- item.counterStep = item.counterTarget / item.counterSpeed;
7933
+
7934
+ const duration = Number(item.getAttribute("data-counter-time")); // ms
7935
+ const target = +item.textContent; // final number
7981
7936
 
7982
7937
  item.updateCounter = () => {
7983
- item.counterCount += item.counterStep;
7984
- item.innerText = Math.ceil(item.counterCount).toLocaleString();
7938
+ const start = performance.now();
7985
7939
 
7986
- if (item.counterCount < item.counterTarget) {
7987
- window.setTimeout(item.updateCounter, item.counterSpeed);
7988
- } else {
7989
- item.innerText = item.counterTarget.toLocaleString();
7990
- }
7940
+ const animate = now => {
7941
+ const elapsed = now - start;
7942
+ const progress = Math.min(elapsed / duration, 1);
7943
+ const current = Math.ceil(progress * target);
7944
+
7945
+ item.textContent = current.toLocaleString();
7946
+
7947
+ if (progress < 1) {
7948
+ requestAnimationFrame(animate);
7949
+ }
7950
+ };
7951
+
7952
+ requestAnimationFrame(animate);
7991
7953
  };
7992
7954
  });
7993
7955
 
7994
- // Function to determine if an element is visible in the web page
7995
- const isElementVisible = (/** @type {Element} */ el) => {
7996
- const scroll = window.scrollY || window.pageYOffset;
7997
- const boundsTop = el.getBoundingClientRect().top + scroll;
7998
- const viewport = {
7999
- top: scroll,
8000
- bottom: scroll + window.innerHeight
8001
- };
8002
- const bounds = {
8003
- top: boundsTop,
8004
- bottom: boundsTop + el.clientHeight
8005
- };
8006
- return (
8007
- (bounds.bottom >= viewport.top && bounds.bottom <= viewport.bottom) ||
8008
- (bounds.top <= viewport.bottom && bounds.top >= viewport.top)
8009
- );
7956
+ // Check if element is visible in viewport
7957
+ const isElementVisible = el => {
7958
+ const rect = el.getBoundingClientRect();
7959
+ return rect.top < window.innerHeight && rect.bottom > 0;
8010
7960
  };
8011
7961
 
8012
- // Funciton that will get fired uppon scrolling
7962
+ // Scroll handler
8013
7963
  const handleScroll = () => {
8014
7964
  elements.forEach(item => {
8015
7965
  if (item.counterAlreadyFired) return;
8016
7966
  if (!isElementVisible(item)) return;
7967
+
8017
7968
  item.updateCounter();
8018
7969
  item.counterAlreadyFired = true;
8019
7970
  });
8020
7971
  };
8021
7972
 
8022
- // Fire the function on load and scroll
7973
+ // Fire once on load and on scroll
8023
7974
  window.addEventListener("load", handleScroll);
8024
- window.addEventListener("scroll", handleScroll);
7975
+ window.addEventListener("scroll", () => {
7976
+ requestAnimationFrame(handleScroll);
7977
+ });
8025
7978
  });
8026
7979
 
8027
7980
  //@ts-check
@@ -8376,7 +8329,7 @@ window.addEventListener("load", () => {
8376
8329
 
8377
8330
  // create on this page label
8378
8331
  const onthispage =
8379
- '<div id="on-this-page-navigation-label" class="label">On this page</div>';
8332
+ '<div id="on-this-page-navigation-label" class="label" lang="en-US">On this page</div>';
8380
8333
  pagenav.innerHTML = onthispage;
8381
8334
 
8382
8335
  // add ul item to the nav and set aria labelledby
@@ -8686,11 +8639,12 @@ cagov-pagination .cagov-pagination__item:has(.cagov-pagination__link-inactive) {
8686
8639
  //@ts-check
8687
8640
 
8688
8641
  window.addEventListener("load", () => {
8689
- const isDesktopWidth = () => window.innerWidth > 991; //Maximum px for mobile width
8690
-
8691
8642
  /** @type {HTMLButtonElement} */
8692
8643
  const navToggleBtn = document.querySelector(".toggle-menu");
8693
8644
  if (!navToggleBtn) return;
8645
+ /** @type {HTMLDivElement} */
8646
+ const navSearchCont = document.querySelector(".navigation-search");
8647
+ if (!navSearchCont) return;
8694
8648
  /** @type {HTMLElement} */
8695
8649
  const mainNav = document.querySelector(".main-navigation");
8696
8650
  // create container for drawer mobile nav items
@@ -8714,16 +8668,6 @@ window.addEventListener("load", () => {
8714
8668
  navMobileMenuToggleBtn.append(...navCloseBtnSpans);
8715
8669
  mobileItemsCont.append(navMobileMenuToggleBtn);
8716
8670
 
8717
- // VARIABLES
8718
- /** @type {HTMLDivElement} */
8719
- const navSearchCont = document.querySelector(".navigation-search");
8720
- if (!navSearchCont) return;
8721
-
8722
- const mobileCntls = document.querySelector(".global-header .mobile-controls");
8723
- const mobileControlsDisplay = mobileCntls
8724
- ? window.getComputedStyle(mobileCntls).display
8725
- : "";
8726
-
8727
8671
  //Used for hiding/showing main elements
8728
8672
  const mainElements = document.querySelectorAll(
8729
8673
  ".main-content, footer, .site-footer, .utility-header, .branding"
@@ -8731,6 +8675,11 @@ window.addEventListener("load", () => {
8731
8675
 
8732
8676
  const regularHeader = document.querySelector("header");
8733
8677
 
8678
+ // Begin Function Definitions
8679
+ const isDesktopWidth = () =>
8680
+ getComputedStyle(document.documentElement)
8681
+ .getPropertyValue("--is-mobile")
8682
+ .trim() === "0";
8734
8683
  // reset navigation function
8735
8684
  const NavReset = () => {
8736
8685
  //RESET
@@ -8774,63 +8723,26 @@ window.addEventListener("load", () => {
8774
8723
  )
8775
8724
  );
8776
8725
 
8777
- // Escape key event listener
8778
- document.addEventListener("keydown", e => {
8779
- if (navSearchCont.classList.contains("visible")) {
8780
- if (e.key === "Escape") {
8781
- e.stopPropagation();
8782
- closeMenu();
8783
- }
8784
- }
8785
- });
8786
-
8787
- const checkIfMobileView = () => {
8788
- const mobileElement = document.querySelector(
8789
- ".global-header .mobile-controls"
8790
- );
8791
- return mobileElement
8792
- ? getComputedStyle(mobileElement)["display"] !== "none"
8793
- : false;
8794
- };
8795
-
8796
- // Close menu on focusout (tabbing out) event (if target is outside of mobile menu and ignore if focus target is navToggleBtn button)
8797
- navSearchCont.addEventListener("focusout", e => {
8798
- if (checkIfMobileView()) {
8799
- const child = /** @type {Node} **/ (e.relatedTarget);
8800
- const parent = /** @type {Node} **/ (e.currentTarget);
8801
-
8802
- if (child && !parent.contains(child)) {
8803
- closeMenu();
8804
- }
8805
- }
8806
- });
8807
-
8808
8726
  // Button click open menu function
8809
8727
  const openMenu = () => {
8810
8728
  navSearchCont.classList.add("visible");
8811
8729
  navSearchCont.classList.remove("not-visible");
8812
8730
  document.body.classList.add("overflow-hidden");
8813
8731
  navToggleBtn.ariaExpanded = "true";
8814
- setOpen();
8815
- // Hide all the website areas (add aria-hidden)
8816
- mainElements.forEach(x => (x.ariaHidden = "true"));
8817
-
8818
- regularHeader?.classList.add("nav-overlay");
8819
- navMobileMenuToggleBtn.focus();
8820
- };
8821
-
8822
- const setOpen = () => {
8823
8732
  navMobileMenuToggleBtn.ariaExpanded = "true";
8824
8733
  navSearchCont.ariaHidden = null;
8825
8734
  // make links focusable
8826
8735
  getAllNavLinks().forEach(el => el.removeAttribute("tabindex"));
8827
8736
  // desktop
8828
- if (
8829
- mobileControlsDisplay !== "block" &&
8830
- navToggleBtn.ariaExpanded !== "false"
8831
- ) {
8737
+
8738
+ if (isDesktopWidth() && navToggleBtn.ariaExpanded !== "false") {
8832
8739
  navToggleBtn.ariaExpanded = "false";
8833
8740
  }
8741
+ // Hide all the website areas (add aria-hidden)
8742
+ mainElements.forEach(x => (x.ariaHidden = "true"));
8743
+
8744
+ regularHeader?.classList.add("nav-overlay");
8745
+ navMobileMenuToggleBtn.focus();
8834
8746
  };
8835
8747
 
8836
8748
  // Button click close menu function
@@ -8844,10 +8756,6 @@ window.addEventListener("load", () => {
8844
8756
 
8845
8757
  navSearchCont.classList.add("not-visible");
8846
8758
 
8847
- setClosed();
8848
- };
8849
-
8850
- const setClosed = () => {
8851
8759
  if (navToggleBtn.ariaExpanded !== "false") {
8852
8760
  navToggleBtn.ariaExpanded = "false";
8853
8761
  }
@@ -8865,11 +8773,6 @@ window.addEventListener("load", () => {
8865
8773
  NavReset();
8866
8774
  };
8867
8775
 
8868
- // Button Click event
8869
- navToggleBtn.addEventListener("click", openMenu);
8870
- // Button Click event
8871
- navMobileMenuToggleBtn.addEventListener("click", closeMenu);
8872
-
8873
8776
  const mobileCheck = () => {
8874
8777
  const searchInput = document.querySelector(".search-textfield");
8875
8778
  if (!searchInput) return;
@@ -8903,10 +8806,37 @@ window.addEventListener("load", () => {
8903
8806
  }
8904
8807
  };
8905
8808
 
8809
+ // End Function Definitions
8810
+
8811
+ // Escape key event listener
8812
+ document.addEventListener("keydown", e => {
8813
+ if (e.key === "Escape" && navSearchCont.classList.contains("visible")) {
8814
+ e.stopPropagation();
8815
+ closeMenu();
8816
+ }
8817
+ });
8818
+
8819
+ // Close menu on focusout (tabbing out) event (if target is outside of mobile menu and ignore if focus target is navToggleBtn button)
8820
+ navSearchCont.addEventListener("focusout", e => {
8821
+ if (!isDesktopWidth()) {
8822
+ const child = /** @type {Node} **/ (e.relatedTarget);
8823
+ const parent = /** @type {Node} **/ (e.currentTarget);
8824
+
8825
+ if (child && !parent.contains(child)) {
8826
+ closeMenu();
8827
+ }
8828
+ }
8829
+ });
8830
+
8831
+ // Button Click event
8832
+ navToggleBtn.addEventListener("click", openMenu);
8833
+ // Button Click event
8834
+ navMobileMenuToggleBtn.addEventListener("click", closeMenu);
8835
+
8906
8836
  // Close mobile nav if click outside of nav
8907
8837
  regularHeader.addEventListener("mouseup", e => {
8908
8838
  // if the target of the click isn't the navigation container nor a descendant of the navigation
8909
- if (checkIfMobileView()) {
8839
+ if (!isDesktopWidth()) {
8910
8840
  if (
8911
8841
  navSearchCont !== e.target &&
8912
8842
  !navSearchCont?.contains(/**@type {Node} */ (e.target))