@graupl/graupl 1.0.0-beta.25 → 1.0.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/css/component/accordion.css +1 -1
  2. package/dist/css/component/accordion.css.map +1 -1
  3. package/dist/css/component/list.css +1 -1
  4. package/dist/css/component/list.css.map +1 -1
  5. package/dist/css/component.css +1 -1
  6. package/dist/css/component.css.map +1 -1
  7. package/dist/css/graupl.css +1 -1
  8. package/dist/css/graupl.css.map +1 -1
  9. package/dist/js/accordion.js +2 -2
  10. package/dist/js/accordion.js.map +1 -1
  11. package/dist/js/alert.js +2 -2
  12. package/dist/js/alert.js.map +1 -1
  13. package/dist/js/carousel.js +2 -2
  14. package/dist/js/carousel.js.map +1 -1
  15. package/dist/js/component/accordion.cjs.js +2 -2
  16. package/dist/js/component/accordion.cjs.js.map +1 -1
  17. package/dist/js/component/accordion.es.js +2 -2
  18. package/dist/js/component/accordion.es.js.map +1 -1
  19. package/dist/js/component/accordion.iife.js +2 -2
  20. package/dist/js/component/accordion.iife.js.map +1 -1
  21. package/dist/js/component/alert.cjs.js +2 -2
  22. package/dist/js/component/alert.cjs.js.map +1 -1
  23. package/dist/js/component/alert.es.js +2 -2
  24. package/dist/js/component/alert.es.js.map +1 -1
  25. package/dist/js/component/alert.iife.js +2 -2
  26. package/dist/js/component/alert.iife.js.map +1 -1
  27. package/dist/js/component/carousel.cjs.js +2 -2
  28. package/dist/js/component/carousel.cjs.js.map +1 -1
  29. package/dist/js/component/carousel.es.js +2 -2
  30. package/dist/js/component/carousel.es.js.map +1 -1
  31. package/dist/js/component/carousel.iife.js +2 -2
  32. package/dist/js/component/carousel.iife.js.map +1 -1
  33. package/dist/js/component/disclosure.cjs.js +2 -2
  34. package/dist/js/component/disclosure.cjs.js.map +1 -1
  35. package/dist/js/component/disclosure.es.js +2 -2
  36. package/dist/js/component/disclosure.es.js.map +1 -1
  37. package/dist/js/component/disclosure.iife.js +2 -2
  38. package/dist/js/component/disclosure.iife.js.map +1 -1
  39. package/dist/js/component/tabs.cjs.js +2 -2
  40. package/dist/js/component/tabs.cjs.js.map +1 -1
  41. package/dist/js/component/tabs.es.js +2 -2
  42. package/dist/js/component/tabs.es.js.map +1 -1
  43. package/dist/js/component/tabs.iife.js +2 -2
  44. package/dist/js/component/tabs.iife.js.map +1 -1
  45. package/dist/js/disclosure.js +2 -2
  46. package/dist/js/disclosure.js.map +1 -1
  47. package/dist/js/generator/accordion.cjs.js +2 -2
  48. package/dist/js/generator/accordion.cjs.js.map +1 -1
  49. package/dist/js/generator/accordion.es.js +2 -2
  50. package/dist/js/generator/accordion.es.js.map +1 -1
  51. package/dist/js/generator/accordion.iife.js +2 -2
  52. package/dist/js/generator/accordion.iife.js.map +1 -1
  53. package/dist/js/generator/alert.cjs.js +2 -2
  54. package/dist/js/generator/alert.cjs.js.map +1 -1
  55. package/dist/js/generator/alert.es.js +2 -2
  56. package/dist/js/generator/alert.es.js.map +1 -1
  57. package/dist/js/generator/alert.iife.js +2 -2
  58. package/dist/js/generator/alert.iife.js.map +1 -1
  59. package/dist/js/generator/carousel.cjs.js +2 -2
  60. package/dist/js/generator/carousel.cjs.js.map +1 -1
  61. package/dist/js/generator/carousel.es.js +2 -2
  62. package/dist/js/generator/carousel.es.js.map +1 -1
  63. package/dist/js/generator/carousel.iife.js +2 -2
  64. package/dist/js/generator/carousel.iife.js.map +1 -1
  65. package/dist/js/generator/disclosure.cjs.js +2 -2
  66. package/dist/js/generator/disclosure.cjs.js.map +1 -1
  67. package/dist/js/generator/disclosure.es.js +2 -2
  68. package/dist/js/generator/disclosure.es.js.map +1 -1
  69. package/dist/js/generator/disclosure.iife.js +2 -2
  70. package/dist/js/generator/disclosure.iife.js.map +1 -1
  71. package/dist/js/generator/tabs.cjs.js +2 -2
  72. package/dist/js/generator/tabs.cjs.js.map +1 -1
  73. package/dist/js/generator/tabs.es.js +2 -2
  74. package/dist/js/generator/tabs.es.js.map +1 -1
  75. package/dist/js/generator/tabs.iife.js +2 -2
  76. package/dist/js/generator/tabs.iife.js.map +1 -1
  77. package/dist/js/graupl.js +2 -8
  78. package/dist/js/graupl.js.map +1 -1
  79. package/dist/js/navigation.js +1 -1
  80. package/dist/js/navigation.js.map +1 -1
  81. package/dist/js/tabs.js +2 -2
  82. package/dist/js/tabs.js.map +1 -1
  83. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.cjs.js","names":["addClass","className","element","length","classList","add","removeClass","remove","selectAllFocusableElements","context","document","fn","querySelector","elements","Array","from","querySelectorAll","tabbableElements","filter","check","getAttribute","selectFirstFocusableElement","selectLastFocusableElement","selectNextFocusableElement","index","indexOf","selectPreviousFocusableElement","TransactionalValue","constructor","initialValue","options","_equals","equals","Object","is","_current","_committed","value","val","committed","isDirty","commit","reset","update","fn","addClass","removeClass","TransactionalValue","TabToggle","_dom","toggle","content","_elements","parent","_active","_activateEvent","CustomEvent","bubbles","detail","item","_deactivateEvent","constructor","toggleElement","contentElement","parentTab","initialize","_setIds","_setAriaAttributes","dom","getAttribute","show","_deactivate","emit","transition","elements","isActive","value","key","index","tabToggle","indexOf","id","setAttribute","_activate","closeClass","openClass","transitionClass","openDuration","requestAnimationFrame","setTimeout","dispatchEvent","closeDuration","force","preserveState","focusState","commit","deactivateSiblings","hide","focus","blur","forEach","isValidInstance","constructor","elements","elementsType","TypeError","key","elementType","name","status","error","isValidType","type","values","valuesType","valueType","isQuerySelector","Error","document","querySelector","isValidClassList","Array","isArray","forEach","value","obj","isValidHoverType","validTypes","includes","join","isTag","tagName","HTMLElement","tag","toLowerCase","check","isValidState","validStates","isValidEvent","validEvents","keyPress","event","key","keyCode","keys","Enter","Space","Escape","ArrowUp","ArrowRight","ArrowDown","ArrowLeft","Home","End","Tab","Object","find","preventEvent","preventDefault","stopPropagation","isValidType","initializeStorage","type","window","Graupl","getStorage","setStorage","data","clearStorage","pushToStorage","key","value","getFromStorage","removeFromStorage","TabToggle","isValidInstance","isValidType","isValidClassList","isQuerySelector","isValidState","isValidEvent","addClass","removeClass","keyPress","preventEvent","storage","Tabs","_dom","tabs","tabList","tabToggle","tabContent","_domLock","_selectors","_elements","_classes","open","close","transition","initialize","_durations","_focusState","_currentEvent","_automatic","_currentChild","_prefix","_key","_errors","constructor","tabsElement","tabListSelector","tabToggleSelector","tabContentSelector","openClass","closeClass","transitionClass","transitionDuration","openDuration","closeDuration","automaticActivation","prefix","key","initializeClass","_validate","Error","errors","join","dom","_generateKey","_setDOMElements","_setIds","_setAriaAttributes","_createChildElements","_handleFocus","_handleClick","_handleKeydown","_handleKeyup","_setTransitionDurations","initializeStorage","pushToStorage","id","elements","filter","toggle","isActive","length","show","requestAnimationFrame","error","console","selectors","value","isAutomatic","currentChild","currentTabToggle","focusState","currentEvent","check","htmlElementChecks","HTMLElement","push","message","querySelectors","querySelector","Object","keys","querySelectorChecks","classes","className","classListChecks","status","durations","durationName","durationChecks","booleanCheck","keyCheck","prefixCheck","regenerate","Math","random","toString","replace","substring","setAttribute","style","setProperty","_setDOMElementType","elementType","base","overwrite","strict","includes","name","domElements","Array","from","querySelectorAll","filteredElements","item","parentElement","isArray","_resetDOMElementType","forEach","index","toggleElement","contentElement","parentTab","addEventListener","event","ToggleKeys","focusFirstChild","focusLastChild","focusNextChild","focusPreviousChild","focusCurrentChild","focus","focusChild","blurCurrentChild","blur"],"sources":["../../../packages/core/src/js/domHelpers.js","../../../packages/core/src/js/TransactionalValue.js","../../../packages/core/src/js/tabs/TabToggle.js","../../../packages/core/src/js/validate.js","../../../packages/core/src/js/eventHandlers.js","../../../packages/core/src/js/storage.js","../../../packages/core/src/js/tabs/Tabs.js"],"sourcesContent":["/**\n * Add a class or array of classes to an element.\n *\n * @param {string|string[]} className - The class or classes to add.\n * @param {HTMLElement} element - The element to add the class to.\n */\nexport function addClass(className, element) {\n // Gracefully handle empty strings or arrays.\n if (className === \"\" || className.length === 0) {\n return;\n }\n\n if (typeof className === \"string\") {\n element.classList.add(className);\n } else {\n element.classList.add(...className);\n }\n}\n\n/**\n * Remove a class or array of classes from an element.\n *\n * @param {string|string[]} className - The class or classes to remove.\n * @param {HTMLElement} element - The element to remove the class from.\n */\nexport function removeClass(className, element) {\n // Gracefully handle empty strings or arrays.\n if (className === \"\" || className.length === 0) {\n return;\n }\n\n if (typeof className === \"string\") {\n element.classList.remove(className);\n } else {\n element.classList.remove(...className);\n }\n}\n\n/**\n * Select all focusable elements within a given context.\n *\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement[]} - An array of focusable elements.\n */\nexport function selectAllFocusableElements(context = document, fn = null) {\n const querySelector =\n \"a[href],area[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),[tabindex]\";\n const elements = Array.from(context.querySelectorAll(querySelector));\n\n const tabbableElements = elements.filter((element) => {\n let check = true;\n\n if (element.getAttribute(\"tabindex\") === \"-1\") check = false;\n\n return check;\n });\n\n if (fn !== null) {\n return tabbableElements.filter(fn);\n } else {\n return tabbableElements;\n }\n}\n\n/**\n * Select the first focusable element within a given context.\n *\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The first focusable element or false if none found.\n */\nexport function selectFirstFocusableElement(context = document, fn = null) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n\n return tabbableElements[0] || false;\n}\n\n/**\n * Select the last focusable element within a given context.\n *\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The last focusable element or false if none found.\n */\nexport function selectLastFocusableElement(context = document, fn = null) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n\n return tabbableElements[tabbableElements.length - 1] || false;\n}\n\n/**\n * Select the next focusable element relative to the given element within a context.\n *\n * @param {HTMLElement} element - The reference element.\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The next focusable element or false if none found.\n */\nexport function selectNextFocusableElement(\n element,\n context = document,\n fn = null\n) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n const index = tabbableElements.indexOf(element);\n\n return index === tabbableElements.length - 1\n ? false\n : tabbableElements[index + 1];\n}\n\n/**\n * Select the previous focusable element relative to the given element within a context.\n *\n * @param {HTMLElement} element - The reference element.\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The previous focusable element or false if none found.\n */\nexport function selectPreviousFocusableElement(\n element,\n context = document,\n fn = null\n) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n const index = tabbableElements.indexOf(element);\n\n return index === 0 ? false : tabbableElements[index - 1];\n}\n","/**\n * A utility class that maintains a \"current\" value and a \"committed\" value.\n *\n * Useful when you need to:\n * - Track in-progress edits and revert to the last saved state.\n * - Compare pending and committed states.\n * - Know if a value has changed since last commit.\n *\n * @example\n * // Managing a form field\n * const username = new TransactionalValue(\"Nick\");\n * username.value = \"NickDJM\";\n * if (username.isDirty) {\n * console.log(\"Unsaved changes detected\");\n * username.commit(); // saves the new value\n * }\n *\n * @example\n * // Reverting edits\n * const counter = new TransactionalValue(10);\n * counter.value = 15;\n * counter.reset(); // reverts to 10\n */\nexport class TransactionalValue {\n /**\n * Creates a new TransactionalValue instance.\n *\n * @param {*} initialValue - The starting (and initially committed) value.\n * @param {{ equals?: function(*, *): boolean }} [options] - Optional config.\n * @param {function(*, *): boolean} [options.equals] - Custom equality comparator. Defaults to `Object.is`.\n */\n constructor(initialValue, options = {}) {\n /**\n * A comparator function used to check equality between\n * the current and committed values.\n *\n * @private\n *\n * @type {function(*, *): boolean}\n */\n this._equals = options.equals || Object.is;\n\n /**\n * The current, editable value.\n *\n * @private\n *\n * @type {*}\n */\n this._current = initialValue;\n\n /**\n * The last committed (baseline) value.\n *\n * @private\n *\n * @type {*}\n */\n this._committed = initialValue;\n }\n\n /**\n * Gets the current editable value.\n *\n * @return {*} The current value.\n *\n * @see _current\n */\n get value() {\n return this._current;\n }\n\n /**\n * Sets the current editable value.\n *\n * @param {*} val - The new value.\n */\n set value(val) {\n this._current = val;\n }\n\n /**\n * Gets the last committed (baseline) value.\n *\n * @readonly\n *\n * @return {*} The last committed value.\n *\n * @see _committed\n */\n get committed() {\n return this._committed;\n }\n\n /**\n * Checks whether the current value differs from the committed one.\n *\n * @readonly\n *\n * @return {boolean} `true` if current and committed values differ.\n */\n get isDirty() {\n return !this._equals(this._current, this._committed);\n }\n\n /**\n * Commits the current value, setting it as the new baseline.\n *\n * @return {TransactionalValue} The current instance.\n */\n commit() {\n this._committed = this._current;\n return this;\n }\n\n /**\n * Resets the current value to the committed baseline.\n *\n * @return {TransactionalValue} The current instance.\n */\n reset() {\n this._current = this._committed;\n return this;\n }\n\n /**\n * Applies a functional update to the current value.\n *\n * @param {function(*): *} fn - A function that receives the previous value and returns the new one.\n * @return {TransactionalValue} The current instance.\n *\n * @example\n * const t = new TransactionalValue(1);\n * t.update(n => n + 1); // 2\n */\n update(fn) {\n this._current = fn(this._current);\n return this;\n }\n}\n","/* global Tabs */\n\nimport { addClass, removeClass } from \"@graupl/core/src/domHelpers.js\";\nimport { TransactionalValue } from \"../TransactionalValue.js\";\n\nclass TabToggle {\n /**\n * The DOM elements within the tab toggle.\n *\n * @protected\n *\n * @type {Object<HTMLElement>}\n *\n * @property {HTMLElement} toggle - The toggle element.\n * @property {HTMLElement} content - The content element.\n */\n _dom = {\n toggle: null,\n content: null,\n };\n\n /**\n * The declared elements within the tab toggle.\n *\n * @protected\n *\n * @type {Object<Tabs>}\n *\n * @property {Tabs} parent - The parent tabs element.\n */\n _elements = {\n parent: null,\n };\n\n /**\n * The active state of the tab toggle.\n *\n * @protected\n *\n * @type {TransactionalValue}\n */\n _active = new TransactionalValue(false);\n\n /**\n * The event that is triggered when the tab toggle is shown.\n *\n * @protected\n *\n * @event grauplTabToggleActivate\n *\n * @type {CustomEvent}\n *\n * @property {boolean} bubbles - A flag to bubble the event.\n * @property {Object<TabToggle>} detail - The details object containing the Accordion item itself.\n */\n _activateEvent = new CustomEvent(\"grauplTabToggleActivate\", {\n bubbles: true,\n detail: { item: this },\n });\n\n /**\n * The event that is triggered when the tab toggle is hidden.\n *\n * @protected\n *\n * @event grauplTabToggleDeactivate\n *\n * @type {CustomEvent}\n *\n * @property {boolean} bubbles - A flag to bubble the event.\n * @property {Object<TabToggle>} detail - The details object containing the Accordion item itself.\n */\n _deactivateEvent = new CustomEvent(\"grauplTabToggleDeactivate\", {\n bubbles: true,\n detail: { item: this },\n });\n\n constructor({ toggleElement, contentElement, parentTab }) {\n // Set DOM elements.\n this._dom.toggle = toggleElement;\n this._dom.content = contentElement;\n\n // Set the parent tab instance.\n this._elements.parent = parentTab;\n }\n\n /**\n * Initializes the tab toggle.\n */\n initialize() {\n // Set up the DOM.\n this._setIds();\n this._setAriaAttributes();\n\n if (this.dom.toggle.getAttribute(\"aria-selected\") === \"true\") {\n this.show();\n } else {\n this._deactivate({ emit: false, transition: false });\n }\n }\n\n /**\n * The DOM elements of the tab toggle.\n *\n * @readonly\n *\n * @type {Object<HTMLElement>}\n *\n * @see _dom\n */\n get dom() {\n return this._dom;\n }\n\n /**\n * The declared elements in the tab toggle.\n *\n * @protected\n *\n * @type {Object<Tabs>}\n *\n * @see _elements\n */\n get elements() {\n return this._elements;\n }\n\n /**\n * The active state of the tab toggle.\n *\n * @readonly\n *\n * @type {TransactionalValue}\n *\n * @see _active\n */\n get isActive() {\n return this._active.value;\n }\n\n /**\n * Sets the IDs of the tab toggle and it's content if they do not already exist.\n *\n * The generated IDs use the following format:\n * - toggle: `tab-toggle-${key}-${index}`\n * - content: `tab-content-${key}-${index}`\n *\n * Where `${key}` is the parent's key and `${index}` is the toggles index in the list of the parent's toggles.\n *\n * @protected\n */\n _setIds() {\n // Get the required information for IDs.\n const { key } = this.elements.parent;\n const index = this.elements.parent.dom.tabToggle.indexOf(this.dom.toggle);\n\n this.dom.toggle.id = this.dom.toggle.id || `tab-toggle-${key}-${index}`;\n this.dom.content.id = this.dom.content.id || `tab-content-${key}-${index}`;\n }\n\n /**\n * Sets the ARIA attributes on the disclosure and it's content.\n */\n _setAriaAttributes() {\n // Set the ARIA attributes for the tab item toggle.\n this.dom.toggle.setAttribute(\"role\", \"tab\");\n\n // If aria-selected is not explicitly set to \"true\", then set it to \"false\".\n if (this.dom.toggle.getAttribute(\"aria-selected\") !== \"true\") {\n this.dom.toggle.setAttribute(\"aria-selected\", \"false\");\n }\n\n // Set the aria-controls attribute for the toggle.\n this.dom.toggle.setAttribute(\"aria-controls\", this.dom.content.id);\n\n // Set the role for the content.\n this.dom.content.setAttribute(\"role\", \"tabpanel\");\n }\n\n /**\n * Activate the toggle.\n *\n * Sets the toggles's `aria-selected` to \"true\", adds the\n * open class to the content, and removes the closed class from the content.\n *\n * @protected\n *\n * @fires grauplTabToggleActivate\n *\n * @param {Object<boolean>} [options = {}] - Options for activating the toggle.\n * @param {boolean} [options.emit = true] - Emit the activat event once activated.\n * @param {boolean} [options.transition = true] - Respect the transition class.\n */\n _activate({ emit = true, transition = true } = {}) {\n const { closeClass, openClass, transitionClass, openDuration } =\n this.elements.parent;\n\n // Set aria-selected to true when hiding accordion item.\n this.dom.toggle.setAttribute(\"aria-selected\", \"true\");\n\n // If we're dealing with transition classes, then we need to utilize\n // requestAnimationFrame to add the transition class, remove the hide class,\n // add the show class, and finally remove the transition class.\n //\n // If `transition` is false, then it doesn't matter if the transition class\n // is set. Do not use the transition.\n if (transition && transitionClass !== \"\") {\n addClass(transitionClass, this.dom.content);\n\n requestAnimationFrame(() => {\n removeClass(closeClass, this.dom.content);\n\n requestAnimationFrame(() => {\n addClass(openClass, this.dom.content);\n\n requestAnimationFrame(() => {\n setTimeout(() => {\n removeClass(transitionClass, this.dom.content);\n }, openDuration);\n });\n });\n });\n } else {\n // Add the show class\n addClass(openClass, this.dom.content);\n\n // Remove the hide class.\n removeClass(closeClass, this.dom.content);\n }\n\n if (emit) {\n this.dom.toggle.dispatchEvent(this._activateEvent);\n }\n }\n\n /**\n * Deactivates the disclosure.\n *\n * Sets the toggles's `aria-expanded` to \"false\", adds the\n * close class to the content, and removes the open class from the content.\n *\n * @protected\n *\n * @fires grauplTabToggleDeactivate\n *\n * @param {Object<boolean>} [options = {}] - Options for collapsing the toggle.\n * @param {boolean} [options.emit = true] - Emit the deactivate event once deactivated.\n * @param {boolean} [options.transition = true] - Respect the transition class.\n */\n _deactivate({ emit = true, transition = true } = {}) {\n const { closeClass, openClass, transitionClass, closeDuration } =\n this.elements.parent;\n\n // Set aria-selected to false when hiding accordion item.\n this.dom.toggle.setAttribute(\"aria-selected\", \"false\");\n\n // If we're dealing with transition classes, then we need to utilize\n // requestAnimationFrame to add the transition class, remove the show class,\n // add the hide class, and finally remove the transition class.\n //\n // If `transition` is false, then it doesn't matter if the transition class\n // is set. Do not use the transition.\n if (transition && transitionClass !== \"\") {\n addClass(transitionClass, this.dom.content);\n\n requestAnimationFrame(() => {\n removeClass(openClass, this.dom.content);\n\n requestAnimationFrame(() => {\n addClass(closeClass, this.dom.content);\n\n requestAnimationFrame(() => {\n setTimeout(() => {\n removeClass(transitionClass, this.dom.content);\n }, closeDuration);\n });\n });\n });\n } else {\n // Add the hide class\n addClass(closeClass, this.dom.content);\n\n // Remove the show class.\n removeClass(openClass, this.dom.content);\n }\n\n if (emit) {\n this.dom.toggle.dispatchEvent(this._deactivateEvent);\n }\n }\n\n /**\n * Shows the tab toggle's content.\n *\n * @param {Object<boolean>} [options = {}] - Options for showing the toggle.\n * @param {boolean} [options.force = false] - Whether to force the show action.\n * @param {boolean} [options.preserveState = false] - Whether to preserve the active state.\n */\n show({ force = false, preserveState = false } = {}) {\n if (this.isActive && !force) return;\n\n // Set the focus state of the parent tabs element.\n this.elements.parent.focusState = \"self\";\n\n // Activate the toggle.\n this._activate();\n\n // Set the active state\n this._active.value = true;\n\n if (!preserveState) {\n this._active.commit();\n }\n\n // Set the tabindex to 0 so it can be focused.\n this.dom.toggle.setAttribute(\"tabindex\", \"0\");\n\n // Deactivate all sibling tab toggles.\n this.deactivateSiblings();\n }\n\n /**\n * Hides the tab toggle's content.\n *\n * @param {Object<boolean>} [options = {}] - Options for hiding the toggle.\n * @param {boolean} [options.force = false] - Whether to force the show action.\n * @param {boolean} [options.preserveState = false] - Whether to preserve the active state.\n */\n hide({ force = false, preserveState = false } = {}) {\n if (!this.isActive && !force) return;\n\n // Set the focus state of the parent tabs element.\n this.elements.parent.focusState = \"none\";\n\n // Deactivate the toggle.\n this._deactivate();\n\n // Set the active state\n this._active.value = false;\n\n if (!preserveState) {\n this._active.commit();\n }\n\n // Set the tabindex to -1.\n this.dom.toggle.setAttribute(\"tabindex\", \"-1\");\n }\n\n /**\n * Focuses the accordion item.\n *\n * @public\n */\n focus() {\n this.dom.toggle.focus();\n }\n\n /**\n * Blurs the accordion item.\n *\n * @public\n */\n blur() {\n this.dom.toggle.blur();\n }\n\n deactivateSiblings() {\n if (this.elements.parent) {\n this.elements.parent.elements.tabToggle.forEach((toggle) => {\n if (toggle !== this) {\n toggle.hide();\n }\n });\n }\n }\n}\n\nexport default TabToggle;\n","/**\n * Check to see if the provided elements have a specific constructor.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * This is essentially just a wrapper function around checking instanceof with\n * more descriptive error message to help debugging.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {object} constructor - The constructor to check for.\n * @param {object} elements - The element(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidInstance(constructor, elements) {\n try {\n if (typeof elements !== \"object\") {\n const elementsType = typeof elements;\n\n throw new TypeError(\n `Elements given to isValidInstance() must be inside of an object. \"${elementsType}\" given.`\n );\n }\n\n for (const key in elements) {\n if (!(elements[key] instanceof constructor)) {\n const elementType = typeof elements[key];\n throw new TypeError(\n `${key} must be an instance of ${constructor.name}. \"${elementType}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Check to see if the provided values are of a specific type.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * This is essentially just a wrapper function around checking typeof with\n * more descriptive error message to help debugging.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {string} type - The type to check for.\n * @param {object} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidType(type, values) {\n try {\n if (typeof values !== \"object\") {\n const valuesType = typeof values;\n\n throw new TypeError(\n `Values given to isValidType() must be inside of an object. \"${valuesType}\" given.`\n );\n }\n\n for (const key in values) {\n const valueType = typeof values[key];\n\n if (valueType !== type) {\n throw new TypeError(`${key} must be a ${type}. \"${valueType}\" given.`);\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Checks to see if the provided values are valid query selectors.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isQuerySelector(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isQuerySelector() must be inside of an object. \"${type}\" given.`\n );\n }\n\n for (const key in values) {\n try {\n if (values[key] === null) {\n throw new Error();\n }\n\n document.querySelector(values[key]);\n } catch {\n throw new TypeError(\n `${key} must be a valid query selector. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Checks to see if the provided value is either a string or an array of strings.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string, string[]>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidClassList(values) {\n try {\n if (typeof values !== \"object\" || Array.isArray(values)) {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidClassList() must be inside of an object. \"${type}\" given.`\n );\n }\n\n for (const key in values) {\n const type = typeof values[key];\n\n if (type !== \"string\") {\n if (Array.isArray(values[key])) {\n values[key].forEach((value) => {\n if (typeof value !== \"string\") {\n throw new TypeError(\n `${key} must be a string or an array of strings. An array containing non-strings given.`\n );\n }\n });\n } else {\n throw new TypeError(\n `${key} must be a string or an array of strings. \"${type}\" given.`\n );\n }\n } else {\n const obj = {};\n obj[key] = values[key];\n\n isQuerySelector(obj);\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Check to see if the provided values are valid hover types.\n *\n * Available types are: `\"off\"`, `\"on\"`, and `\"dynamic\"`.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidHoverType(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidHoverType() must be inside of an object. \"${type}\" given.`\n );\n }\n\n const validTypes = [\"off\", \"on\", \"dynamic\"];\n\n for (const key in values) {\n if (!validTypes.includes(values[key])) {\n throw new TypeError(\n `${key} must be one of the following values: ${validTypes.join(\n \", \"\n )}. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Checks to see if the provided elements are using a specific tag.\n *\n * The elements must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `true` if the check is successful.\n *\n * @param {string} tagName - The name of the tag.\n * @param {Object<HTMLElement>} elements - The element(s) to check.\n * @return {boolean} - The result of the check.\n */\nexport function isTag(tagName, elements) {\n if (\n isValidType(\"string\", { tagName }).status &&\n isValidInstance(HTMLElement, elements).status\n ) {\n const tag = tagName.toLowerCase();\n let check = true;\n\n for (const key in elements) {\n if (elements[key].tagName.toLowerCase() !== tag) check = false;\n }\n\n return check;\n } else {\n return false;\n }\n}\n\n/**\n * Check to see if the provided values are valid focus states for a menu.\n *\n * Available states are: `\"none\"`, `\"self\"`, and `\"child\"`.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidState(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidState() must be inside of an object. \"${type}\" given.`\n );\n }\n\n const validStates = [\"none\", \"self\", \"child\"];\n\n for (const key in values) {\n if (!validStates.includes(values[key])) {\n throw new TypeError(\n `${key} must be one of the following values: ${validStates.join(\n \", \"\n )}. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Check to see if the provided values are valid event types for a menu.\n *\n * Available events are: `\"none\"`, `\"mouse\"`, `\"keyboard\"`, and `\"character\"`.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidEvent(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidEvent() must be inside of an object. \"${type}\" given.`\n );\n }\n\n const validEvents = [\"none\", \"mouse\", \"keyboard\", \"character\"];\n\n for (const key in values) {\n if (!validEvents.includes(values[key])) {\n throw new TypeError(\n `${key} must be one of the following values: ${validEvents.join(\n \", \"\n )}. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n","/**\n * Retrieves the pressed key from an event.\n *\n * @param {KeyboardEvent} event - The keyboard event.\n * @return {string} - The name of the key or an empty string.\n */\nexport function keyPress(event) {\n try {\n // Use event.key or event.keyCode to support older browsers.\n const key = event.key || event.keyCode;\n const keys = {\n Enter: key === \"Enter\" || key === 13,\n Space: key === \" \" || key === \"Spacebar\" || key === 32,\n Escape: key === \"Escape\" || key === \"Esc\" || key === 27,\n ArrowUp: key === \"ArrowUp\" || key === \"Up\" || key === 38,\n ArrowRight: key === \"ArrowRight\" || key === \"Right\" || key === 39,\n ArrowDown: key === \"ArrowDown\" || key === \"Down\" || key === 40,\n ArrowLeft: key === \"ArrowLeft\" || key === \"Left\" || key === 37,\n Home: key === \"Home\" || key === 36,\n End: key === \"End\" || key === 35,\n Tab: key === \"Tab\" || key === 9,\n };\n\n return Object.keys(keys).find((key) => keys[key] === true) || \"\";\n } catch {\n // Return an empty string if something goes wrong.\n return \"\";\n }\n}\n\n/**\n * Stops an event from taking action.\n *\n * @param {Event} event - The event.\n */\nexport function preventEvent(event) {\n event.preventDefault();\n event.stopPropagation();\n}\n","/**\n * @file\n * Provides a system to get and store Graupl data in the browser.\n */\n\nimport { isValidType } from \"./validate.js\";\n\n/**\n * Initializes the storage system.\n *\n * @param {?string} [type = null] - The type of storage to initialize.\n */\nexport function initializeStorage(type = null) {\n window.Graupl = window.Graupl || {};\n\n if (isValidType(\"string\", { type })) {\n window.Graupl[type] = window.Graupl[type] || {};\n }\n}\n\n/**\n * Get the storage object.\n *\n * @param {?string} type - The type of storage to get.\n * @return {object} - The storage object.\n */\nexport function getStorage(type = null) {\n if (isValidType(\"string\", { type })) {\n return window.Graupl[type];\n }\n\n return window.Graupl;\n}\n\n/**\n * Set the storage object of a given type.\n *\n * @param {string} type - The type of storage to set.\n * @param {object} data - The data to set.\n */\nexport function setStorage(type, data = {}) {\n if (isValidType(\"string\", { type }) && isValidType(\"object\", { data })) {\n window.Graupl[type] = data;\n }\n}\n\n/**\n * Clear the storage object of a given type.\n *\n * @param {string} type - The type of storage to clear.\n */\nexport function clearStorage(type) {\n if (isValidType(\"string\", { type })) {\n window.Graupl[type] = {};\n }\n}\n\n/**\n * Push a value to the storage object.\n *\n * @param {string} type - The type of storage to push to.\n * @param {string} key - The key to use for the value.\n * @param {*} value - The value to store.\n */\nexport function pushToStorage(type, key, value) {\n if (isValidType(\"string\", { type, key })) {\n window.Graupl[type][key] = value;\n }\n}\n\n/**\n * Get a value from the storage object.\n *\n * @param {string }type - The type of storage to get from.\n * @param {string }key - The key to get the value from.\n * @return {*} - The value from the storage object.\n */\nexport function getFromStorage(type, key) {\n if (isValidType(\"string\", { type, key })) {\n return window.Graupl[type][key];\n }\n\n return null;\n}\n\n/**\n * Remove a value from the storage object.\n *\n * @param {string} type - The type of storage to remove from.\n * @param {string} key - The key to remove the value from.\n */\nexport function removeFromStorage(type, key) {\n if (isValidType(\"string\", { type, key })) {\n delete window.Graupl[type][key];\n }\n}\n\nexport default {\n initializeStorage,\n getStorage,\n setStorage,\n clearStorage,\n pushToStorage,\n getFromStorage,\n removeFromStorage,\n};\n","/**\n * @file\n * The Tab class.\n */\n\nimport TabToggle from \"./TabToggle.js\";\nimport {\n isValidInstance,\n isValidType,\n isValidClassList,\n isQuerySelector,\n isValidState,\n isValidEvent,\n} from \"../validate.js\";\nimport { addClass, removeClass } from \"../domHelpers.js\";\nimport { keyPress, preventEvent } from \"../eventHandlers.js\";\nimport storage from \"../storage.js\";\n\nclass Tabs {\n /**\n * The DOM elements within the tab.\n *\n * @protected\n *\n * @type {Object<HTMLElement, HTMLElement[]>}\n *\n * @property {HTMLElement} tabs - The tabs element.\n * @property {HTMLElement} tabList - The tab list element.\n * @property {HTMLElement[]} tabToggle - An array of tab item toggles.\n * @property {HTMLElement[]} tabContent - An array of tab item contents.\n */\n _dom = {\n tabs: null,\n tabList: null,\n tabToggle: [],\n tabContent: [],\n };\n\n /**\n * The DOM elements within the tab that cannot be reset or generated by the tab.\n *\n * @protected\n *\n * @type {string[]}\n */\n _domLock = [\"tab\"];\n\n /**\n * The query selectors used by the tab.\n *\n * @protected\n *\n * @type {Object<string>}\n *\n * @property {string} tabList - The query selector for the tab list.\n * @property {string} tabToggle - The query selector for tab toggles.\n * @property {string} tabContent - The query selector for tab contents.\n */\n _selectors = {\n tabList: \"\",\n tabToggle: \"\",\n tabContent: \"\",\n };\n\n /**\n * The declared elements within the tabs.\n *\n * @protected\n *\n * @type {Object<TabToggle[]>}\n *\n * @property {TabToggle[]} tabToggle - The list of tab items.\n */\n _elements = {\n tabToggle: [],\n };\n\n /**\n * The classes to apply when the tabs are in various states.\n *\n * @protected\n *\n * @type {Object<string, string[]>}\n *\n * @property {string|string[]} open - The class(es) to apply when the tab is open.\n * @property {string|string[]} close - The class(es) to apply when the tab is closed.\n * @property {string|string[]} transition - The class(es) to apply when the tab is transitioning between states.\n * @property {string|string[]} initialize - The class(es) to apply when the tab is initializing.\n */\n _classes = {\n open: \"show\",\n close: \"hide\",\n transition: \"transitioning\",\n initialize: \"initializing\",\n };\n\n /**\n * The duration times (in milliseconds) for various things throughout the tabs.\n *\n * @protected\n *\n * @type {Object<number>}\n *\n * @property {number} transition - The duration time (in milliseconds) for the transition between open and closed states.\n * @property {number} open - The duration time (in milliseconds) for the transition from closed to open states.\n * @property {number} close - The duration time (in milliseconds) for the transition from open to closed states.\n */\n _durations = {\n transition: 250,\n open: -1,\n close: -1,\n };\n\n /**\n * The current state of the tab's focus.\n *\n * @protected\n *\n * @type {string}\n */\n _focusState = \"none\";\n\n /**\n * This last event triggered on the tab.\n *\n * @protected\n *\n * @type {string}\n */\n _currentEvent = \"none\";\n\n /**\n * A flag to set if focusing a tab item toggle will automatically activate it.\n *\n * @protected\n *\n * @type {boolean}\n */\n _automatic = false;\n\n /**\n * The index of the current child node.\n *\n * @protected\n *\n * @type {number}\n */\n _currentChild = 0;\n\n /**\n * The prefix to use for CSS custom properties.\n *\n * @protected\n *\n * @type {string}\n */\n _prefix = \"graupl-\";\n\n /**\n * The key used to generate IDs throughout the tab.\n *\n * @protected\n *\n * @type {string}\n */\n _key = \"\";\n\n /**\n * errors - The list of errors found during validation.\n *\n * @protected\n *\n * @type {string[]}\n */\n _errors = [];\n\n /**\n * Constructs a new `Tab`.\n *\n * @param {object} options - The options for generating the tab.\n * @param {HTMLElement} [options.tabsElement] - The tab element in the DOM.\n * @param {string} [options.tabListSelector = .tab-list] - The query selector string for the tab list.\n * @param {string} [options.tabToggleSelector = .tab-toggle] - The query selector string for tab toggle.\n * @param {string} [options.tabContentSelector = .tab-content] - The query selector string for tab content.\n * @param {?(string|string[])} [options.openClass = show] - The class to apply when a tab is \"open\".\n * @param {?(string|string[])} [options.closeClass = hide] - The class to apply when a tab is \"closed\".\n * @param {?(string|string[])} [options.transitionClass = null] - The class to apply when a tab is transitioning between \"open\" and \"closed\" states.\n * @param {number} [options.transitionDuration = 300] - The duration of the transition between \"open\" and \"closed\" states (in milliseconds).\n * @param {number} [options.openDuration = -1] - The duration of the transition from \"closed\" to \"open\" states (in milliseconds).\n * @param {number} [options.closeDuration = -1] - The duration of the transition from \"open\" to \"closed\" states (in milliseconds).\n * @param {boolean} [options.automaticActivation = false] - A flag to set if focusing a tab item toggle will automatically activate it.\n * @param {?string} [options.prefix = graupl-] - The prefix to use for CSS custom properties.\n * @param {?string} [options.key = null] - The key used to generate IDs throughout the tab.\n * @param {?(string|string[])} [options.initializeClass = initializing] - The class to apply when a tabs are initialzing.\n * @param {boolean} [options.initialize = false] - A flag to initialize the tab immediately upon creation.\n */\n constructor({\n tabsElement,\n tabListSelector = \".tab-list\",\n tabToggleSelector = \".tab-toggle\",\n tabContentSelector = \".tab-content\",\n openClass = \"show\",\n closeClass = \"hide\",\n transitionClass = null,\n transitionDuration = 300,\n openDuration = -1,\n closeDuration = -1,\n automaticActivation = false,\n prefix = \"graupl-\",\n key = null,\n initializeClass = \"initializing\",\n initialize = false,\n }) {\n // Set DOM elements.\n this._dom.tabs = tabsElement;\n\n // Set DOM selectors.\n this._selectors.tabList = tabListSelector;\n this._selectors.tabToggle = tabToggleSelector;\n this._selectors.tabContent = tabContentSelector;\n\n // Set open/close classes.\n this._classes.open = openClass || \"\";\n this._classes.close = closeClass || \"\";\n this._classes.transition = transitionClass || \"\";\n this._classes.initialize = initializeClass || \"\";\n\n // Set transition duration.\n this._durations.transition = transitionDuration;\n this._durations.open = openDuration;\n this._durations.close = closeDuration;\n\n // Set automatic activation.\n this._automatic = automaticActivation;\n\n // Set prefix.\n this._prefix = prefix || \"\";\n\n // Set the key.\n this._key = key || \"\";\n\n if (initialize) {\n this.initialize();\n }\n }\n\n /**\n * Initializes the tabs.\n */\n initialize() {\n try {\n if (!this._validate()) {\n throw new Error(\n `Graupl Tab: cannot initialize tab. The following errors have been found:\\n - ${this.errors.join(\n \"\\n - \"\n )}`\n );\n }\n\n addClass(this._classes.initialize, this.dom.tabs);\n\n // Set up the DOM.\n this._generateKey();\n this._setDOMElements();\n this._setIds();\n this._setAriaAttributes();\n\n // Create the child elements.\n this._createChildElements();\n\n // Handle events.\n this._handleFocus();\n this._handleClick();\n this._handleKeydown();\n this._handleKeyup();\n\n // // Set the custom props.\n this._setTransitionDurations();\n\n // Set up the storage.\n storage.initializeStorage(\"tabs\");\n storage.pushToStorage(\"tabs\", this.dom.tabs.id, this);\n\n if (\n this.elements.tabToggle.filter((toggle) => toggle.isActive).length === 0\n ) {\n this.elements.tabToggle[0].show();\n }\n\n requestAnimationFrame(() => {\n removeClass(this._classes.initialize, this.dom.tabs);\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n /**\n * The DOM elements of the tab.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _dom\n */\n get dom() {\n return this._dom;\n }\n\n /**\n * The declared elements of the tabs.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _elements\n */\n get elements() {\n return this._elements;\n }\n\n /**\n * The selectors used for the tab and tab items.\n *\n * @readonly\n *\n * @type {boolean}\n *\n * @see _selectors\n */\n get selectors() {\n return this._selectors;\n }\n\n /**\n * The class(es) to apply when the tab is open.\n *\n * @type {string|string[]}\n *\n * @see _classes.open\n */\n get openClass() {\n return this._classes.open;\n }\n\n set openClass(value) {\n isValidClassList({ openClass: value });\n\n if (this._classes.open !== value) {\n this._classes.open = value;\n }\n }\n\n /**\n * The class(es) to apply when the tab is closed.\n *\n * @type {string|string[]}\n *\n * @see _classes.close\n */\n get closeClass() {\n return this._classes.close;\n }\n\n set closeClass(value) {\n isValidClassList({ closeClass: value });\n\n if (this._classes.close !== value) {\n this._classes.close = value;\n }\n }\n\n /**\n * The class(es) to apply when the tab is transitioning between open and closed.\n *\n * @type {string|string[]}\n *\n * @see _classes.transition\n */\n get transitionClass() {\n return this._classes.transition;\n }\n\n set transitionClass(value) {\n isValidClassList({ transitionClass: value });\n\n if (this._classes.transition !== value) {\n this._classes.transition = value;\n }\n }\n\n /**\n * The duration time (in milliseconds) for the transition between open and closed states.\n *\n * @type {number}\n *\n * @see _durations.transition\n */\n get transitionDuration() {\n return this._durations.transition;\n }\n\n set transitionDuration(value) {\n isValidType(\"number\", { value });\n\n if (this._durations.transition !== value) {\n this._durations.transition = value;\n this._setTransitionDurations();\n }\n }\n\n /**\n * The duration time (in milliseconds) for the transition from closed to open states.\n *\n * If openDuration is set to -1, the transitionDuration will be used instead.\n *\n * @type {number}\n *\n * @see _durations.open\n */\n get openDuration() {\n return this._durations.open === -1\n ? this.transitionDuration\n : this._durations.open;\n }\n\n set openDuration(value) {\n isValidType(\"number\", { value });\n\n if (this._durations.open !== value) {\n this._durations.open = value;\n this._setTransitionDurations();\n }\n }\n\n /**\n * The duration time (in milliseconds) for the transition from open to closed states.\n *\n * If closeDuration is set to -1, the transitionDuration will be used instead.\n *\n * @type {number}\n *\n * @see _durations.close\n */\n get closeDuration() {\n return this._durations.close === -1\n ? this.transitionDuration\n : this._durations.close;\n }\n\n set closeDuration(value) {\n isValidType(\"number\", { value });\n\n if (this._durations.close !== value) {\n this._durations.close = value;\n this._setTransitionDurations();\n }\n }\n\n /**\n * A flag to set if focusing a tab item toggle will automatically activate it.\n *\n * @type {boolean}\n *\n * @see _automatic\n */\n get isAutomatic() {\n return this._automatic;\n }\n\n set isAutomatic(value) {\n isValidType(\"boolean\", { value });\n\n if (this._automatic !== value) {\n this._automatic = value;\n }\n }\n\n /**\n * The current index of the tab item.\n *\n * @readonly\n *\n * @type {number}\n *\n * @see _currentChild\n */\n get currentChild() {\n return this._currentChild;\n }\n\n set currentChild(value) {\n isValidType(\"number\", { value });\n\n if (\n this._currentChild !== value &&\n value >= 0 &&\n value < this.elements.tabToggle.length\n ) {\n this._currentChild = value;\n }\n }\n /**\n * The currently selected tab item.\n *\n * @readonly\n *\n * @type {TabToggle}\n */\n get currentTabToggle() {\n return this.elements.tabToggle[this.currentChild];\n }\n\n /**\n * The current state of the tab's focus.\n *\n * @type {string}\n *\n * @see _focusState\n */\n get focusState() {\n return this._focusState;\n }\n\n set focusState(value) {\n isValidState({ value });\n\n if (this._focusState !== value) {\n this._focusState = value;\n }\n }\n\n /**\n * The last event triggered on the tabs.\n *\n * @type {string}\n *\n * @see _currentEvent\n */\n get currentEvent() {\n return this._currentEvent;\n }\n\n set currentEvent(value) {\n isValidEvent({ value });\n\n if (this._currentEvent !== value) {\n this._currentEvent = value;\n }\n }\n\n /**\n * The prefix to use for CSS custom properties.\n *\n * @type {string}\n *\n * @see _prefix\n */\n get prefix() {\n return this._prefix;\n }\n\n set prefix(value) {\n isValidType(\"string\", { value });\n\n if (this._prefix !== value) {\n this._prefix = value;\n }\n }\n\n /**\n * The key used to generate IDs throughout the tab.\n *\n * @readonly\n *\n * @type {string}\n *\n * @see _key\n */\n get key() {\n return this._key;\n }\n\n /**\n * An array to hold error messages.\n *\n * @readonly\n *\n * @type {string[]}\n *\n * @see _errors\n */\n get errors() {\n return this._errors;\n }\n\n /**\n * Validates all aspects of the tabs to ensure proper functionality.\n *\n * @protected\n *\n * @return {boolean} - The result of the validation.\n */\n _validate() {\n let check = true;\n\n // HTML element checks.\n const htmlElementChecks = isValidInstance(HTMLElement, {\n tabsElement: this.dom.tabs,\n });\n\n if (!htmlElementChecks) {\n this._errors.push(htmlElementChecks.message);\n check = false;\n }\n\n // Query selector checks.\n const querySelectors = {};\n\n for (const querySelector of Object.keys(this._selectors)) {\n querySelectors[`${querySelector}Selector`] =\n this._selectors[querySelector];\n }\n\n const querySelectorChecks = isQuerySelector(querySelectors);\n\n if (!querySelectorChecks) {\n this._errors.push(querySelectorChecks.message);\n check = false;\n }\n\n // Class list checks.\n const classes = {};\n\n for (const className of Object.keys(this._classes)) {\n if (this._classes[className] === \"\") {\n continue;\n }\n\n classes[`${className}Class`] = this._classes[className];\n }\n\n const classListChecks = isValidClassList(classes);\n\n if (!classListChecks.status) {\n this._errors.push(classListChecks.error.message);\n check = false;\n }\n\n // Duration checks.\n const durations = {};\n\n for (const durationName of Object.keys(this._durations)) {\n durations[`${durationName}Duration`] = this._durations[durationName];\n }\n\n const durationChecks = isValidType(\"number\", durations);\n\n if (!durationChecks.status) {\n this._errors.push(durationChecks.error.message);\n check = false;\n }\n\n // Boolean checks.\n const booleanCheck = isValidType(\"boolean\", {\n automaticActivation: this._automatic,\n });\n\n if (!booleanCheck.status) {\n this._errors.push(booleanCheck.error.message);\n check = false;\n }\n\n // Key check.\n if (this._key !== \"\") {\n const keyCheck = isValidType(\"string\", { key: this._key });\n\n if (!keyCheck.status) {\n this._errors.push(keyCheck.error.message);\n check = false;\n }\n }\n\n // Prefix check.\n const prefixCheck = isValidType(\"string\", { prefix: this._prefix });\n\n if (!prefixCheck.status) {\n this._errors.push(prefixCheck.error.message);\n check = false;\n }\n\n return check;\n }\n\n /**\n * Generates a key for the tabs.\n *\n * @param {Object<boolean>} [options = {}] - Options for generating the key.\n * @param {boolean} [options.regenerate = false] - A flag to determine if the key should be regenerated.\n */\n _generateKey({ regenerate = false } = {}) {\n if (this.key === \"\" || regenerate) {\n this._key = Math.random()\n .toString(36)\n .replace(/[^a-z]+/g, \"\")\n .substring(0, 10);\n }\n }\n\n /**\n * Sets the IDs of the tab and it's children if they do not already exist.\n *\n * The generated IDs use the key and follow the format:\n * - tabs: `tabs-${key}`\n * - tab-list: `tab-list-${key}`\n *\n * @protected\n */\n _setIds() {\n this.dom.tabs.id = this.dom.tabs.id || `tabs-${this.key}`;\n this.dom.tabList.id = this.dom.tabList.id || `tab-list-${this.key}`;\n }\n\n /**\n * Sets the ARIA attributes for the tablist.\n *\n * @protected\n */\n _setAriaAttributes() {\n this.dom.tabList.setAttribute(\"role\", \"tablist\");\n }\n\n /**\n * Sets the transition durations of the tab as a CSS custom properties.\n *\n * The custom properties are:\n * - `--graupl-tabs-transition-duration`,\n * - `--graupl-tabs-open-transition-duration`, and\n * - `--graupl-tabs-close-transition-duration`.\n *\n * The prefix of `graupl-` can be changed by setting the tab's prefix value.\n *\n * @protected\n */\n _setTransitionDurations() {\n this.dom.tabs.style.setProperty(\n `--${this.prefix}tabs-transition-duration`,\n `${this.transitionDuration}ms`\n );\n\n this.dom.tabs.style.setProperty(\n `--${this.prefix}tabs-open-transition-duration`,\n `${this.openDuration}ms`\n );\n\n this.dom.tabs.style.setProperty(\n `--${this.prefix}tabs-close-transition-duration`,\n `${this.closeDuration}ms`\n );\n }\n\n /**\n * Sets DOM elements.\n *\n * Elements listed in _domLock cannot be set using this method.\n *\n * @protected\n *\n * @param {string} elementType - The type of element to populate.\n * @param {Object<HTMLElement,boolean>} [options = {}] - The options for setting the DOM element type.\n * @param {HTMLElement} [options.base = this.dom.tabs] - The element used as the base for the querySelector.\n * @param {boolean} [options.overwrite = true] - A flag to set if the existing elements will be overwritten.\n * @param {boolean} [options.strict = true] - A flag to set if the elements must be direct children of the base.\n */\n _setDOMElementType(\n elementType,\n { base = this.dom.tabs, overwrite = true, strict = true } = {}\n ) {\n if (typeof this.selectors[elementType] === \"string\") {\n if (this._domLock.includes(elementType)) {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" element cannot be set through _setDOMElementType.`\n );\n }\n\n if (base !== this.dom.tabs) isValidInstance(HTMLElement, { base });\n\n // Get the all elements matching the selector in the base.\n const domElements = Array.from(\n base.querySelectorAll(this.selectors[elementType])\n );\n\n // Filter the elements so only direct children of the base are kept.\n const filteredElements = domElements.filter((item) =>\n strict ? item.parentElement === base : true\n );\n\n if (overwrite) {\n if (Array.isArray(this._dom[elementType])) {\n this._dom[elementType] = filteredElements;\n } else {\n this._dom[elementType] = filteredElements[0] || null;\n }\n } else {\n if (Array.isArray(this._dom[elementType])) {\n this._dom[elementType] = [\n ...this._dom[elementType],\n ...filteredElements,\n ];\n } else {\n this._dom[elementType] = filteredElements[0] || null;\n }\n }\n } else {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" is not a valid element type.`\n );\n }\n }\n\n /**\n * Resets DOM elements.\n *\n * Elements listed in _domLock cannot be reset using this method.\n *\n * @protected\n *\n * @param {string} elementType - The type of element to clear.\n */\n _resetDOMElementType(elementType) {\n if (typeof this.selectors[elementType] === \"string\") {\n if (this._domLock.includes(elementType)) {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" element cannot be reset through _resetDOMElementType.`\n );\n }\n\n if (Array.isArray(this._dom[elementType])) {\n this._dom[elementType] = [];\n } else {\n this._dom[elementType] = null;\n }\n } else {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" is not a valid element type.`\n );\n }\n }\n\n /**\n * Sets all DOM elements within the tab.\n *\n * Utilizes _setDOMElementType and\n * _resetDOMElementType.\n *\n * @protected\n */\n _setDOMElements() {\n this._resetDOMElementType(\"tabList\");\n this._setDOMElementType(\"tabList\");\n\n if (this.dom.tabList) {\n this._resetDOMElementType(\"tabToggle\");\n this._setDOMElementType(\"tabToggle\", { base: this.dom.tabList });\n }\n\n this._resetDOMElementType(\"tabContent\");\n this._setDOMElementType(\"tabContent\");\n }\n\n /**\n * Creates and initializes all tab toggles.\n *\n * @protected\n */\n _createChildElements() {\n this.dom.tabToggle.forEach((tabToggle, index) => {\n const toggle = new TabToggle({\n toggleElement: tabToggle,\n contentElement: this.dom.tabContent[index],\n parentTab: this,\n });\n\n toggle.initialize();\n\n this._elements.tabToggle.push(toggle);\n });\n }\n\n /**\n * Handles focus events throughout the tab for proper use.\n *\n * - Adds a `focus` listener to every tab item so when it gains focus,\n * it will set the tab's current child to the index of the item.\n *\n * @protected\n */\n _handleFocus() {\n this.elements.tabToggle.forEach((toggle, index) => {\n toggle.dom.toggle.addEventListener(\"focus\", () => {\n this.currentChild = index;\n\n if (this.isAutomatic) {\n this.currentTabToggle.show();\n }\n });\n });\n }\n\n /**\n * Handles click events throughout the tab item for proper use.\n *\n * - Adds a `pointerup` listener to the tab item toggles that will toggle each tab item.\n *\n * @protected\n */\n _handleClick() {\n this.elements.tabToggle.forEach((toggle, index) => {\n toggle.dom.toggle.addEventListener(\"pointerup\", () => {\n this.currentChild = index;\n toggle.show();\n });\n });\n }\n\n /**\n * Handles keydown events throughout the tab item for proper use.\n *\n * This method exists to assist the _handleKeyup method.\n *\n * - Adds a `keydown` listener to all tab item toggles.\n * - Blocks propagation on \"Space\", \"Enter\", \"ArrowRight\", \"ArrowLeft\", \"Home\", and \"End\" keys.\n */\n _handleKeydown() {\n this.dom.tabToggle.forEach((tabToggle) => {\n tabToggle.addEventListener(\"keydown\", (event) => {\n const key = keyPress(event);\n const ToggleKeys = [\n \"Space\",\n \"Enter\",\n \"ArrowRight\",\n \"ArrowLeft\",\n \"Home\",\n \"End\",\n ];\n\n // Prevent default behavior for space and enter keys.\n if (ToggleKeys.includes(key)) {\n preventEvent(event);\n }\n });\n });\n }\n\n /**\n * Handles keyup events throughout the tab item for proper use.\n *\n * Adds the follow keybindings (explanations are taken from the WAI ARIA Practices Guide Tab Pattern):\n *\n * - `Enter` or `Space`:\n * - When focus is on the tab link for a collapsed panel, expands the associated panel. If the implementation allows only one panel to be expanded, and if another panel is expanded, collapses that panel.\n * - When focus is on the tab link for an expanded panel, collapses the panel if the implementation supports collapsing. Some implementations require one panel to be expanded at all times and allow only one panel to be expanded; so, they do not support a collapse function.\n * - `Tab`: Moves focus to the next focusable element; all focusable elements in the tab are included in the page `Tab` sequence.\n * - `Shift + Tab`: Moves focus to the previous focusable element; all focusable elements in the tab are included in the page `Tab` sequence.\n * - `Down Arrow` (Optional): If focus is on an tab link, moves focus to the next tab link. If focus is on the last tab link, either does nothing or moves focus to the first tab link.\n * - `Up Arrow` (Optional): If focus is on an tab link, moves focus to the previous tab link. If focus is on the first tab link, either does nothing or moves focus to the last tab link.\n * - `Home` (Optional): When focus is on an tab link, moves focus to the first tab link.\n * - `End` (Optional): When focus is on an tab link, moves focus to the last tab link.\n *\n * Note: When the above explanations mention \"tab link\", they are referring to the tab item toggle.\n */\n _handleKeyup() {\n this.dom.tabToggle.forEach((tabToggle) => {\n tabToggle.addEventListener(\"keyup\", (event) => {\n const key = keyPress(event);\n\n switch (key) {\n case \"Space\":\n case \"Enter\":\n preventEvent(event);\n this.currentTabToggle.show();\n\n break;\n case \"Home\":\n preventEvent(event);\n this.focusFirstChild();\n\n break;\n case \"End\":\n preventEvent(event);\n this.focusLastChild();\n\n break;\n case \"ArrowRight\":\n preventEvent(event);\n this.focusNextChild();\n\n break;\n case \"ArrowLeft\":\n preventEvent(event);\n this.focusPreviousChild();\n\n break;\n }\n });\n });\n }\n\n /**\n * Focus the tab's current child.\n *\n * @public\n */\n focusCurrentChild() {\n if (this.currentChild !== -1) {\n this.currentTabToggle.focus();\n }\n }\n\n /**\n * Focuses the tab's child at a given index.\n *\n * @public\n *\n * @param {number} index - The index of the child to focus.\n */\n focusChild(index) {\n this.blurCurrentChild();\n this.currentChild = index;\n this.focusCurrentChild();\n }\n\n /**\n * Focuses the tab's first child.\n *\n * @public\n */\n focusFirstChild() {\n this.focusChild(0);\n }\n\n /**\n * Focus the tab's last child.\n *\n * @public\n */\n focusLastChild() {\n this.focusChild(this.elements.tabToggle.length - 1);\n }\n\n /**\n * Focus the tab's next child.\n *\n * @public\n */\n focusNextChild() {\n if (this.currentChild < this.elements.tabToggle.length - 1) {\n this.focusChild(this.currentChild + 1);\n } else {\n this.focusFirstChild();\n }\n }\n\n /**\n * Focus the tab's previous child.\n *\n * @public\n */\n focusPreviousChild() {\n if (this.currentChild > 0) {\n this.focusChild(this.currentChild - 1);\n } else {\n this.focusLastChild();\n }\n }\n\n /**\n * Blurs the tab's current child.\n *\n * @public\n */\n blurCurrentChild() {\n if (this.currentChild !== -1) {\n this.currentTabToggle.blur();\n }\n }\n}\n\nexport default Tabs;\n"],"mappings":"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"}
1
+ {"version":3,"file":"tabs.cjs.js","names":["addClass","className","element","length","classList","add","removeClass","remove","selectAllFocusableElements","context","document","fn","querySelector","elements","Array","from","querySelectorAll","tabbableElements","filter","check","getAttribute","selectFirstFocusableElement","selectLastFocusableElement","selectNextFocusableElement","index","indexOf","selectPreviousFocusableElement","TransactionalValue","constructor","initialValue","options","_equals","equals","Object","is","_current","_committed","value","val","committed","isDirty","commit","reset","update","fn","isValidInstance","constructor","elements","elementsType","TypeError","key","elementType","name","status","error","isValidType","type","values","valuesType","valueType","isQuerySelector","Error","document","querySelector","isValidClassList","Array","isArray","forEach","value","obj","isValidHoverType","validTypes","includes","join","isTag","tagName","HTMLElement","tag","toLowerCase","check","isValidState","validStates","isValidEvent","validEvents","isValidType","initializeStorage","type","window","Graupl","getStorage","setStorage","data","clearStorage","pushToStorage","key","value","getFromStorage","removeFromStorage","isValidInstance","isValidType","isValidClassList","isQuerySelector","isValidState","isValidEvent","storage","Component","_dom","_protectedDOMElements","_selectors","_elements","_classes","initialize","_durations","_delays","_focusState","_currentEvent","_breakpoint","_mediaQueryString","_mediaQueryList","_mediaQueryListEventCallback","event","matches","_intervals","_timeouts","_listeners","_events","_prefix","_key","_storageKey","_id","_valid","_errors","constructor","prefix","key","initializeClass","_validate","Error","name","errors","join","_generateKey","error","console","init","dom","selectors","elements","classes","durations","delays","intervals","timeouts","listeners","events","value","focusState","currentEvent","breakpoint","mediaQuery","Object","keys","length","domElements","domKey","Array","isArray","forEach","element","index","domChecks","HTMLElement","push","message","querySelectors","querySelector","querySelectorChecks","className","classListChecks","status","durationName","durationChecks","delayName","delayChecks","keyCheck","prefixCheck","regenerate","Math","random","toString","replace","substring","_setIds","_setAriaAttributes","_setCustomProps","_setDOMElementType","elementType","context","overwrite","strict","includes","from","querySelectorAll","filteredElements","filter","item","parentElement","_resetDOMElementType","_setDOMElements","_createChildElements","_handleMediaMatch","_breakpointWidth","window","matchMedia","addEventListener","_handleFocus","_handleClick","_handleKeydown","_handleKeyup","_store","initializeStorage","pushToStorage","_unstore","removeFromStorage","_setInterval","callback","delay","scope","_clearInterval","setInterval","clearInterval","_setTimeout","_clearTimeout","setTimeout","clearTimeout","_dispatchEvent","eventType","dispatchEvent","_addEventListener","type","listener","options","_removeEventListener","removeEventListener","indexOf","splice","_removeEventListeners","dispose","addClass","removeClass","TransactionalValue","Component","TabToggle","_dom","toggle","content","_protectedDOMElements","_elements","parent","_active","_events","activate","CustomEvent","bubbles","detail","deactivate","constructor","toggleElement","contentElement","parentTab","prefix","key","initialize","_setIds","_setAriaAttributes","dom","getAttribute","show","force","emit","transition","hide","isActive","value","elements","index","tabToggle","indexOf","id","_id","setAttribute","_reveal","closeClass","openClass","transitionClass","openDuration","requestAnimationFrame","_setTimeout","_dispatchEvent","_conceal","closeDuration","preserveState","focusState","commit","hideSiblings","focus","blur","forEach","keyPress","event","key","keyCode","keys","Enter","Space","Escape","ArrowUp","ArrowRight","ArrowDown","ArrowLeft","Home","End","Tab","Object","find","preventEvent","preventDefault","stopPropagation","TabToggle","isValidType","isValidClassList","addClass","removeClass","keyPress","preventEvent","Component","Tabs","_dom","tabs","tabList","tabToggle","tabContent","_protectedDOMElements","_selectors","_elements","_classes","open","close","transition","initialize","_durations","_automatic","_currentChild","_storageKey","constructor","tabsElement","tabListSelector","tabToggleSelector","tabContentSelector","openClass","closeClass","transitionClass","transitionDuration","openDuration","closeDuration","automaticActivation","prefix","key","initializeClass","dom","_setDOMElements","_setIds","_setAriaAttributes","_setCustomProps","_createChildElements","_handleFocus","_handleClick","_handleKeydown","_handleKeyup","_store","elements","filter","toggle","isActive","length","show","error","console","requestAnimationFrame","value","_setTransitionDurations","isAutomatic","currentChild","currentTabToggle","_validate","booleans","booleanChecks","_errors","push","message","_valid","id","_id","setAttribute","style","setProperty","_resetDOMElementType","_setDOMElementType","context","forEach","index","toggleElement","contentElement","parentTab","_addEventListener","event","ToggleKeys","includes","focusFirstChild","focusLastChild","focusNextChild","focusPreviousChild","focusCurrentChild","focus","focusChild","blurCurrentChild","blur"],"sources":["../../../packages/core/src/js/domHelpers.js","../../../packages/core/src/js/TransactionalValue.js","../../../packages/core/src/js/validate.js","../../../packages/core/src/js/storage.js","../../../packages/core/src/js/Component.js","../../../packages/core/src/js/tabs/TabToggle.js","../../../packages/core/src/js/eventHandlers.js","../../../packages/core/src/js/tabs/Tabs.js"],"sourcesContent":["/**\n * Add a class or array of classes to an element.\n *\n * @param {string|string[]} className - The class or classes to add.\n * @param {HTMLElement} element - The element to add the class to.\n */\nexport function addClass(className, element) {\n // Gracefully handle empty strings or arrays.\n if (className === \"\" || className.length === 0) {\n return;\n }\n\n if (typeof className === \"string\") {\n element.classList.add(className);\n } else {\n element.classList.add(...className);\n }\n}\n\n/**\n * Remove a class or array of classes from an element.\n *\n * @param {string|string[]} className - The class or classes to remove.\n * @param {HTMLElement} element - The element to remove the class from.\n */\nexport function removeClass(className, element) {\n // Gracefully handle empty strings or arrays.\n if (className === \"\" || className.length === 0) {\n return;\n }\n\n if (typeof className === \"string\") {\n element.classList.remove(className);\n } else {\n element.classList.remove(...className);\n }\n}\n\n/**\n * Select all focusable elements within a given context.\n *\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement[]} - An array of focusable elements.\n */\nexport function selectAllFocusableElements(context = document, fn = null) {\n const querySelector =\n \"a[href],area[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),[tabindex]\";\n const elements = Array.from(context.querySelectorAll(querySelector));\n\n const tabbableElements = elements.filter((element) => {\n let check = true;\n\n if (element.getAttribute(\"tabindex\") === \"-1\") check = false;\n\n return check;\n });\n\n if (fn !== null) {\n return tabbableElements.filter(fn);\n } else {\n return tabbableElements;\n }\n}\n\n/**\n * Select the first focusable element within a given context.\n *\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The first focusable element or false if none found.\n */\nexport function selectFirstFocusableElement(context = document, fn = null) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n\n return tabbableElements[0] || false;\n}\n\n/**\n * Select the last focusable element within a given context.\n *\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The last focusable element or false if none found.\n */\nexport function selectLastFocusableElement(context = document, fn = null) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n\n return tabbableElements[tabbableElements.length - 1] || false;\n}\n\n/**\n * Select the next focusable element relative to the given element within a context.\n *\n * @param {HTMLElement} element - The reference element.\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The next focusable element or false if none found.\n */\nexport function selectNextFocusableElement(\n element,\n context = document,\n fn = null\n) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n const index = tabbableElements.indexOf(element);\n\n return index === tabbableElements.length - 1\n ? false\n : tabbableElements[index + 1];\n}\n\n/**\n * Select the previous focusable element relative to the given element within a context.\n *\n * @param {HTMLElement} element - The reference element.\n * @param {HTMLElement} [context = document] - The context in which to search for focusable elements.\n * @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.\n * @return {HTMLElement|boolean} - The previous focusable element or false if none found.\n */\nexport function selectPreviousFocusableElement(\n element,\n context = document,\n fn = null\n) {\n const tabbableElements = selectAllFocusableElements(context, fn);\n const index = tabbableElements.indexOf(element);\n\n return index === 0 ? false : tabbableElements[index - 1];\n}\n","/**\n * A utility class that maintains a \"current\" value and a \"committed\" value.\n *\n * Useful when you need to:\n * - Track in-progress edits and revert to the last saved state.\n * - Compare pending and committed states.\n * - Know if a value has changed since last commit.\n *\n * @example\n * // Managing a form field\n * const username = new TransactionalValue(\"Nick\");\n * username.value = \"NickDJM\";\n * if (username.isDirty) {\n * console.log(\"Unsaved changes detected\");\n * username.commit(); // saves the new value\n * }\n *\n * @example\n * // Reverting edits\n * const counter = new TransactionalValue(10);\n * counter.value = 15;\n * counter.reset(); // reverts to 10\n */\nexport class TransactionalValue {\n /**\n * Creates a new TransactionalValue instance.\n *\n * @param {*} initialValue - The starting (and initially committed) value.\n * @param {{ equals?: function(*, *): boolean }} [options] - Optional config.\n * @param {function(*, *): boolean} [options.equals] - Custom equality comparator. Defaults to `Object.is`.\n */\n constructor(initialValue, options = {}) {\n /**\n * A comparator function used to check equality between\n * the current and committed values.\n *\n * @private\n *\n * @type {function(*, *): boolean}\n */\n this._equals = options.equals || Object.is;\n\n /**\n * The current, editable value.\n *\n * @private\n *\n * @type {*}\n */\n this._current = initialValue;\n\n /**\n * The last committed (baseline) value.\n *\n * @private\n *\n * @type {*}\n */\n this._committed = initialValue;\n }\n\n /**\n * Gets the current editable value.\n *\n * @return {*} The current value.\n *\n * @see _current\n */\n get value() {\n return this._current;\n }\n\n /**\n * Sets the current editable value.\n *\n * @param {*} val - The new value.\n */\n set value(val) {\n this._current = val;\n }\n\n /**\n * Gets the last committed (baseline) value.\n *\n * @readonly\n *\n * @return {*} The last committed value.\n *\n * @see _committed\n */\n get committed() {\n return this._committed;\n }\n\n /**\n * Checks whether the current value differs from the committed one.\n *\n * @readonly\n *\n * @return {boolean} `true` if current and committed values differ.\n */\n get isDirty() {\n return !this._equals(this._current, this._committed);\n }\n\n /**\n * Commits the current value, setting it as the new baseline.\n *\n * @return {TransactionalValue} The current instance.\n */\n commit() {\n this._committed = this._current;\n return this;\n }\n\n /**\n * Resets the current value to the committed baseline.\n *\n * @return {TransactionalValue} The current instance.\n */\n reset() {\n this._current = this._committed;\n return this;\n }\n\n /**\n * Applies a functional update to the current value.\n *\n * @param {function(*): *} fn - A function that receives the previous value and returns the new one.\n * @return {TransactionalValue} The current instance.\n *\n * @example\n * const t = new TransactionalValue(1);\n * t.update(n => n + 1); // 2\n */\n update(fn) {\n this._current = fn(this._current);\n return this;\n }\n}\n","/**\n * Check to see if the provided elements have a specific constructor.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * This is essentially just a wrapper function around checking instanceof with\n * more descriptive error message to help debugging.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {object} constructor - The constructor to check for.\n * @param {object} elements - The element(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidInstance(constructor, elements) {\n try {\n if (typeof elements !== \"object\") {\n const elementsType = typeof elements;\n\n throw new TypeError(\n `Elements given to isValidInstance() must be inside of an object. \"${elementsType}\" given.`\n );\n }\n\n for (const key in elements) {\n if (!(elements[key] instanceof constructor)) {\n const elementType = typeof elements[key];\n throw new TypeError(\n `${key} must be an instance of ${constructor.name}. \"${elementType}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Check to see if the provided values are of a specific type.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * This is essentially just a wrapper function around checking typeof with\n * more descriptive error message to help debugging.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {string} type - The type to check for.\n * @param {object} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidType(type, values) {\n try {\n if (typeof values !== \"object\") {\n const valuesType = typeof values;\n\n throw new TypeError(\n `Values given to isValidType() must be inside of an object. \"${valuesType}\" given.`\n );\n }\n\n for (const key in values) {\n const valueType = typeof values[key];\n\n if (valueType !== type) {\n throw new TypeError(`${key} must be a ${type}. \"${valueType}\" given.`);\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Checks to see if the provided values are valid query selectors.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isQuerySelector(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isQuerySelector() must be inside of an object. \"${type}\" given.`\n );\n }\n\n for (const key in values) {\n try {\n if (values[key] === null) {\n throw new Error();\n }\n\n document.querySelector(values[key]);\n } catch {\n throw new TypeError(\n `${key} must be a valid query selector. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Checks to see if the provided value is either a string or an array of strings.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string, string[]>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidClassList(values) {\n try {\n if (typeof values !== \"object\" || Array.isArray(values)) {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidClassList() must be inside of an object. \"${type}\" given.`\n );\n }\n\n for (const key in values) {\n const type = typeof values[key];\n\n if (type !== \"string\") {\n if (Array.isArray(values[key])) {\n values[key].forEach((value) => {\n if (typeof value !== \"string\") {\n throw new TypeError(\n `${key} must be a string or an array of strings. An array containing non-strings given.`\n );\n }\n });\n } else {\n throw new TypeError(\n `${key} must be a string or an array of strings. \"${type}\" given.`\n );\n }\n } else {\n const obj = {};\n obj[key] = values[key];\n\n isQuerySelector(obj);\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Check to see if the provided values are valid hover types.\n *\n * Available types are: `\"off\"`, `\"on\"`, and `\"dynamic\"`.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidHoverType(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidHoverType() must be inside of an object. \"${type}\" given.`\n );\n }\n\n const validTypes = [\"off\", \"on\", \"dynamic\"];\n\n for (const key in values) {\n if (!validTypes.includes(values[key])) {\n throw new TypeError(\n `${key} must be one of the following values: ${validTypes.join(\n \", \"\n )}. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Checks to see if the provided elements are using a specific tag.\n *\n * The elements must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `true` if the check is successful.\n *\n * @param {string} tagName - The name of the tag.\n * @param {Object<HTMLElement>} elements - The element(s) to check.\n * @return {boolean} - The result of the check.\n */\nexport function isTag(tagName, elements) {\n if (\n isValidType(\"string\", { tagName }).status &&\n isValidInstance(HTMLElement, elements).status\n ) {\n const tag = tagName.toLowerCase();\n let check = true;\n\n for (const key in elements) {\n if (elements[key].tagName.toLowerCase() !== tag) check = false;\n }\n\n return check;\n } else {\n return false;\n }\n}\n\n/**\n * Check to see if the provided values are valid focus states for a menu.\n *\n * Available states are: `\"none\"`, `\"self\"`, and `\"child\"`.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidState(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidState() must be inside of an object. \"${type}\" given.`\n );\n }\n\n const validStates = [\"none\", \"self\", \"child\"];\n\n for (const key in values) {\n if (!validStates.includes(values[key])) {\n throw new TypeError(\n `${key} must be one of the following values: ${validStates.join(\n \", \"\n )}. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n\n/**\n * Check to see if the provided values are valid event types for a menu.\n *\n * Available events are: `\"none\"`, `\"mouse\"`, `\"keyboard\"`, and `\"character\"`.\n *\n * The values must be provided inside of an object\n * so the variable name can be retrieved in case of errors.\n *\n * Will return `{ status: true }` if the check is successful.\n *\n * @param {Object<string>} values - The value(s) to check.\n * @return {Object<boolean, string>} - The result of the check.\n */\nexport function isValidEvent(values) {\n try {\n if (typeof values !== \"object\") {\n const type = typeof values;\n\n throw new TypeError(\n `Values given to isValidEvent() must be inside of an object. \"${type}\" given.`\n );\n }\n\n const validEvents = [\"none\", \"mouse\", \"keyboard\", \"character\"];\n\n for (const key in values) {\n if (!validEvents.includes(values[key])) {\n throw new TypeError(\n `${key} must be one of the following values: ${validEvents.join(\n \", \"\n )}. \"${values[key]}\" given.`\n );\n }\n }\n\n return {\n status: true,\n error: null,\n };\n } catch (error) {\n return {\n status: false,\n error,\n };\n }\n}\n","/**\n * @file\n * Provides a system to get and store Graupl data in the browser.\n */\n\nimport { isValidType } from \"./validate.js\";\n\n/**\n * Initializes the storage system.\n *\n * @param {?string} [type = null] - The type of storage to initialize.\n */\nexport function initializeStorage(type = null) {\n window.Graupl = window.Graupl || {};\n\n if (isValidType(\"string\", { type })) {\n window.Graupl[type] = window.Graupl[type] || {};\n }\n}\n\n/**\n * Get the storage object.\n *\n * @param {?string} type - The type of storage to get.\n * @return {object} - The storage object.\n */\nexport function getStorage(type = null) {\n if (isValidType(\"string\", { type })) {\n return window.Graupl[type];\n }\n\n return window.Graupl;\n}\n\n/**\n * Set the storage object of a given type.\n *\n * @param {string} type - The type of storage to set.\n * @param {object} data - The data to set.\n */\nexport function setStorage(type, data = {}) {\n if (isValidType(\"string\", { type }) && isValidType(\"object\", { data })) {\n window.Graupl[type] = data;\n }\n}\n\n/**\n * Clear the storage object of a given type.\n *\n * @param {string} type - The type of storage to clear.\n */\nexport function clearStorage(type) {\n if (isValidType(\"string\", { type })) {\n window.Graupl[type] = {};\n }\n}\n\n/**\n * Push a value to the storage object.\n *\n * @param {string} type - The type of storage to push to.\n * @param {string} key - The key to use for the value.\n * @param {*} value - The value to store.\n */\nexport function pushToStorage(type, key, value) {\n if (isValidType(\"string\", { type, key })) {\n window.Graupl[type][key] = value;\n }\n}\n\n/**\n * Get a value from the storage object.\n *\n * @param {string }type - The type of storage to get from.\n * @param {string }key - The key to get the value from.\n * @return {*} - The value from the storage object.\n */\nexport function getFromStorage(type, key) {\n if (isValidType(\"string\", { type, key })) {\n return window.Graupl[type][key];\n }\n\n return null;\n}\n\n/**\n * Remove a value from the storage object.\n *\n * @param {string} type - The type of storage to remove from.\n * @param {string} key - The key to remove the value from.\n */\nexport function removeFromStorage(type, key) {\n if (isValidType(\"string\", { type, key })) {\n delete window.Graupl[type][key];\n }\n}\n\nexport default {\n initializeStorage,\n getStorage,\n setStorage,\n clearStorage,\n pushToStorage,\n getFromStorage,\n removeFromStorage,\n};\n","/**\n * @file\n * A generic component class.\n */\n\nimport {\n isValidInstance,\n isValidType,\n isValidClassList,\n isQuerySelector,\n isValidState,\n isValidEvent,\n} from \"./validate.js\";\nimport storage from \"./storage.js\";\n\nclass Component {\n /**\n * The DOM elements within the component.\n *\n * @protected\n *\n * @type {Object<HTMLElement, HTMLElement[]>}\n */\n _dom = {};\n\n /**\n * The DOM elements within the component that cannot be reset or generated by the component itself.\n *\n * @protected\n *\n * @type {string[]}\n */\n _protectedDOMElements = [];\n\n /**\n * The query selectors used by the component.\n *\n * @protected\n *\n * @type {Object<string>}\n */\n _selectors = {};\n\n /**\n * The instantiated elements within the component.\n *\n * @protected\n *\n * @type {object}\n */\n _elements = {};\n\n /**\n * The CSS classes to apply when the component is in various states.\n *\n * @protected\n *\n * @type {Object<string, string[]>}\n *\n * @\n */\n _classes = {\n initialize: \"\",\n };\n\n /**\n * The duration times (in milliseconds) for various aspects throughout the component.\n *\n * @protected\n *\n * @type {Object<number>}\n */\n _durations = {};\n\n /**\n * The delay times (in milliseconds) for various aspects throughout the component.\n *\n * @protected\n *\n * @type {Object<number>}\n */\n _delays = {};\n\n /**\n * The current state of the component's focus.\n *\n * @protected\n *\n * @type {string}\n */\n _focusState = \"none\";\n\n /**\n * The last type of event triggered within the component.\n *\n * @protected\n *\n * @type {string}\n */\n _currentEvent = \"none\";\n\n /**\n * The breakoint that the component will call media query list events.\n *\n * @protected\n *\n * @type {string}\n */\n _breakpoint = \"\";\n\n /**\n * The media query to use to trigger media query list events.\n *\n * @type {string}\n */\n _mediaQueryString = \"\";\n\n /**\n * This MediaQueryList for the component.\n *\n * @protected\n *\n * @type {MediaQueryList|null}\n */\n _mediaQueryList = null;\n\n /**\n * A callback for media query list events.\n *\n * @protected\n *\n * @type {Function}\n *\n * @param {MediaQueryListEvent} event - The event.\n */\n _mediaQueryListEventCallback = (event) => {\n // Add functionality to handle media matches.\n if (event.matches) {\n // Do something.\n } else {\n // Do something else.\n }\n };\n\n /**\n * Intervals throughout the component.\n *\n * @protected\n *\n * @type {Object<Function>}\n */\n _intervals = {};\n\n /**\n * Timeouts throughout the component.\n *\n * @protected\n *\n * @type {Object<Function>}\n */\n _timeouts = {};\n\n /**\n * Event listeners throughout the component.\n *\n * @protected\n *\n * @type {object[]}\n */\n _listeners = [];\n\n /**\n * Custom events that can be triggered throughout the component.\n *\n * @protected\n *\n * @type {Object<CustomEvent>}\n */\n _events = {};\n\n /**\n * The prefix used for CSS custom properties and attributes.\n *\n * @protected\n *\n * @type {string}\n */\n _prefix = \"graupl-\";\n\n /**\n * The key used to generate IDs throughout the component.\n *\n * @protected\n *\n * @type {string}\n */\n _key = \"\";\n\n /**\n * The key used for storage.\n *\n * @protected\n *\n * @type {string}\n */\n _storageKey = \"components\";\n\n /**\n * The main ID of the component.\n *\n * @protected\n *\n * @type {string}\n */\n _id = \"\";\n\n /**\n * The validity state of the component.\n *\n * @protected\n *\n * @type {boolean}\n */\n _valid = true;\n\n /**\n * The errors found throughout the component.\n *\n * @protected\n *\n * @type {string[]}\n */\n _errors = [];\n\n /**\n * Constructs a new component.\n *\n * @param {object} [options = {}] - The options for generating the component.\n * @param {?string} [options.prefix = graupl-] - The prefix used for CSS custom properties and attributes.\n * @param {?string} [options.key = null] - The key used to generate IDs throughout the component.\n * @param {?(string|string[])} [options.initializeClass = initializing] - The class(es) to apply when the component is initializing.\n */\n constructor({\n prefix = \"graupl-\",\n key = null,\n initializeClass = \"initializing\",\n } = {}) {\n // Set the classes.\n this._classes.initialize = initializeClass || \"\";\n\n // Set the prefix and key.\n this._prefix = prefix || \"\";\n this._key = key || \"\";\n }\n\n /**\n * Initialize the component.\n */\n initialize() {\n try {\n if (!this._validate()) {\n throw new Error(\n `Graupl ${this.constructor.name}: Cannot initialize component. The following errors have been found:\\n - ${this.errors.join(\"\\n - \")}`\n );\n }\n\n this._generateKey();\n } catch (error) {\n console.error(error);\n }\n }\n init() {\n this.initialize();\n }\n\n /**\n * The DOM elements within the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _dom\n */\n get dom() {\n return this._dom;\n }\n\n /**\n * The query selectors used by the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _selectors\n */\n get selectors() {\n return this._selectors;\n }\n\n /**\n * The instantiated elements within the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _elements\n */\n get elements() {\n return this._elements;\n }\n\n /**\n * The CSS classes to apply when the component is in various states.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _classes\n */\n get classes() {\n return this._classes;\n }\n\n /**\n * The duration times (in milliseconds) for various aspects throughout the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _durations\n */\n get durations() {\n return this._durations;\n }\n\n /**\n * The delay times (in milliseconds) for various aspects throughout the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _delays\n */\n get delays() {\n return this._delays;\n }\n\n /**\n * Intervals throughout the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _intervals\n */\n get intervals() {\n return this._intervals;\n }\n\n /**\n * Timeouts throughout the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _timeouts\n */\n get timeouts() {\n return this._timeouts;\n }\n\n /**\n * Event listeners throughout the component.\n *\n * @readonly\n *\n * @type {object[]}\n *\n * @see _listeners\n */\n get listeners() {\n return this._listeners;\n }\n\n /**\n * Custom events that can be triggered throughout the component.\n *\n * @readonly\n *\n * @type {object}\n *\n * @see _events\n */\n get events() {\n return this._events;\n }\n\n /**\n * The class(es) to apply when the component is initializing.\n *\n * @type {string|string[]}\n *\n * @see _classes.initialize\n */\n get initializeClass() {\n return this._classes.initialize;\n }\n\n set initializeClass(value) {\n isValidClassList({ initializeClass: value });\n\n if (this._classes.initialize !== value) {\n this._classes.initialize = value;\n }\n }\n\n /**\n * The current state of the component's focus.\n *\n * @type {string}\n *\n * @see _focusState\n */\n get focusState() {\n return this._focusState;\n }\n\n set focusState(value) {\n isValidState({ focusState: value });\n\n if (this._focusState !== value) {\n this._focusState = value;\n }\n }\n\n /**\n * The last type of event triggered within the component.\n *\n * @type {string}\n *\n * @see _currentEvent\n */\n get currentEvent() {\n return this._currentEvent;\n }\n\n set currentEvent(value) {\n isValidEvent({ currentEvent: value });\n\n if (this._currentEvent !== value) {\n this._currentEvent = value;\n }\n }\n\n /**\n * The breakoint that the component will call media query list events.\n *\n * @type {string}\n *\n * @see _breakpoint\n */\n get breakpoint() {\n return this._breakpoint;\n }\n\n set breakpoint(value) {\n isValidType(\"string\", { breakpoint: value });\n\n if (this._breakpoint !== value) {\n this._breakpoint = value;\n }\n }\n\n /**\n * The media query to use to trigger media query list events.\n *\n * @type {string}\n *\n * @see _mediaQueryString\n */\n get mediaQuery() {\n if (this._mediaQueryString !== \"\") {\n return this._mediaQueryString;\n }\n\n return `(width <= ${this._breakpoint})`;\n }\n\n set mediaQuery(value) {\n isValidType(\"string\", { mediaQuery: value });\n\n if (this._mediaQueryString !== value) {\n this._mediaQueryString = value;\n }\n }\n\n /**\n * The prefix used for CSS custom properties and attributes.\n *\n * @readonly\n *\n * @type {string}\n *\n * @see _prefix\n */\n get prefix() {\n return this._prefix;\n }\n\n /**\n * The key used to generate IDs throughout the component.\n *\n * @readonly\n *\n * @type {string}\n *\n * @see _key\n */\n get key() {\n return this._key;\n }\n\n /**\n * An array to hold error messages.\n *\n * @readonly\n *\n * @type {string[]}\n *\n * @see _errors\n */\n get errors() {\n return this._errors;\n }\n\n /**\n * Validates all aspects of the component to ensure proper functionality.\n *\n * Keys are altered to match the arguments passed in during creation where possible.\n *\n * @protected\n *\n * @return {boolean} - The result of the validation checks.\n */\n _validate() {\n // DOM checks.\n if (Object.keys(this._dom).length > 0) {\n const domElements = {};\n\n // Loop through and add \"Element\" to the end of each key in _dom.\n for (const domKey of Object.keys(this._dom)) {\n // If we're dealing with an array, we need to check each element in the array.\n if (Array.isArray(this._dom[domKey])) {\n this._dom[domKey].forEach((element, index) => {\n domElements[`${domKey}Element[${index}]`] = element;\n });\n }\n\n domElements[`${domKey}Element`] = this._dom[domKey];\n }\n\n // Check the DOM elements.\n const domChecks = isValidInstance(HTMLElement, domElements);\n\n // Handle DOM check failure.\n if (!domChecks) {\n this._errors.push(domChecks.message);\n this._valid = false;\n }\n }\n\n // Query selector checks.\n if (Object.keys(this._selectors).length > 0) {\n const querySelectors = {};\n\n // Loop through and add \"Selector\" to the end of each key in _selectors.\n for (const querySelector of Object.keys(this._selectors)) {\n querySelectors[`${querySelector}Selector`] =\n this._selectors[querySelector];\n }\n\n // Check the query selectors.\n const querySelectorChecks = isQuerySelector(querySelectors);\n\n // Handle query selector check failure.\n if (!querySelectorChecks) {\n this._errors.push(querySelectorChecks.message);\n this._valid = false;\n }\n }\n\n // Class list checks.\n if (Object.keys(this._classes).length > 0) {\n const classes = {};\n\n // Loop through and add \"Class\" to the end of each key in _classes.\n for (const className of Object.keys(this._classes)) {\n if (this._classes[className] === \"\") {\n continue;\n }\n\n classes[`${className}Class`] = this._classes[className];\n }\n\n // Check the class lists.\n const classListChecks = isValidClassList(classes);\n\n // Handle class list check failure.\n if (!classListChecks.status) {\n this._errors.push(classListChecks.error.message);\n this._valid = false;\n }\n }\n\n // Duration checks.\n if (Object.keys(this._durations).length > 0) {\n const durations = {};\n\n // Loop through and add \"Duration\" to the end of each key in _durations.\n for (const durationName of Object.keys(this._durations)) {\n durations[`${durationName}Duration`] = this._durations[durationName];\n }\n\n // Check the durations.\n const durationChecks = isValidType(\"number\", durations);\n\n // Handle duration check failure.\n if (!durationChecks.status) {\n this._errors.push(durationChecks.error.message);\n this._valid = false;\n }\n }\n\n // Delay checks.\n if (Object.keys(this.delays).length > 0) {\n const delays = {};\n\n // Loop through and add \"Delay\" to the end of each key in delays.\n for (const delayName of Object.keys(this.delays)) {\n delays[`${delayName}Delay`] = this.delays[delayName];\n }\n\n // Check the delays.\n const delayChecks = isValidType(\"number\", delays);\n\n // Handle delay check failure.\n if (!delayChecks.status) {\n this._errors.push(delayChecks.error.message);\n this._valid = false;\n }\n }\n\n // Key check.\n if (this._key !== \"\") {\n // Check the key.\n const keyCheck = isValidType(\"string\", { key: this._key });\n\n // Handle key check failure.\n if (!keyCheck.status) {\n this._errors.push(keyCheck.error.message);\n this._valid = false;\n }\n }\n\n // Prefix check.\n if (this._prefix !== \"\") {\n const prefixCheck = isValidType(\"string\", { prefix: this._prefix });\n\n if (!prefixCheck.status) {\n this._errors.push(prefixCheck.error.message);\n this._valid = false;\n }\n }\n\n return this._valid;\n }\n\n /**\n * Generates a key for the component.\n *\n * @param {boolean} [regenerate = false] - A flag to determine if the key should be regenerated.\n */\n _generateKey(regenerate = false) {\n if (this._key === \"\" || regenerate) {\n this._key = Math.random()\n .toString(36)\n .replace(/[^a-z]+/g, \"\")\n .substring(0, 10);\n }\n }\n\n /**\n * Sets IDs throughout the component.\n */\n _setIds() {\n // Add functionality to set IDs throughout the component.\n }\n\n /**\n * Sets ARIA attributes throughout the component.\n */\n _setAriaAttributes() {\n // Add functionality to set attributes throughout the component.\n }\n\n /**\n * Sets custom props throughout the component.\n */\n _setCustomProps() {\n // Add functionality to set custom props throughout the component.\n }\n\n /**\n * Sets DOM elements throughout the component.\n *\n * Elements listed in _protectedDOMElements cannot be set using this method.\n *\n * @protected\n *\n * @param {string} elementType - The type of element to populate.\n * @param {Object<HTMLElement,boolean>} [options = {}] - The options for setting the DOM element type.\n * @param {HTMLElement} [options.context] - The element used as the base context for the querySelector.\n * @param {boolean} [options.overwrite = true] - A flag to set if the existing elements will be overwritten.\n * @param {boolean} [options.strict = true] - A flag to set if the elements must be direct children of the base.\n */\n _setDOMElementType(\n elementType,\n { context, overwrite = true, strict = true } = {}\n ) {\n // Make sure the element type is valid.\n if (typeof this.selectors[elementType] !== \"string\") {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" is not a valid element type.`\n );\n }\n\n // Make sure the element type can actually be set through this method.\n if (this._protectedDOMElements.includes(elementType)) {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" element cannot be set through _setDOMElementType because it is a protected element.`\n );\n }\n\n // Make sure the context element is actually an HTMLELement.\n isValidInstance(HTMLElement, { context });\n\n // Get the all elements matching the selector in the context.\n const domElements = Array.from(\n context.querySelectorAll(this.selectors[elementType])\n );\n\n // Filter the elements so if `strict` is true, only direct children of the context are kept.\n const filteredElements = domElements.filter((item) =>\n strict ? item.parentElement === context : true\n );\n\n if (Array.isArray(this._dom[elementType])) {\n if (overwrite) {\n this._dom[elementType] = filteredElements;\n } else {\n this._dom[elementType] = [\n ...this._dom[elementType],\n ...filteredElements,\n ];\n }\n } else {\n this._dom[elementType] = filteredElements[0] || null;\n }\n }\n\n /**\n * Resets DOM elements throughout the component.\n *\n * Elements listed in _protectedDOMElements cannot be reset using this method.\n *\n * @protected\n *\n * @param {string} elementType - The type of element to clear.\n */\n _resetDOMElementType(elementType) {\n // Make sure the element type is valid.\n if (typeof this.selectors[elementType] !== \"string\") {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" is not a valid element type.`\n );\n }\n\n // Make sure the element type can actually be reset through this method.\n if (this._protectedDOMElements.includes(elementType)) {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${elementType}\" element cannot be reset through _resetDOMElementType because it is a protected element.`\n );\n }\n\n if (Array.isArray(this._dom[elementType])) {\n this._dom[elementType] = [];\n } else {\n this._dom[elementType] = null;\n }\n }\n\n /**\n * Sets all DOM elements throughout the component.\n *\n * Utilizes _setDOMElementType and _resetDOMElementType.\n *\n * @protected\n */\n _setDOMElements() {\n // Add functionality to set DOM Elements throughout the component.\n }\n\n /**\n * Creates and initializes child elements throughout the component.\n *\n * @protected\n */\n _createChildElements() {\n // Add functionality to handle creating child elements throughout the component.\n }\n\n /**\n * Handles media match events throughout the component.\n *\n * @protected\n */\n _handleMediaMatch() {\n if (this._breakpointWidth === \"\") {\n return;\n }\n\n this._mediaQueryList = window.matchMedia(this.mediaQuery);\n this._mediaQueryList.addEventListener(\n \"change\",\n this._mediaQueryListEventCallback\n );\n this._mediaQueryListEventCallback(this._mediaQueryList);\n }\n\n /**\n * Handles focus events through the component.\n *\n * @protected\n */\n _handleFocus() {\n // Add functionality to handle focus events throughout the component.\n }\n\n /**\n * Handles click events through the component.\n *\n * @protected\n */\n _handleClick() {\n // Add functionality to handle click events throughout the component.\n }\n\n /**\n * Handles keydown events through the component.\n *\n * @protected\n */\n _handleKeydown() {\n // Add functionality to handle keydown events throughout the component.\n }\n\n /**\n * Handles keyup events through the component.\n *\n * @protected\n */\n _handleKeyup() {\n // Add functionality to handle keyup events throughout the component.\n }\n\n /**\n * Stores the component into the global Graupl storage object.\n *\n * @protected\n */\n _store() {\n // Set up the storage.\n storage.initializeStorage(this._storageKey);\n storage.pushToStorage(\n this._storageKey,\n this._id !== \"\" ? this._id : this._key,\n this\n );\n }\n\n /**\n * Removes the component from the global Graupl storage object.\n *\n * @protected\n */\n _unstore() {\n storage.removeFromStorage(\n this._storageKey,\n this._id !== \"\" ? this._id : this._key\n );\n }\n\n /**\n * Sets an interval within the component.\n *\n * @protected\n *\n * @param {Function} [callback] - The callback function.\n * @param {number} [delay] - The time (in milliseconds) of the delay.\n * @param {string} [scope = _default] - The scope of the interval (used to store the interval in _intervals).\n */\n _setInterval(callback, delay, scope = \"_default\") {\n this._clearInterval(scope);\n\n this._intervals[scope] = setInterval(callback, delay);\n }\n\n /**\n * Clears the interval within the component.\n *\n * @protected\n *\n * @param {string} [scope = _default] - The scope of the interval (used to get the interval from _intervals).\n */\n _clearInterval(scope = \"_default\") {\n clearInterval(this._intervals[scope]);\n }\n\n /**\n * Sets a timeout within the component.\n *\n * @protected\n *\n * @param {Function} [callback] - The callback function.\n * @param {number} [delay] - The time (in milliseconds) of the delay.\n * @param {string} [scope = _default] - The scope of the timeout (used to store the timeout in _timeouts).\n */\n _setTimeout(callback, delay, scope = \"_default\") {\n this._clearTimeout(scope);\n\n this._timeouts[scope] = setTimeout(callback, delay);\n }\n\n /**\n * Clears the timeout within the component.\n *\n * @protected\n *\n * @param {string} [scope = _default] - The scope of the timeout (used to get the timeout from _timeouts).\n */\n _clearTimeout(scope = \"_default\") {\n clearTimeout(this._timeouts[scope]);\n }\n\n /**\n * Dispatch a custom event on an element in the DOM.\n *\n * @param {string} eventType - The type of the event to dispatch.\n * @param {HTMLElement} element - The element to dispatch the event on.\n */\n _dispatchEvent(eventType, element) {\n // Make sure the event type exists.\n if (!Object.keys(this.events).includes(eventType)) {\n throw new Error(\n `Graupl ${this.constructor.name}: \"${eventType}\" is not a valid event type.`\n );\n }\n\n // Make sure the element is actually an HTML Element.\n isValidInstance(HTMLElement, { element });\n\n // Dispatch the event.\n element.dispatchEvent(this.events[eventType]);\n }\n\n /**\n * Add an event listener to an element and register it within the component.\n *\n * @param {string} type - The type of event to listen for.\n * @param {HTMLElement} element - The element to add the listener to.\n * @param {Function} listener - The listener callback.\n * @param {object|boolean} [options = {}] - Options to pass to the listener.\n */\n _addEventListener(type, element, listener, options = {}) {\n // Add the listener.\n element.addEventListener(type, listener, options);\n\n // Store it in the component.\n this._listeners.push({\n type,\n element,\n listener,\n options,\n });\n }\n\n /**\n * Remove an event listener to an element and unregister it within the component.\n *\n * @param {string} type - The type of event to listen for.\n * @param {HTMLElement} element - The element to add the listener to.\n * @param {Function} listener - The listener callback.\n * @param {object|boolean} [options = {}] - Options to pass to the listener.\n */\n _removeEventListener(type, element, listener, options = {}) {\n // Remove the listener.\n element.removeEventListener(type, listener, options);\n\n // Remove it from the component storage.\n const index = this._listeners.indexOf({\n type,\n element,\n listener,\n options,\n });\n\n if (index !== -1) {\n this._listeners.splice(index);\n }\n }\n\n /**\n * Removes all event listeners registered in the component.\n *\n * @protected\n */\n _removeEventListeners() {\n this._listeners.forEach(({ type, element, listener, options }) => {\n this._removeEventListener(type, element, listener, options);\n });\n }\n\n /**\n * Disposes of the current instantiated component.\n *\n * Removes all event listeners and delete's the object.\n */\n dispose() {\n this._removeEventListeners();\n this._unstore();\n\n delete this;\n }\n}\n\nexport default Component;\n","/**\n * @file\n * The TabToggle class.\n */\n\n/* global Tabs */\n\nimport { addClass, removeClass } from \"@graupl/core/src/domHelpers.js\";\nimport { TransactionalValue } from \"../TransactionalValue.js\";\nimport Component from \"../Component.js\";\n\nclass TabToggle extends Component {\n /**\n * The DOM elements within the tab toggle.\n *\n * @protected\n *\n * @type {Object<HTMLElement>}\n *\n * @property {HTMLElement} toggle - The toggle element.\n * @property {HTMLElement} content - The content element.\n */\n _dom = {\n toggle: null,\n content: null,\n };\n\n /**\n * The DOM elements within the tab toggle that cannot be reset or generated by the tab toggle itself.\n *\n * @protected\n *\n * @type {string[]}\n */\n _protectedDOMElements = [\"toggle\", \"content\"];\n\n /**\n * The instantiated elements within the component.\n *\n * @protected\n *\n * @type {Object<Tabs>}\n *\n * @property {Tabs} parent - The parent tabs element.\n */\n _elements = {\n parent: null,\n };\n\n /**\n * The active state of the tab toggle.\n *\n * @protected\n *\n * @type {TransactionalValue}\n */\n _active = new TransactionalValue(false);\n\n /**\n * Custom events that can be triggered throughout the tab toggle.\n *\n * @protected\n *\n * @type {Object<CustomEvent>}\n */\n _events = {\n /**\n * The event that is triggered when the tab toggle is shown.\n *\n * @event grauplTabToggleActivate\n *\n * @type {CustomEvent}\n *\n * @property {boolean} bubbles - A flag to bubble the event\n * @property {Object<TabToggle>} detail - The details object containing the tab toggle itself.\n * @property {TabToggle} detail.toggle - The tab toggle.\n */\n activate: new CustomEvent(\"grauplTabToggleActivate\", {\n bubbles: true,\n detail: {\n toggle: this,\n },\n }),\n /**\n * The event that is triggered when the tab toggle is hidden.\n *\n * @event grauplTabToggleDeactivate\n *\n * @type {CustomEvent}\n *\n * @property {boolean} bubbles - A flag to bubble the event\n * @property {Object<TabToggle>} detail - The details object containing the tab toggle itself.\n * @property {TabToggle} detail.toggle - The tab toggle.\n */\n deactivate: new CustomEvent(\"grauplTabToggleDeactivate\", {\n bubbles: true,\n detail: {\n toggle: this,\n },\n }),\n };\n\n /**\n * Constructs a new TabToggle.\n *\n * @param {object} [options = {}] - The options for generating the tab toggle.\n * @param {HTMLElement} options.toggleElement - The tab toggle DOM element.\n * @param {HTMLElement} options.contentElement - The tab content DOM element.\n * @param {Tabs} options.parentTab - The Tabs element the toggle belongs to.\n */\n constructor({ toggleElement, contentElement, parentTab } = {}) {\n super({\n prefix: parentTab.prefix,\n key: parentTab.key,\n });\n\n // Set DOM elements.\n this._dom.toggle = toggleElement;\n this._dom.content = contentElement;\n\n // Set the parent tab instance.\n this._elements.parent = parentTab;\n }\n\n /**\n * Initializes the tab toggle.\n */\n initialize() {\n // Set up the DOM.\n this._setIds();\n this._setAriaAttributes();\n\n if (this.dom.toggle.getAttribute(\"aria-selected\") === \"true\") {\n this.show({ force: true, emit: false, transition: false });\n } else {\n this.hide({ force: true, emit: false, transition: false });\n }\n }\n\n /**\n * The active state of the tab toggle.\n *\n * @readonly\n *\n * @type {TransactionalValue}\n *\n * @see _active\n */\n get isActive() {\n return this._active.value;\n }\n\n /**\n * Sets the IDs of the tab toggle and it's content if they do not already exist.\n *\n * The generated IDs use the following format:\n * - toggle: `tab-toggle-${key}-${index}`\n * - content: `tab-content-${key}-${index}`\n *\n * Where `${key}` is the parent's key and `${index}` is the toggles index in the list of the parent's toggles.\n *\n * @protected\n */\n _setIds() {\n // Get the required information for IDs.\n const { key } = this.elements.parent;\n const index = this.elements.parent.dom.tabToggle.indexOf(this.dom.toggle);\n\n this.dom.toggle.id = this.dom.toggle.id || `tab-toggle-${key}-${index}`;\n this.dom.content.id = this.dom.content.id || `tab-content-${key}-${index}`;\n\n this._id = this.dom.toggle.id;\n }\n\n /**\n * Sets the ARIA attributes on the disclosure and it's content.\n */\n _setAriaAttributes() {\n // Set the ARIA attributes for the tab item toggle.\n this.dom.toggle.setAttribute(\"role\", \"tab\");\n\n // If aria-selected is not explicitly set to \"true\", then set it to \"false\".\n if (this.dom.toggle.getAttribute(\"aria-selected\") !== \"true\") {\n this.dom.toggle.setAttribute(\"aria-selected\", \"false\");\n }\n\n // Set the aria-controls attribute for the toggle.\n this.dom.toggle.setAttribute(\"aria-controls\", this.dom.content.id);\n\n // Set the role for the content.\n this.dom.content.setAttribute(\"role\", \"tabpanel\");\n }\n\n /**\n * Reveal the toggle.\n *\n * Sets the toggle's `aria-selected` to \"true\", adds the\n * open class to the content, and removes the closed class from the content.\n *\n * @protected\n *\n * @fires grauplTabToggleActivate\n *\n * @param {Object<boolean>} [options = {}] - Options for revealing the toggle.\n * @param {boolean} [options.emit = true] - Emit the activate event once revealed.\n * @param {boolean} [options.transition = true] - Respect the transition class.\n */\n _reveal({ emit = true, transition = true } = {}) {\n const { closeClass, openClass, transitionClass, openDuration } =\n this.elements.parent;\n\n // Set aria-selected to true when hiding accordion item.\n this.dom.toggle.setAttribute(\"aria-selected\", \"true\");\n\n // If we're dealing with transition classes, then we need to utilize\n // requestAnimationFrame to add the transition class, remove the hide class,\n // add the show class, and finally remove the transition class.\n //\n // If `transition` is false, then it doesn't matter if the transition class\n // is set. Do not use the transition.\n if (transition && transitionClass !== \"\") {\n addClass(transitionClass, this.dom.content);\n\n requestAnimationFrame(() => {\n removeClass(closeClass, this.dom.content);\n\n requestAnimationFrame(() => {\n addClass(openClass, this.dom.content);\n\n requestAnimationFrame(() => {\n this._setTimeout(\n () => removeClass(transitionClass, this.dom.content),\n openDuration\n );\n });\n });\n });\n } else {\n // Add the show class\n addClass(openClass, this.dom.content);\n\n // Remove the hide class.\n removeClass(closeClass, this.dom.content);\n }\n\n if (emit) {\n this._dispatchEvent(\"activate\", this.dom.toggle);\n }\n }\n\n /**\n * Conseals the toggle.\n *\n * Sets the toggle's `aria-expanded` to \"false\", adds the\n * close class to the content, and removes the open class from the content.\n *\n * @protected\n *\n * @fires grauplTabToggleDeactivate\n *\n * @param {Object<boolean>} [options = {}] - Options for concealing the toggle.\n * @param {boolean} [options.emit = true] - Emit the deactivate event once concealed.\n * @param {boolean} [options.transition = true] - Respect the transition class.\n */\n _conceal({ emit = true, transition = true } = {}) {\n const { closeClass, openClass, transitionClass, closeDuration } =\n this.elements.parent;\n\n // Set aria-selected to false when hiding accordion item.\n this.dom.toggle.setAttribute(\"aria-selected\", \"false\");\n\n // If we're dealing with transition classes, then we need to utilize\n // requestAnimationFrame to add the transition class, remove the show class,\n // add the hide class, and finally remove the transition class.\n //\n // If `transition` is false, then it doesn't matter if the transition class\n // is set. Do not use the transition.\n if (transition && transitionClass !== \"\") {\n addClass(transitionClass, this.dom.content);\n\n requestAnimationFrame(() => {\n removeClass(openClass, this.dom.content);\n\n requestAnimationFrame(() => {\n addClass(closeClass, this.dom.content);\n\n requestAnimationFrame(() => {\n this._setTimeout(\n () => removeClass(transitionClass, this.dom.content),\n closeDuration\n );\n });\n });\n });\n } else {\n // Add the hide class\n addClass(closeClass, this.dom.content);\n\n // Remove the show class.\n removeClass(openClass, this.dom.content);\n }\n\n if (emit) {\n this._dispatchEvent(\"deactivate\", this.dom.toggle);\n }\n }\n\n /**\n * Shows the tab toggle's content.\n *\n * @param {Object<boolean>} [options = {}] - The options for showing the tab toggle.\n * @param {boolean} [options.force = false] - Whether to force the open action.\n * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.\n * @param {boolean} [options.emit = true] - Emit the deactivate event once revealed.\n * @param {boolean} [options.transition = true] - Respect the transition class.\n */\n show({\n force = false,\n preserveState = false,\n emit = true,\n transition = true,\n } = {}) {\n if (this.isActive && !force) return;\n\n // Set the focus state of the parent tabs element.\n this.elements.parent.focusState = \"self\";\n\n // Reveal the toggle.\n this._reveal({ emit, transition });\n\n // Set the active state\n this._active.value = true;\n\n if (!preserveState) {\n this._active.commit();\n }\n\n // Set the tabindex to 0 so it can be focused.\n this.dom.toggle.setAttribute(\"tabindex\", \"0\");\n\n // Hide all sibling tab toggles.\n this.hideSiblings();\n }\n\n /**\n * Hides the tab toggle's content.\n *\n * @param {Object<boolean>} [options = {}] - The options for hiding the tab toggle.\n * @param {boolean} [options.force = false] - Whether to force the hide action.\n * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.\n * @param {boolean} [options.emit = true] - Emit the deactivate event once consealed.\n * @param {boolean} [options.transition = true] - Respect the transition class.\n */\n hide({\n force = false,\n preserveState = false,\n emit = true,\n transition = true,\n } = {}) {\n if (!this.isActive && !force) return;\n\n // Set the focus state of the parent tabs element.\n this.elements.parent.focusState = \"none\";\n\n // Conceal the toggle.\n this._conceal({ emit, transition });\n\n // Set the active state\n this._active.value = false;\n\n if (!preserveState) {\n this._active.commit();\n }\n\n // Set the tabindex to -1.\n this.dom.toggle.setAttribute(\"tabindex\", \"-1\");\n }\n\n /**\n * Focuses the accordion item.\n */\n focus() {\n this.dom.toggle.focus();\n }\n\n /**\n * Blurs the accordion item.\n */\n blur() {\n this.dom.toggle.blur();\n }\n\n /**\n * Hides all sibling toggles within the same Tabs element.\n */\n hideSiblings() {\n if (this.elements.parent) {\n this.elements.parent.elements.tabToggle.forEach((toggle) => {\n if (toggle !== this) {\n toggle.hide();\n }\n });\n }\n }\n}\n\nexport default TabToggle;\n","/**\n * Retrieves the pressed key from an event.\n *\n * @param {KeyboardEvent} event - The keyboard event.\n * @return {string} - The name of the key or an empty string.\n */\nexport function keyPress(event) {\n try {\n // Use event.key or event.keyCode to support older browsers.\n const key = event.key || event.keyCode;\n const keys = {\n Enter: key === \"Enter\" || key === 13,\n Space: key === \" \" || key === \"Spacebar\" || key === 32,\n Escape: key === \"Escape\" || key === \"Esc\" || key === 27,\n ArrowUp: key === \"ArrowUp\" || key === \"Up\" || key === 38,\n ArrowRight: key === \"ArrowRight\" || key === \"Right\" || key === 39,\n ArrowDown: key === \"ArrowDown\" || key === \"Down\" || key === 40,\n ArrowLeft: key === \"ArrowLeft\" || key === \"Left\" || key === 37,\n Home: key === \"Home\" || key === 36,\n End: key === \"End\" || key === 35,\n Tab: key === \"Tab\" || key === 9,\n };\n\n return Object.keys(keys).find((key) => keys[key] === true) || \"\";\n } catch {\n // Return an empty string if something goes wrong.\n return \"\";\n }\n}\n\n/**\n * Stops an event from taking action.\n *\n * @param {Event} event - The event.\n */\nexport function preventEvent(event) {\n event.preventDefault();\n event.stopPropagation();\n}\n","/**\n * @file\n * The Tabs class.\n */\n\nimport TabToggle from \"./TabToggle.js\";\nimport { isValidType, isValidClassList } from \"../validate.js\";\nimport { addClass, removeClass } from \"../domHelpers.js\";\nimport { keyPress, preventEvent } from \"../eventHandlers.js\";\nimport Component from \"../Component.js\";\n\nclass Tabs extends Component {\n /**\n * The DOM elements within the tabs.\n *\n * @protected\n *\n * @type {Object<HTMLElement, HTMLElement[]>}\n *\n * @property {HTMLElement} tabs - The tabs element.\n * @property {HTMLElement} tabList - The tab list element.\n * @property {HTMLElement[]} tabToggle - An array of tab item toggles.\n * @property {HTMLElement[]} tabContent - An array of tab item contents.\n */\n _dom = {\n tabs: null,\n tabList: null,\n tabToggle: [],\n tabContent: [],\n };\n\n /**\n * The DOM elements within the tabs that cannot be reset or generated by the tabs itself.\n *\n * @protected\n *\n * @type {string[]}\n */\n _protectedDOMElements = [\"tab\"];\n\n /**\n * The query selectors used by the tabs.\n *\n * @protected\n *\n * @type {Object<string>}\n *\n * @property {string} tabList - The query selector for the tab list.\n * @property {string} tabToggle - The query selector for tab toggles.\n * @property {string} tabContent - The query selector for tab contents.\n */\n _selectors = {\n tabList: \"\",\n tabToggle: \"\",\n tabContent: \"\",\n };\n\n /**\n * The instantiated elements within the tabs.\n *\n * @protected\n *\n * @type {Object<TabToggle[]>}\n *\n * @property {TabToggle[]} tabToggle - The list of tab items.\n */\n _elements = {\n tabToggle: [],\n };\n\n /**\n * The CSS classes to apply when the tabs is in various states.\n *\n * @protected\n *\n * @type {Object<string, string[]>}\n *\n * @property {string|string[]} open - The class(es) to apply when the tab is open.\n * @property {string|string[]} close - The class(es) to apply when the tab is closed.\n * @property {string|string[]} transition - The class(es) to apply when the tab is transitioning between states.\n * @property {string|string[]} initialize - The class(es) to apply when the tab is initializing.\n */\n _classes = {\n open: \"show\",\n close: \"hide\",\n transition: \"transitioning\",\n initialize: \"initializing\",\n };\n\n /**\n * The duration times (in milliseconds) for variouse aspects throughout the tabs.\n *\n * @protected\n *\n * @type {Object<number>}\n *\n * @property {number} transition - The duration time (in milliseconds) for the transition between open and closed states.\n * @property {number} open - The duration time (in milliseconds) for the transition from closed to open states.\n * @property {number} close - The duration time (in milliseconds) for the transition from open to closed states.\n */\n _durations = {\n transition: 250,\n open: -1,\n close: -1,\n };\n\n /**\n * A flag to set if focusing a tab item toggle will automatically activate it.\n *\n * @protected\n *\n * @type {boolean}\n */\n _automatic = false;\n\n /**\n * The index of the current child node.\n *\n * @protected\n *\n * @type {number}\n */\n _currentChild = 0;\n\n /**\n * The key used for storage.\n *\n * @protected\n *\n * @type {string}\n */\n _storageKey = \"tabs\";\n\n /**\n * Constructs a new `Tab`.\n *\n * @param {object} options - The options for generating the tab.\n * @param {HTMLElement} [options.tabsElement] - The tab element in the DOM.\n * @param {string} [options.tabListSelector = .tab-list] - The query selector string for the tab list.\n * @param {string} [options.tabToggleSelector = .tab-toggle] - The query selector string for tab toggle.\n * @param {string} [options.tabContentSelector = .tab-content] - The query selector string for tab content.\n * @param {?(string|string[])} [options.openClass = show] - The class to apply when a tab is \"open\".\n * @param {?(string|string[])} [options.closeClass = hide] - The class to apply when a tab is \"closed\".\n * @param {?(string|string[])} [options.transitionClass = null] - The class to apply when a tab is transitioning between \"open\" and \"closed\" states.\n * @param {number} [options.transitionDuration = 300] - The duration of the transition between \"open\" and \"closed\" states (in milliseconds).\n * @param {number} [options.openDuration = -1] - The duration of the transition from \"closed\" to \"open\" states (in milliseconds).\n * @param {number} [options.closeDuration = -1] - The duration of the transition from \"open\" to \"closed\" states (in milliseconds).\n * @param {boolean} [options.automaticActivation = false] - A flag to set if focusing a tab item toggle will automatically activate it.\n * @param {?string} [options.prefix = graupl-] - The prefix to use for CSS custom properties.\n * @param {?string} [options.key = null] - The key used to generate IDs throughout the tab.\n * @param {?(string|string[])} [options.initializeClass = initializing] - The class to apply when a tabs are initialzing.\n * @param {boolean} [options.initialize = false] - A flag to initialize the tab immediately upon creation.\n */\n constructor({\n tabsElement,\n tabListSelector = \".tab-list\",\n tabToggleSelector = \".tab-toggle\",\n tabContentSelector = \".tab-content\",\n openClass = \"show\",\n closeClass = \"hide\",\n transitionClass = null,\n transitionDuration = 300,\n openDuration = -1,\n closeDuration = -1,\n automaticActivation = false,\n prefix = \"graupl-\",\n key = null,\n initializeClass = \"initializing\",\n initialize = false,\n }) {\n super({\n prefix,\n key,\n initializeClass,\n });\n\n // Set DOM elements.\n this._dom.tabs = tabsElement;\n\n // Set DOM selectors.\n this._selectors.tabList = tabListSelector;\n this._selectors.tabToggle = tabToggleSelector;\n this._selectors.tabContent = tabContentSelector;\n\n // Set open/close classes.\n this._classes.open = openClass || \"\";\n this._classes.close = closeClass || \"\";\n this._classes.transition = transitionClass || \"\";\n\n // Set transition duration.\n this._durations.transition = transitionDuration;\n this._durations.open = openDuration;\n this._durations.close = closeDuration;\n\n // Set automatic activation.\n this._automatic = automaticActivation;\n\n if (initialize) {\n this.initialize();\n }\n }\n\n /**\n * Initializes the tabs.\n */\n initialize() {\n try {\n // Add the initialization class.\n addClass(this.initializeClass, this.dom.tabs);\n\n super.initialize();\n\n // Set up the DOM.\n this._setDOMElements();\n this._setIds();\n this._setAriaAttributes();\n this._setCustomProps();\n\n // Create the child elements.\n this._createChildElements();\n\n // Handle events.\n this._handleFocus();\n this._handleClick();\n this._handleKeydown();\n this._handleKeyup();\n\n // Store the component.\n this._store();\n\n // Make sure the first tab is open if no other tab is active.\n if (\n this.elements.tabToggle.filter((toggle) => toggle.isActive).length === 0\n ) {\n this.elements.tabToggle[0].show();\n }\n } catch (error) {\n console.error(error);\n } finally {\n // Remove the initialization class.\n requestAnimationFrame(() => {\n removeClass(this.initializeClass, this.dom.tabs);\n });\n }\n }\n\n /**\n * The class(es) to apply when the tab is open.\n *\n * @type {string|string[]}\n *\n * @see _classes.open\n */\n get openClass() {\n return this._classes.open;\n }\n\n set openClass(value) {\n isValidClassList({ openClass: value });\n\n if (this._classes.open !== value) {\n this._classes.open = value;\n }\n }\n\n /**\n * The class(es) to apply when the tab is closed.\n *\n * @type {string|string[]}\n *\n * @see _classes.close\n */\n get closeClass() {\n return this._classes.close;\n }\n\n set closeClass(value) {\n isValidClassList({ closeClass: value });\n\n if (this._classes.close !== value) {\n this._classes.close = value;\n }\n }\n\n /**\n * The class(es) to apply when the tab is transitioning between open and closed.\n *\n * @type {string|string[]}\n *\n * @see _classes.transition\n */\n get transitionClass() {\n return this._classes.transition;\n }\n\n set transitionClass(value) {\n isValidClassList({ transitionClass: value });\n\n if (this._classes.transition !== value) {\n this._classes.transition = value;\n }\n }\n\n /**\n * The duration time (in milliseconds) for the transition between open and closed states.\n *\n * @type {number}\n *\n * @see _durations.transition\n */\n get transitionDuration() {\n return this._durations.transition;\n }\n\n set transitionDuration(value) {\n isValidType(\"number\", { transitionDuration: value });\n\n if (this._durations.transition !== value) {\n this._durations.transition = value;\n this._setTransitionDurations();\n }\n }\n\n /**\n * The duration time (in milliseconds) for the transition from closed to open states.\n *\n * If openDuration is set to -1, the transitionDuration will be used instead.\n *\n * @type {number}\n *\n * @see _durations.open\n */\n get openDuration() {\n return this._durations.open === -1\n ? this.transitionDuration\n : this._durations.open;\n }\n\n set openDuration(value) {\n isValidType(\"number\", { openDuration: value });\n\n if (this._durations.open !== value) {\n this._durations.open = value;\n this._setTransitionDurations();\n }\n }\n\n /**\n * The duration time (in milliseconds) for the transition from open to closed states.\n *\n * If closeDuration is set to -1, the transitionDuration will be used instead.\n *\n * @type {number}\n *\n * @see _durations.close\n */\n get closeDuration() {\n return this._durations.close === -1\n ? this.transitionDuration\n : this._durations.close;\n }\n\n set closeDuration(value) {\n isValidType(\"number\", { closeDuration: value });\n\n if (this._durations.close !== value) {\n this._durations.close = value;\n this._setTransitionDurations();\n }\n }\n\n /**\n * A flag to set if focusing a tab item toggle will automatically activate it.\n *\n * @type {boolean}\n *\n * @see _automatic\n */\n get isAutomatic() {\n return this._automatic;\n }\n\n set isAutomatic(value) {\n isValidType(\"boolean\", { isAutomatic: value });\n\n if (this._automatic !== value) {\n this._automatic = value;\n }\n }\n\n /**\n * The current index of the tab item.\n *\n * @readonly\n *\n * @type {number}\n *\n * @see _currentChild\n */\n get currentChild() {\n return this._currentChild;\n }\n\n set currentChild(value) {\n isValidType(\"number\", { currentChild: value });\n\n if (\n this._currentChild !== value &&\n value >= 0 &&\n value < this.elements.tabToggle.length\n ) {\n this._currentChild = value;\n }\n }\n /**\n * The currently selected tab item.\n *\n * @readonly\n *\n * @type {TabToggle}\n */\n get currentTabToggle() {\n return this.elements.tabToggle[this.currentChild];\n }\n\n /**\n * Validates all aspects of the tabs to ensure proper functionality.\n *\n * Keys are altered to match the arguments passed in during creation where possible.\n *\n * @protected\n *\n * @return {boolean} - The result of the validation.\n */\n _validate() {\n super._validate();\n\n // Boolean checks.\n const booleans = {\n automaticActivation: this._automatic,\n };\n\n // Check the booleans.\n const booleanChecks = isValidType(\"boolean\", booleans);\n\n // Handle boolean check failure.\n if (!booleanChecks) {\n this._errors.push(booleanChecks.message);\n this._valid = false;\n }\n\n return this._valid;\n }\n\n /**\n * Sets the IDs throughout the tabs.\n *\n * The generated IDs use the key and follow the format:\n * - tabs: `tabs-${key}`\n * - tab-list: `tab-list-${key}`\n *\n * @protected\n */\n _setIds() {\n this.dom.tabs.id = this.dom.tabs.id || `tabs-${this.key}`;\n this.dom.tabList.id = this.dom.tabList.id || `tab-list-${this.key}`;\n\n this._id = this.dom.tabs.id;\n }\n\n /**\n * Sets ARIA attributes throughout the tabs.\n *\n * @protected\n */\n _setAriaAttributes() {\n this.dom.tabList.setAttribute(\"role\", \"tablist\");\n }\n\n /**\n * Sets custom props throughout the tabs.\n *\n * The custom properties are:\n * - `--graupl-tabs-transition-duration`,\n * - `--graupl-tabs-open-transition-duration`, and\n * - `--graupl-tabs-close-transition-duration`.\n *\n * The prefix of `graupl-` can be changed by setting the tab's prefix value.\n *\n * @protected\n */\n _setCustomProps() {\n this.dom.tabs.style.setProperty(\n `--${this.prefix}tabs-transition-duration`,\n `${this.transitionDuration}ms`\n );\n\n this.dom.tabs.style.setProperty(\n `--${this.prefix}tabs-open-transition-duration`,\n `${this.openDuration}ms`\n );\n\n this.dom.tabs.style.setProperty(\n `--${this.prefix}tabs-close-transition-duration`,\n `${this.closeDuration}ms`\n );\n }\n\n /**\n * Sets all DOM elements within the tabs.\n *\n * Utilizes _setDOMElementType and\n * _resetDOMElementType.\n *\n * @protected\n */\n _setDOMElements() {\n this._resetDOMElementType(\"tabList\");\n this._setDOMElementType(\"tabList\", { context: this.dom.tabs });\n\n if (this.dom.tabList) {\n this._resetDOMElementType(\"tabToggle\");\n this._setDOMElementType(\"tabToggle\", { context: this.dom.tabList });\n }\n\n this._resetDOMElementType(\"tabContent\");\n this._setDOMElementType(\"tabContent\", { context: this.dom.tabs });\n }\n\n /**\n * Creates and initializes all tab toggles.\n *\n * @protected\n */\n _createChildElements() {\n this.dom.tabToggle.forEach((tabToggle, index) => {\n const toggle = new TabToggle({\n toggleElement: tabToggle,\n contentElement: this.dom.tabContent[index],\n parentTab: this,\n });\n\n toggle.initialize();\n\n this._elements.tabToggle.push(toggle);\n });\n }\n\n /**\n * Handles focus events throughout the tab for proper use.\n *\n * - Adds a `focus` listener to every tab item so when it gains focus,\n * it will set the tab's current child to the index of the item.\n *\n * @protected\n */\n _handleFocus() {\n this.elements.tabToggle.forEach((toggle, index) => {\n this._addEventListener(\"focus\", toggle.dom.toggle, () => {\n this.currentChild = index;\n\n if (this.isAutomatic) {\n this.currentTabToggle.show();\n }\n });\n });\n }\n\n /**\n * Handles click events throughout the tab item for proper use.\n *\n * - Adds a `pointerup` listener to the tab item toggles that will toggle each tab item.\n *\n * @protected\n */\n _handleClick() {\n this.elements.tabToggle.forEach((toggle, index) => {\n this._addEventListener(\"pointerup\", toggle.dom.toggle, () => {\n this.currentChild = index;\n toggle.show();\n });\n });\n }\n\n /**\n * Handles keydown events throughout the tab item for proper use.\n *\n * This method exists to assist the _handleKeyup method.\n *\n * - Adds a `keydown` listener to all tab item toggles.\n * - Blocks propagation on \"Space\", \"Enter\", \"ArrowRight\", \"ArrowLeft\", \"Home\", and \"End\" keys.\n */\n _handleKeydown() {\n this.dom.tabToggle.forEach((tabToggle) => {\n this._addEventListener(\"keydown\", tabToggle, (event) => {\n const key = keyPress(event);\n const ToggleKeys = [\n \"Space\",\n \"Enter\",\n \"ArrowRight\",\n \"ArrowLeft\",\n \"Home\",\n \"End\",\n ];\n\n // Prevent default behavior for space and enter keys.\n if (ToggleKeys.includes(key)) {\n preventEvent(event);\n }\n });\n });\n }\n\n /**\n * Handles keyup events throughout the tab item for proper use.\n *\n * Adds the follow keybindings (explanations are taken from the WAI ARIA Practices Guide Tab Pattern):\n *\n * - `Enter` or `Space`:\n * - When focus is on the tab link for a collapsed panel, expands the associated panel. If the implementation allows only one panel to be expanded, and if another panel is expanded, collapses that panel.\n * - When focus is on the tab link for an expanded panel, collapses the panel if the implementation supports collapsing. Some implementations require one panel to be expanded at all times and allow only one panel to be expanded; so, they do not support a collapse function.\n * - `Tab`: Moves focus to the next focusable element; all focusable elements in the tab are included in the page `Tab` sequence.\n * - `Shift + Tab`: Moves focus to the previous focusable element; all focusable elements in the tab are included in the page `Tab` sequence.\n * - `Down Arrow` (Optional): If focus is on an tab link, moves focus to the next tab link. If focus is on the last tab link, either does nothing or moves focus to the first tab link.\n * - `Up Arrow` (Optional): If focus is on an tab link, moves focus to the previous tab link. If focus is on the first tab link, either does nothing or moves focus to the last tab link.\n * - `Home` (Optional): When focus is on an tab link, moves focus to the first tab link.\n * - `End` (Optional): When focus is on an tab link, moves focus to the last tab link.\n *\n * Note: When the above explanations mention \"tab link\", they are referring to the tab item toggle.\n */\n _handleKeyup() {\n this.dom.tabToggle.forEach((tabToggle) => {\n this._addEventListener(\"keyup\", tabToggle, (event) => {\n const key = keyPress(event);\n\n switch (key) {\n case \"Space\":\n case \"Enter\":\n preventEvent(event);\n this.currentTabToggle.show();\n\n break;\n case \"Home\":\n preventEvent(event);\n this.focusFirstChild();\n\n break;\n case \"End\":\n preventEvent(event);\n this.focusLastChild();\n\n break;\n case \"ArrowRight\":\n preventEvent(event);\n this.focusNextChild();\n\n break;\n case \"ArrowLeft\":\n preventEvent(event);\n this.focusPreviousChild();\n\n break;\n }\n });\n });\n }\n\n /**\n * Focus the tab's current child.\n */\n focusCurrentChild() {\n if (this.currentChild !== -1) {\n this.currentTabToggle.focus();\n }\n }\n\n /**\n * Focuses the tab's child at a given index.\n *\n * @param {number} index - The index of the child to focus.\n */\n focusChild(index) {\n this.blurCurrentChild();\n this.currentChild = index;\n this.focusCurrentChild();\n }\n\n /**\n * Focuses the tab's first child.\n */\n focusFirstChild() {\n this.focusChild(0);\n }\n\n /**\n * Focus the tab's last child.\n */\n focusLastChild() {\n this.focusChild(this.elements.tabToggle.length - 1);\n }\n\n /**\n * Focus the tab's next child.\n */\n focusNextChild() {\n if (this.currentChild < this.elements.tabToggle.length - 1) {\n this.focusChild(this.currentChild + 1);\n } else {\n this.focusFirstChild();\n }\n }\n\n /**\n * Focus the tab's previous child.\n */\n focusPreviousChild() {\n if (this.currentChild > 0) {\n this.focusChild(this.currentChild - 1);\n } else {\n this.focusLastChild();\n }\n }\n\n /**\n * Blurs the tab's current child.\n */\n blurCurrentChild() {\n if (this.currentChild !== -1) {\n this.currentTabToggle.blur();\n }\n }\n}\n\nexport default Tabs;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- function h(t,e){t===""||t.length===0||(typeof t=="string"?e.classList.add(t):e.classList.add(...t))}function l(t,e){t===""||t.length===0||(typeof t=="string"?e.classList.remove(t):e.classList.remove(...t))}var A=class{constructor(t,e={}){this._equals=e.equals||Object.is,this._current=t,this._committed=t}get value(){return this._current}set value(t){this._current=t}get committed(){return this._committed}get isDirty(){return!this._equals(this._current,this._committed)}commit(){return this._committed=this._current,this}reset(){return this._current=this._committed,this}update(t){return this._current=t(this._current),this}},k=class{_dom={toggle:null,content:null};_elements={parent:null};_active=new A(!1);_activateEvent=new CustomEvent("grauplTabToggleActivate",{bubbles:!0,detail:{item:this}});_deactivateEvent=new CustomEvent("grauplTabToggleDeactivate",{bubbles:!0,detail:{item:this}});constructor({toggleElement:t,contentElement:e,parentTab:s}){this._dom.toggle=t,this._dom.content=e,this._elements.parent=s}initialize(){this._setIds(),this._setAriaAttributes(),this.dom.toggle.getAttribute("aria-selected")==="true"?this.show():this._deactivate({emit:!1,transition:!1})}get dom(){return this._dom}get elements(){return this._elements}get isActive(){return this._active.value}_setIds(){const{key:t}=this.elements.parent,e=this.elements.parent.dom.tabToggle.indexOf(this.dom.toggle);this.dom.toggle.id=this.dom.toggle.id||`tab-toggle-${t}-${e}`,this.dom.content.id=this.dom.content.id||`tab-content-${t}-${e}`}_setAriaAttributes(){this.dom.toggle.setAttribute("role","tab"),this.dom.toggle.getAttribute("aria-selected")!=="true"&&this.dom.toggle.setAttribute("aria-selected","false"),this.dom.toggle.setAttribute("aria-controls",this.dom.content.id),this.dom.content.setAttribute("role","tabpanel")}_activate({emit:t=!0,transition:e=!0}={}){const{closeClass:s,openClass:i,transitionClass:o,openDuration:a}=this.elements.parent;this.dom.toggle.setAttribute("aria-selected","true"),e&&o!==""?(h(o,this.dom.content),requestAnimationFrame(()=>{l(s,this.dom.content),requestAnimationFrame(()=>{h(i,this.dom.content),requestAnimationFrame(()=>{setTimeout(()=>{l(o,this.dom.content)},a)})})})):(h(i,this.dom.content),l(s,this.dom.content)),t&&this.dom.toggle.dispatchEvent(this._activateEvent)}_deactivate({emit:t=!0,transition:e=!0}={}){const{closeClass:s,openClass:i,transitionClass:o,closeDuration:a}=this.elements.parent;this.dom.toggle.setAttribute("aria-selected","false"),e&&o!==""?(h(o,this.dom.content),requestAnimationFrame(()=>{l(i,this.dom.content),requestAnimationFrame(()=>{h(s,this.dom.content),requestAnimationFrame(()=>{setTimeout(()=>{l(o,this.dom.content)},a)})})})):(h(s,this.dom.content),l(i,this.dom.content)),t&&this.dom.toggle.dispatchEvent(this._deactivateEvent)}show({force:t=!1,preserveState:e=!1}={}){this.isActive&&!t||(this.elements.parent.focusState="self",this._activate(),this._active.value=!0,e||this._active.commit(),this.dom.toggle.setAttribute("tabindex","0"),this.deactivateSiblings())}hide({force:t=!1,preserveState:e=!1}={}){!this.isActive&&!t||(this.elements.parent.focusState="none",this._deactivate(),this._active.value=!1,e||this._active.commit(),this.dom.toggle.setAttribute("tabindex","-1"))}focus(){this.dom.toggle.focus()}blur(){this.dom.toggle.blur()}deactivateSiblings(){this.elements.parent&&this.elements.parent.elements.tabToggle.forEach(t=>{t!==this&&t.hide()})}},$=k;function _(t,e){try{if(typeof e!="object"){const s=typeof e;throw new TypeError(`Elements given to isValidInstance() must be inside of an object. "${s}" given.`)}for(const s in e)if(!(e[s]instanceof t)){const i=typeof e[s];throw new TypeError(`${s} must be an instance of ${t.name}. "${i}" given.`)}return{status:!0,error:null}}catch(s){return{status:!1,error:s}}}function r(t,e){try{if(typeof e!="object"){const s=typeof e;throw new TypeError(`Values given to isValidType() must be inside of an object. "${s}" given.`)}for(const s in e){const i=typeof e[s];if(i!==t)throw new TypeError(`${s} must be a ${t}. "${i}" given.`)}return{status:!0,error:null}}catch(s){return{status:!1,error:s}}}function b(t){try{if(typeof t!="object"){const e=typeof t;throw new TypeError(`Values given to isQuerySelector() must be inside of an object. "${e}" given.`)}for(const e in t)try{if(t[e]===null)throw new Error;document.querySelector(t[e])}catch{throw new TypeError(`${e} must be a valid query selector. "${t[e]}" given.`)}return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function m(t){try{if(typeof t!="object"||Array.isArray(t)){const e=typeof t;throw new TypeError(`Values given to isValidClassList() must be inside of an object. "${e}" given.`)}for(const e in t){const s=typeof t[e];if(s!=="string")if(Array.isArray(t[e]))t[e].forEach(i=>{if(typeof i!="string")throw new TypeError(`${e} must be a string or an array of strings. An array containing non-strings given.`)});else throw new TypeError(`${e} must be a string or an array of strings. "${s}" given.`);else{const i={};i[e]=t[e],b(i)}}return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function v(t){try{if(typeof t!="object"){const s=typeof t;throw new TypeError(`Values given to isValidState() must be inside of an object. "${s}" given.`)}const e=["none","self","child"];for(const s in t)if(!e.includes(t[s]))throw new TypeError(`${s} must be one of the following values: ${e.join(", ")}. "${t[s]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function D(t){try{if(typeof t!="object"){const s=typeof t;throw new TypeError(`Values given to isValidEvent() must be inside of an object. "${s}" given.`)}const e=["none","mouse","keyboard","character"];for(const s in t)if(!e.includes(t[s]))throw new TypeError(`${s} must be one of the following values: ${e.join(", ")}. "${t[s]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function p(t){try{const e=t.key||t.keyCode,s={Enter:e==="Enter"||e===13,Space:e===" "||e==="Spacebar"||e===32,Escape:e==="Escape"||e==="Esc"||e===27,ArrowUp:e==="ArrowUp"||e==="Up"||e===38,ArrowRight:e==="ArrowRight"||e==="Right"||e===39,ArrowDown:e==="ArrowDown"||e==="Down"||e===40,ArrowLeft:e==="ArrowLeft"||e==="Left"||e===37,Home:e==="Home"||e===36,End:e==="End"||e===35,Tab:e==="Tab"||e===9};return Object.keys(s).find(i=>s[i]===!0)||""}catch{return""}}function c(t){t.preventDefault(),t.stopPropagation()}function S(t=null){window.Graupl=window.Graupl||{},r("string",{type:t})&&(window.Graupl[t]=window.Graupl[t]||{})}function L(t=null){return r("string",{type:t})?window.Graupl[t]:window.Graupl}function j(t,e={}){r("string",{type:t})&&r("object",{data:e})&&(window.Graupl[t]=e)}function x(t){r("string",{type:t})&&(window.Graupl[t]={})}function O(t,e,s){r("string",{type:t,key:e})&&(window.Graupl[t][e]=s)}function q(t,e){return r("string",{type:t,key:e})?window.Graupl[t][e]:null}function G(t,e){r("string",{type:t,key:e})&&delete window.Graupl[t][e]}var y={initializeStorage:S,getStorage:L,setStorage:j,clearStorage:x,pushToStorage:O,getFromStorage:q,removeFromStorage:G},M=class{_dom={tabs:null,tabList:null,tabToggle:[],tabContent:[]};_domLock=["tab"];_selectors={tabList:"",tabToggle:"",tabContent:""};_elements={tabToggle:[]};_classes={open:"show",close:"hide",transition:"transitioning",initialize:"initializing"};_durations={transition:250,open:-1,close:-1};_focusState="none";_currentEvent="none";_automatic=!1;_currentChild=0;_prefix="graupl-";_key="";_errors=[];constructor({tabsElement:t,tabListSelector:e=".tab-list",tabToggleSelector:s=".tab-toggle",tabContentSelector:i=".tab-content",openClass:o="show",closeClass:a="hide",transitionClass:u=null,transitionDuration:d=300,openDuration:f=-1,closeDuration:g=-1,automaticActivation:n=!1,prefix:w="graupl-",key:E=null,initializeClass:C="initializing",initialize:T=!1}){this._dom.tabs=t,this._selectors.tabList=e,this._selectors.tabToggle=s,this._selectors.tabContent=i,this._classes.open=o||"",this._classes.close=a||"",this._classes.transition=u||"",this._classes.initialize=C||"",this._durations.transition=d,this._durations.open=f,this._durations.close=g,this._automatic=n,this._prefix=w||"",this._key=E||"",T&&this.initialize()}initialize(){try{if(!this._validate())throw new Error(`Graupl Tab: cannot initialize tab. The following errors have been found:
1
+ function a(t,e){t===""||t.length===0||(typeof t=="string"?e.classList.add(t):e.classList.add(...t))}function h(t,e){t===""||t.length===0||(typeof t=="string"?e.classList.remove(t):e.classList.remove(...t))}var k=class{constructor(t,e={}){this._equals=e.equals||Object.is,this._current=t,this._committed=t}get value(){return this._current}set value(t){this._current=t}get committed(){return this._committed}get isDirty(){return!this._equals(this._current,this._committed)}commit(){return this._committed=this._current,this}reset(){return this._current=this._committed,this}update(t){return this._current=t(this._current),this}};function u(t,e){try{if(typeof e!="object"){const s=typeof e;throw new TypeError(`Elements given to isValidInstance() must be inside of an object. "${s}" given.`)}for(const s in e)if(!(e[s]instanceof t)){const i=typeof e[s];throw new TypeError(`${s} must be an instance of ${t.name}. "${i}" given.`)}return{status:!0,error:null}}catch(s){return{status:!1,error:s}}}function r(t,e){try{if(typeof e!="object"){const s=typeof e;throw new TypeError(`Values given to isValidType() must be inside of an object. "${s}" given.`)}for(const s in e){const i=typeof e[s];if(i!==t)throw new TypeError(`${s} must be a ${t}. "${i}" given.`)}return{status:!0,error:null}}catch(s){return{status:!1,error:s}}}function _(t){try{if(typeof t!="object"){const e=typeof t;throw new TypeError(`Values given to isQuerySelector() must be inside of an object. "${e}" given.`)}for(const e in t)try{if(t[e]===null)throw new Error;document.querySelector(t[e])}catch{throw new TypeError(`${e} must be a valid query selector. "${t[e]}" given.`)}return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function c(t){try{if(typeof t!="object"||Array.isArray(t)){const e=typeof t;throw new TypeError(`Values given to isValidClassList() must be inside of an object. "${e}" given.`)}for(const e in t){const s=typeof t[e];if(s!=="string")if(Array.isArray(t[e]))t[e].forEach(i=>{if(typeof i!="string")throw new TypeError(`${e} must be a string or an array of strings. An array containing non-strings given.`)});else throw new TypeError(`${e} must be a string or an array of strings. "${s}" given.`);else{const i={};i[e]=t[e],_(i)}}return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function A(t){try{if(typeof t!="object"){const s=typeof t;throw new TypeError(`Values given to isValidState() must be inside of an object. "${s}" given.`)}const e=["none","self","child"];for(const s in t)if(!e.includes(t[s]))throw new TypeError(`${s} must be one of the following values: ${e.join(", ")}. "${t[s]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function $(t){try{if(typeof t!="object"){const s=typeof t;throw new TypeError(`Values given to isValidEvent() must be inside of an object. "${s}" given.`)}const e=["none","mouse","keyboard","character"];for(const s in t)if(!e.includes(t[s]))throw new TypeError(`${s} must be one of the following values: ${e.join(", ")}. "${t[s]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function L(t=null){window.Graupl=window.Graupl||{},r("string",{type:t})&&(window.Graupl[t]=window.Graupl[t]||{})}function D(t=null){return r("string",{type:t})?window.Graupl[t]:window.Graupl}function S(t,e={}){r("string",{type:t})&&r("object",{data:e})&&(window.Graupl[t]=e)}function O(t){r("string",{type:t})&&(window.Graupl[t]={})}function j(t,e,s){r("string",{type:t,key:e})&&(window.Graupl[t][e]=s)}function x(t,e){return r("string",{type:t,key:e})?window.Graupl[t][e]:null}function z(t,e){r("string",{type:t,key:e})&&delete window.Graupl[t][e]}var d={initializeStorage:L,getStorage:D,setStorage:S,clearStorage:O,pushToStorage:j,getFromStorage:x,removeFromStorage:z},M=class{_dom={};_protectedDOMElements=[];_selectors={};_elements={};_classes={initialize:""};_durations={};_delays={};_focusState="none";_currentEvent="none";_breakpoint="";_mediaQueryString="";_mediaQueryList=null;_mediaQueryListEventCallback=t=>{t.matches};_intervals={};_timeouts={};_listeners=[];_events={};_prefix="graupl-";_key="";_storageKey="components";_id="";_valid=!0;_errors=[];constructor({prefix:t="graupl-",key:e=null,initializeClass:s="initializing"}={}){this._classes.initialize=s||"",this._prefix=t||"",this._key=e||""}initialize(){try{if(!this._validate())throw new Error(`Graupl ${this.constructor.name}: Cannot initialize component. The following errors have been found:
2
2
  - ${this.errors.join(`
3
- - `)}`);h(this._classes.initialize,this.dom.tabs),this._generateKey(),this._setDOMElements(),this._setIds(),this._setAriaAttributes(),this._createChildElements(),this._handleFocus(),this._handleClick(),this._handleKeydown(),this._handleKeyup(),this._setTransitionDurations(),y.initializeStorage("tabs"),y.pushToStorage("tabs",this.dom.tabs.id,this),this.elements.tabToggle.filter(t=>t.isActive).length===0&&this.elements.tabToggle[0].show(),requestAnimationFrame(()=>{l(this._classes.initialize,this.dom.tabs)})}catch(t){console.error(t)}}get dom(){return this._dom}get elements(){return this._elements}get selectors(){return this._selectors}get openClass(){return this._classes.open}set openClass(t){m({openClass:t}),this._classes.open!==t&&(this._classes.open=t)}get closeClass(){return this._classes.close}set closeClass(t){m({closeClass:t}),this._classes.close!==t&&(this._classes.close=t)}get transitionClass(){return this._classes.transition}set transitionClass(t){m({transitionClass:t}),this._classes.transition!==t&&(this._classes.transition=t)}get transitionDuration(){return this._durations.transition}set transitionDuration(t){r("number",{value:t}),this._durations.transition!==t&&(this._durations.transition=t,this._setTransitionDurations())}get openDuration(){return this._durations.open===-1?this.transitionDuration:this._durations.open}set openDuration(t){r("number",{value:t}),this._durations.open!==t&&(this._durations.open=t,this._setTransitionDurations())}get closeDuration(){return this._durations.close===-1?this.transitionDuration:this._durations.close}set closeDuration(t){r("number",{value:t}),this._durations.close!==t&&(this._durations.close=t,this._setTransitionDurations())}get isAutomatic(){return this._automatic}set isAutomatic(t){r("boolean",{value:t}),this._automatic!==t&&(this._automatic=t)}get currentChild(){return this._currentChild}set currentChild(t){r("number",{value:t}),this._currentChild!==t&&t>=0&&t<this.elements.tabToggle.length&&(this._currentChild=t)}get currentTabToggle(){return this.elements.tabToggle[this.currentChild]}get focusState(){return this._focusState}set focusState(t){v({value:t}),this._focusState!==t&&(this._focusState=t)}get currentEvent(){return this._currentEvent}set currentEvent(t){D({value:t}),this._currentEvent!==t&&(this._currentEvent=t)}get prefix(){return this._prefix}set prefix(t){r("string",{value:t}),this._prefix!==t&&(this._prefix=t)}get key(){return this._key}get errors(){return this._errors}_validate(){let t=!0;const e=_(HTMLElement,{tabsElement:this.dom.tabs});e||(this._errors.push(e.message),t=!1);const s={};for(const n of Object.keys(this._selectors))s[`${n}Selector`]=this._selectors[n];const i=b(s);i||(this._errors.push(i.message),t=!1);const o={};for(const n of Object.keys(this._classes))this._classes[n]!==""&&(o[`${n}Class`]=this._classes[n]);const a=m(o);a.status||(this._errors.push(a.error.message),t=!1);const u={};for(const n of Object.keys(this._durations))u[`${n}Duration`]=this._durations[n];const d=r("number",u);d.status||(this._errors.push(d.error.message),t=!1);const f=r("boolean",{automaticActivation:this._automatic});if(f.status||(this._errors.push(f.error.message),t=!1),this._key!==""){const n=r("string",{key:this._key});n.status||(this._errors.push(n.error.message),t=!1)}const g=r("string",{prefix:this._prefix});return g.status||(this._errors.push(g.error.message),t=!1),t}_generateKey({regenerate:t=!1}={}){(this.key===""||t)&&(this._key=Math.random().toString(36).replace(/[^a-z]+/g,"").substring(0,10))}_setIds(){this.dom.tabs.id=this.dom.tabs.id||`tabs-${this.key}`,this.dom.tabList.id=this.dom.tabList.id||`tab-list-${this.key}`}_setAriaAttributes(){this.dom.tabList.setAttribute("role","tablist")}_setTransitionDurations(){this.dom.tabs.style.setProperty(`--${this.prefix}tabs-transition-duration`,`${this.transitionDuration}ms`),this.dom.tabs.style.setProperty(`--${this.prefix}tabs-open-transition-duration`,`${this.openDuration}ms`),this.dom.tabs.style.setProperty(`--${this.prefix}tabs-close-transition-duration`,`${this.closeDuration}ms`)}_setDOMElementType(t,{base:e=this.dom.tabs,overwrite:s=!0,strict:i=!0}={}){if(typeof this.selectors[t]=="string"){if(this._domLock.includes(t))throw new Error(`Graupl ${this.constructor.name}: "${t}" element cannot be set through _setDOMElementType.`);e!==this.dom.tabs&&_(HTMLElement,{base:e});const o=Array.from(e.querySelectorAll(this.selectors[t])).filter(a=>i?a.parentElement===e:!0);s?Array.isArray(this._dom[t])?this._dom[t]=o:this._dom[t]=o[0]||null:Array.isArray(this._dom[t])?this._dom[t]=[...this._dom[t],...o]:this._dom[t]=o[0]||null}else throw new Error(`Graupl ${this.constructor.name}: "${t}" is not a valid element type.`)}_resetDOMElementType(t){if(typeof this.selectors[t]=="string"){if(this._domLock.includes(t))throw new Error(`Graupl ${this.constructor.name}: "${t}" element cannot be reset through _resetDOMElementType.`);Array.isArray(this._dom[t])?this._dom[t]=[]:this._dom[t]=null}else throw new Error(`Graupl ${this.constructor.name}: "${t}" is not a valid element type.`)}_setDOMElements(){this._resetDOMElementType("tabList"),this._setDOMElementType("tabList"),this.dom.tabList&&(this._resetDOMElementType("tabToggle"),this._setDOMElementType("tabToggle",{base:this.dom.tabList})),this._resetDOMElementType("tabContent"),this._setDOMElementType("tabContent")}_createChildElements(){this.dom.tabToggle.forEach((t,e)=>{const s=new $({toggleElement:t,contentElement:this.dom.tabContent[e],parentTab:this});s.initialize(),this._elements.tabToggle.push(s)})}_handleFocus(){this.elements.tabToggle.forEach((t,e)=>{t.dom.toggle.addEventListener("focus",()=>{this.currentChild=e,this.isAutomatic&&this.currentTabToggle.show()})})}_handleClick(){this.elements.tabToggle.forEach((t,e)=>{t.dom.toggle.addEventListener("pointerup",()=>{this.currentChild=e,t.show()})})}_handleKeydown(){this.dom.tabToggle.forEach(t=>{t.addEventListener("keydown",e=>{const s=p(e);["Space","Enter","ArrowRight","ArrowLeft","Home","End"].includes(s)&&c(e)})})}_handleKeyup(){this.dom.tabToggle.forEach(t=>{t.addEventListener("keyup",e=>{switch(p(e)){case"Space":case"Enter":c(e),this.currentTabToggle.show();break;case"Home":c(e),this.focusFirstChild();break;case"End":c(e),this.focusLastChild();break;case"ArrowRight":c(e),this.focusNextChild();break;case"ArrowLeft":c(e),this.focusPreviousChild();break}})})}focusCurrentChild(){this.currentChild!==-1&&this.currentTabToggle.focus()}focusChild(t){this.blurCurrentChild(),this.currentChild=t,this.focusCurrentChild()}focusFirstChild(){this.focusChild(0)}focusLastChild(){this.focusChild(this.elements.tabToggle.length-1)}focusNextChild(){this.currentChild<this.elements.tabToggle.length-1?this.focusChild(this.currentChild+1):this.focusFirstChild()}focusPreviousChild(){this.currentChild>0?this.focusChild(this.currentChild-1):this.focusLastChild()}blurCurrentChild(){this.currentChild!==-1&&this.currentTabToggle.blur()}},V=M;export{V as default};
3
+ - `)}`);this._generateKey()}catch(t){console.error(t)}}init(){this.initialize()}get dom(){return this._dom}get selectors(){return this._selectors}get elements(){return this._elements}get classes(){return this._classes}get durations(){return this._durations}get delays(){return this._delays}get intervals(){return this._intervals}get timeouts(){return this._timeouts}get listeners(){return this._listeners}get events(){return this._events}get initializeClass(){return this._classes.initialize}set initializeClass(t){c({initializeClass:t}),this._classes.initialize!==t&&(this._classes.initialize=t)}get focusState(){return this._focusState}set focusState(t){A({focusState:t}),this._focusState!==t&&(this._focusState=t)}get currentEvent(){return this._currentEvent}set currentEvent(t){$({currentEvent:t}),this._currentEvent!==t&&(this._currentEvent=t)}get breakpoint(){return this._breakpoint}set breakpoint(t){r("string",{breakpoint:t}),this._breakpoint!==t&&(this._breakpoint=t)}get mediaQuery(){return this._mediaQueryString!==""?this._mediaQueryString:`(width <= ${this._breakpoint})`}set mediaQuery(t){r("string",{mediaQuery:t}),this._mediaQueryString!==t&&(this._mediaQueryString=t)}get prefix(){return this._prefix}get key(){return this._key}get errors(){return this._errors}_validate(){if(Object.keys(this._dom).length>0){const t={};for(const s of Object.keys(this._dom))Array.isArray(this._dom[s])&&this._dom[s].forEach((i,n)=>{t[`${s}Element[${n}]`]=i}),t[`${s}Element`]=this._dom[s];const e=u(HTMLElement,t);e||(this._errors.push(e.message),this._valid=!1)}if(Object.keys(this._selectors).length>0){const t={};for(const s of Object.keys(this._selectors))t[`${s}Selector`]=this._selectors[s];const e=_(t);e||(this._errors.push(e.message),this._valid=!1)}if(Object.keys(this._classes).length>0){const t={};for(const s of Object.keys(this._classes))this._classes[s]!==""&&(t[`${s}Class`]=this._classes[s]);const e=c(t);e.status||(this._errors.push(e.error.message),this._valid=!1)}if(Object.keys(this._durations).length>0){const t={};for(const s of Object.keys(this._durations))t[`${s}Duration`]=this._durations[s];const e=r("number",t);e.status||(this._errors.push(e.error.message),this._valid=!1)}if(Object.keys(this.delays).length>0){const t={};for(const s of Object.keys(this.delays))t[`${s}Delay`]=this.delays[s];const e=r("number",t);e.status||(this._errors.push(e.error.message),this._valid=!1)}if(this._key!==""){const t=r("string",{key:this._key});t.status||(this._errors.push(t.error.message),this._valid=!1)}if(this._prefix!==""){const t=r("string",{prefix:this._prefix});t.status||(this._errors.push(t.error.message),this._valid=!1)}return this._valid}_generateKey(t=!1){(this._key===""||t)&&(this._key=Math.random().toString(36).replace(/[^a-z]+/g,"").substring(0,10))}_setIds(){}_setAriaAttributes(){}_setCustomProps(){}_setDOMElementType(t,{context:e,overwrite:s=!0,strict:i=!0}={}){if(typeof this.selectors[t]!="string")throw new Error(`Graupl ${this.constructor.name}: "${t}" is not a valid element type.`);if(this._protectedDOMElements.includes(t))throw new Error(`Graupl ${this.constructor.name}: "${t}" element cannot be set through _setDOMElementType because it is a protected element.`);u(HTMLElement,{context:e});const n=Array.from(e.querySelectorAll(this.selectors[t])).filter(o=>i?o.parentElement===e:!0);Array.isArray(this._dom[t])?s?this._dom[t]=n:this._dom[t]=[...this._dom[t],...n]:this._dom[t]=n[0]||null}_resetDOMElementType(t){if(typeof this.selectors[t]!="string")throw new Error(`Graupl ${this.constructor.name}: "${t}" is not a valid element type.`);if(this._protectedDOMElements.includes(t))throw new Error(`Graupl ${this.constructor.name}: "${t}" element cannot be reset through _resetDOMElementType because it is a protected element.`);Array.isArray(this._dom[t])?this._dom[t]=[]:this._dom[t]=null}_setDOMElements(){}_createChildElements(){}_handleMediaMatch(){this._breakpointWidth!==""&&(this._mediaQueryList=window.matchMedia(this.mediaQuery),this._mediaQueryList.addEventListener("change",this._mediaQueryListEventCallback),this._mediaQueryListEventCallback(this._mediaQueryList))}_handleFocus(){}_handleClick(){}_handleKeydown(){}_handleKeyup(){}_store(){d.initializeStorage(this._storageKey),d.pushToStorage(this._storageKey,this._id!==""?this._id:this._key,this)}_unstore(){d.removeFromStorage(this._storageKey,this._id!==""?this._id:this._key)}_setInterval(t,e,s="_default"){this._clearInterval(s),this._intervals[s]=setInterval(t,e)}_clearInterval(t="_default"){clearInterval(this._intervals[t])}_setTimeout(t,e,s="_default"){this._clearTimeout(s),this._timeouts[s]=setTimeout(t,e)}_clearTimeout(t="_default"){clearTimeout(this._timeouts[t])}_dispatchEvent(t,e){if(!Object.keys(this.events).includes(t))throw new Error(`Graupl ${this.constructor.name}: "${t}" is not a valid event type.`);u(HTMLElement,{element:e}),e.dispatchEvent(this.events[t])}_addEventListener(t,e,s,i={}){e.addEventListener(t,s,i),this._listeners.push({type:t,element:e,listener:s,options:i})}_removeEventListener(t,e,s,i={}){e.removeEventListener(t,s,i);const n=this._listeners.indexOf({type:t,element:e,listener:s,options:i});n!==-1&&this._listeners.splice(n)}_removeEventListeners(){this._listeners.forEach(({type:t,element:e,listener:s,options:i})=>{this._removeEventListener(t,e,s,i)})}dispose(){this._removeEventListeners(),this._unstore(),delete this}},f=M,Q=class extends f{_dom={toggle:null,content:null};_protectedDOMElements=["toggle","content"];_elements={parent:null};_active=new k(!1);_events={activate:new CustomEvent("grauplTabToggleActivate",{bubbles:!0,detail:{toggle:this}}),deactivate:new CustomEvent("grauplTabToggleDeactivate",{bubbles:!0,detail:{toggle:this}})};constructor({toggleElement:t,contentElement:e,parentTab:s}={}){super({prefix:s.prefix,key:s.key}),this._dom.toggle=t,this._dom.content=e,this._elements.parent=s}initialize(){this._setIds(),this._setAriaAttributes(),this.dom.toggle.getAttribute("aria-selected")==="true"?this.show({force:!0,emit:!1,transition:!1}):this.hide({force:!0,emit:!1,transition:!1})}get isActive(){return this._active.value}_setIds(){const{key:t}=this.elements.parent,e=this.elements.parent.dom.tabToggle.indexOf(this.dom.toggle);this.dom.toggle.id=this.dom.toggle.id||`tab-toggle-${t}-${e}`,this.dom.content.id=this.dom.content.id||`tab-content-${t}-${e}`,this._id=this.dom.toggle.id}_setAriaAttributes(){this.dom.toggle.setAttribute("role","tab"),this.dom.toggle.getAttribute("aria-selected")!=="true"&&this.dom.toggle.setAttribute("aria-selected","false"),this.dom.toggle.setAttribute("aria-controls",this.dom.content.id),this.dom.content.setAttribute("role","tabpanel")}_reveal({emit:t=!0,transition:e=!0}={}){const{closeClass:s,openClass:i,transitionClass:n,openDuration:o}=this.elements.parent;this.dom.toggle.setAttribute("aria-selected","true"),e&&n!==""?(a(n,this.dom.content),requestAnimationFrame(()=>{h(s,this.dom.content),requestAnimationFrame(()=>{a(i,this.dom.content),requestAnimationFrame(()=>{this._setTimeout(()=>h(n,this.dom.content),o)})})})):(a(i,this.dom.content),h(s,this.dom.content)),t&&this._dispatchEvent("activate",this.dom.toggle)}_conceal({emit:t=!0,transition:e=!0}={}){const{closeClass:s,openClass:i,transitionClass:n,closeDuration:o}=this.elements.parent;this.dom.toggle.setAttribute("aria-selected","false"),e&&n!==""?(a(n,this.dom.content),requestAnimationFrame(()=>{h(i,this.dom.content),requestAnimationFrame(()=>{a(s,this.dom.content),requestAnimationFrame(()=>{this._setTimeout(()=>h(n,this.dom.content),o)})})})):(a(s,this.dom.content),h(i,this.dom.content)),t&&this._dispatchEvent("deactivate",this.dom.toggle)}show({force:t=!1,preserveState:e=!1,emit:s=!0,transition:i=!0}={}){this.isActive&&!t||(this.elements.parent.focusState="self",this._reveal({emit:s,transition:i}),this._active.value=!0,e||this._active.commit(),this.dom.toggle.setAttribute("tabindex","0"),this.hideSiblings())}hide({force:t=!1,preserveState:e=!1,emit:s=!0,transition:i=!0}={}){!this.isActive&&!t||(this.elements.parent.focusState="none",this._conceal({emit:s,transition:i}),this._active.value=!1,e||this._active.commit(),this.dom.toggle.setAttribute("tabindex","-1"))}focus(){this.dom.toggle.focus()}blur(){this.dom.toggle.blur()}hideSiblings(){this.elements.parent&&this.elements.parent.elements.tabToggle.forEach(t=>{t!==this&&t.hide()})}},G=Q;function m(t){try{const e=t.key||t.keyCode,s={Enter:e==="Enter"||e===13,Space:e===" "||e==="Spacebar"||e===32,Escape:e==="Escape"||e==="Esc"||e===27,ArrowUp:e==="ArrowUp"||e==="Up"||e===38,ArrowRight:e==="ArrowRight"||e==="Right"||e===39,ArrowDown:e==="ArrowDown"||e==="Down"||e===40,ArrowLeft:e==="ArrowLeft"||e==="Left"||e===37,Home:e==="Home"||e===36,End:e==="End"||e===35,Tab:e==="Tab"||e===9};return Object.keys(s).find(i=>s[i]===!0)||""}catch{return""}}function l(t){t.preventDefault(),t.stopPropagation()}var q=class extends f{_dom={tabs:null,tabList:null,tabToggle:[],tabContent:[]};_protectedDOMElements=["tab"];_selectors={tabList:"",tabToggle:"",tabContent:""};_elements={tabToggle:[]};_classes={open:"show",close:"hide",transition:"transitioning",initialize:"initializing"};_durations={transition:250,open:-1,close:-1};_automatic=!1;_currentChild=0;_storageKey="tabs";constructor({tabsElement:t,tabListSelector:e=".tab-list",tabToggleSelector:s=".tab-toggle",tabContentSelector:i=".tab-content",openClass:n="show",closeClass:o="hide",transitionClass:g=null,transitionDuration:b=300,openDuration:p=-1,closeDuration:y=-1,automaticActivation:E=!1,prefix:w="graupl-",key:C=null,initializeClass:v="initializing",initialize:T=!1}){super({prefix:w,key:C,initializeClass:v}),this._dom.tabs=t,this._selectors.tabList=e,this._selectors.tabToggle=s,this._selectors.tabContent=i,this._classes.open=n||"",this._classes.close=o||"",this._classes.transition=g||"",this._durations.transition=b,this._durations.open=p,this._durations.close=y,this._automatic=E,T&&this.initialize()}initialize(){try{a(this.initializeClass,this.dom.tabs),super.initialize(),this._setDOMElements(),this._setIds(),this._setAriaAttributes(),this._setCustomProps(),this._createChildElements(),this._handleFocus(),this._handleClick(),this._handleKeydown(),this._handleKeyup(),this._store(),this.elements.tabToggle.filter(t=>t.isActive).length===0&&this.elements.tabToggle[0].show()}catch(t){console.error(t)}finally{requestAnimationFrame(()=>{h(this.initializeClass,this.dom.tabs)})}}get openClass(){return this._classes.open}set openClass(t){c({openClass:t}),this._classes.open!==t&&(this._classes.open=t)}get closeClass(){return this._classes.close}set closeClass(t){c({closeClass:t}),this._classes.close!==t&&(this._classes.close=t)}get transitionClass(){return this._classes.transition}set transitionClass(t){c({transitionClass:t}),this._classes.transition!==t&&(this._classes.transition=t)}get transitionDuration(){return this._durations.transition}set transitionDuration(t){r("number",{transitionDuration:t}),this._durations.transition!==t&&(this._durations.transition=t,this._setTransitionDurations())}get openDuration(){return this._durations.open===-1?this.transitionDuration:this._durations.open}set openDuration(t){r("number",{openDuration:t}),this._durations.open!==t&&(this._durations.open=t,this._setTransitionDurations())}get closeDuration(){return this._durations.close===-1?this.transitionDuration:this._durations.close}set closeDuration(t){r("number",{closeDuration:t}),this._durations.close!==t&&(this._durations.close=t,this._setTransitionDurations())}get isAutomatic(){return this._automatic}set isAutomatic(t){r("boolean",{isAutomatic:t}),this._automatic!==t&&(this._automatic=t)}get currentChild(){return this._currentChild}set currentChild(t){r("number",{currentChild:t}),this._currentChild!==t&&t>=0&&t<this.elements.tabToggle.length&&(this._currentChild=t)}get currentTabToggle(){return this.elements.tabToggle[this.currentChild]}_validate(){super._validate();const t=r("boolean",{automaticActivation:this._automatic});return t||(this._errors.push(t.message),this._valid=!1),this._valid}_setIds(){this.dom.tabs.id=this.dom.tabs.id||`tabs-${this.key}`,this.dom.tabList.id=this.dom.tabList.id||`tab-list-${this.key}`,this._id=this.dom.tabs.id}_setAriaAttributes(){this.dom.tabList.setAttribute("role","tablist")}_setCustomProps(){this.dom.tabs.style.setProperty(`--${this.prefix}tabs-transition-duration`,`${this.transitionDuration}ms`),this.dom.tabs.style.setProperty(`--${this.prefix}tabs-open-transition-duration`,`${this.openDuration}ms`),this.dom.tabs.style.setProperty(`--${this.prefix}tabs-close-transition-duration`,`${this.closeDuration}ms`)}_setDOMElements(){this._resetDOMElementType("tabList"),this._setDOMElementType("tabList",{context:this.dom.tabs}),this.dom.tabList&&(this._resetDOMElementType("tabToggle"),this._setDOMElementType("tabToggle",{context:this.dom.tabList})),this._resetDOMElementType("tabContent"),this._setDOMElementType("tabContent",{context:this.dom.tabs})}_createChildElements(){this.dom.tabToggle.forEach((t,e)=>{const s=new G({toggleElement:t,contentElement:this.dom.tabContent[e],parentTab:this});s.initialize(),this._elements.tabToggle.push(s)})}_handleFocus(){this.elements.tabToggle.forEach((t,e)=>{this._addEventListener("focus",t.dom.toggle,()=>{this.currentChild=e,this.isAutomatic&&this.currentTabToggle.show()})})}_handleClick(){this.elements.tabToggle.forEach((t,e)=>{this._addEventListener("pointerup",t.dom.toggle,()=>{this.currentChild=e,t.show()})})}_handleKeydown(){this.dom.tabToggle.forEach(t=>{this._addEventListener("keydown",t,e=>{const s=m(e);["Space","Enter","ArrowRight","ArrowLeft","Home","End"].includes(s)&&l(e)})})}_handleKeyup(){this.dom.tabToggle.forEach(t=>{this._addEventListener("keyup",t,e=>{switch(m(e)){case"Space":case"Enter":l(e),this.currentTabToggle.show();break;case"Home":l(e),this.focusFirstChild();break;case"End":l(e),this.focusLastChild();break;case"ArrowRight":l(e),this.focusNextChild();break;case"ArrowLeft":l(e),this.focusPreviousChild();break}})})}focusCurrentChild(){this.currentChild!==-1&&this.currentTabToggle.focus()}focusChild(t){this.blurCurrentChild(),this.currentChild=t,this.focusCurrentChild()}focusFirstChild(){this.focusChild(0)}focusLastChild(){this.focusChild(this.elements.tabToggle.length-1)}focusNextChild(){this.currentChild<this.elements.tabToggle.length-1?this.focusChild(this.currentChild+1):this.focusFirstChild()}focusPreviousChild(){this.currentChild>0?this.focusChild(this.currentChild-1):this.focusLastChild()}blurCurrentChild(){this.currentChild!==-1&&this.currentTabToggle.blur()}},F=q;export{F as default};
4
4
 
5
5
  //# sourceMappingURL=tabs.es.js.map