@travelopia/web-components 0.9.9 → 0.9.11
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.
package/dist/declarations.d.ts
CHANGED
|
@@ -624,6 +624,11 @@ export class TPLightboxElement extends HTMLElement {
|
|
|
624
624
|
* @param {Event} e Click event.
|
|
625
625
|
*/
|
|
626
626
|
handleDialogClick(e: MouseEvent): void;
|
|
627
|
+
/**
|
|
628
|
+
* Handle when the dialog is closed (e.g., via Escape key).
|
|
629
|
+
* Syncs lightbox state with native dialog close behavior.
|
|
630
|
+
*/
|
|
631
|
+
handleDialogClose(): void;
|
|
627
632
|
/**
|
|
628
633
|
* Handles the touch start event.
|
|
629
634
|
*
|
package/dist/lightbox/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(()=>{"use strict";class t extends HTMLElement{constructor(){var t,e,i;super(),this.currentTemplate=null,this.currentGroup="",this.allGroups=null,this.touchStartX=0,this.touchStartY=0,this.swipeThreshold=200,this.previouslyFocusedElement=null,this.boundHandleKeyDown=this.handleKeyDown.bind(this),this.dialogElement=this.querySelector("dialog"),this.lightboxNavItems=this.querySelectorAll("tp-lightbox-nav-item"),null===(t=this.dialogElement)||void 0===t||t.addEventListener("click",this.handleDialogClick.bind(this)),null===(e=this.dialogElement)||void 0===e||e.addEventListener("touchstart",this.handleTouchStart.bind(this)),null===(i=this.dialogElement)||void 0===i||i.addEventListener("touchend",this.handleTouchEnd.bind(this))}static get observedAttributes(){return["open","index","total","close-on-overlay-click","loading"]}attributeChangedCallback(t="",e="",i=""){e!==i&&(this.dispatchEvent(new CustomEvent("change")),"index"===t&&this.triggerCurrentIndexTarget(),"open"!==t&&"index"!==t||this.updateNavCurrentItem())}isAriaEnabled(){return"no"!==this.getAttribute("aria")}get template(){return this.currentTemplate}set template(t){this.currentTemplate=t,this.dispatchEvent(new CustomEvent("template-set"));const e=this.querySelector("tp-lightbox-content");if(e)if(this.currentTemplate){const t=this.currentTemplate.content.cloneNode(!0);e.replaceChildren(t),this.dispatchEvent(new CustomEvent("content-change")),setTimeout((()=>{this.prepareImageLoading(),this.prepareNavigation()}),0)}else e.innerHTML=""}get group(){return this.currentGroup}set group(t){this.currentGroup=t}get currentIndex(){var t;return parseInt(null!==(t=this.getAttribute("index"))&&void 0!==t?t:"1")}set currentIndex(t){t<1&&(t=1),this.setAttribute("index",t.toString()),this.dispatchEvent(new CustomEvent("slide-set",{detail:{slideIndex:t}}))}triggerCurrentIndexTarget(){const t=this.getAllGroups();t&&t[this.currentIndex-1]&&t[this.currentIndex-1].trigger()}open(){const t=this.querySelector("dialog");t&&!t.open&&("no"!==this.getAttribute("manage-focus")&&(this.previouslyFocusedElement=this.ownerDocument.activeElement),""===this.group||this.allGroups||this.updateAllGroups(),t.showModal(),this.setAttribute("open","yes"),document.addEventListener("keydown",this.boundHandleKeyDown),"no"!==this.getAttribute("manage-focus")&&this.setInitialFocus())}close(){document.removeEventListener("keydown",this.boundHandleKeyDown);const t=this.querySelector("dialog");null==t||t.close(),this.removeAttribute("open"),"no"!==this.getAttribute("manage-focus")&&this.previouslyFocusedElement&&(this.previouslyFocusedElement.focus(),this.previouslyFocusedElement=null),this.allGroups=null}previous(){""!==this.group&&this.getAllGroups()&&this.currentIndex>1&&this.currentIndex--}next(){if(""===this.group)return;const t=this.getAllGroups();t&&this.currentIndex<t.length&&this.currentIndex++}updateAllGroups(t=null){if(t&&t.length)return this.allGroups=t,void this.setAttribute("total",this.allGroups.length.toString());this.allGroups=document.querySelectorAll(`tp-lightbox-trigger[group="${this.group}"]`),this.allGroups.length?this.setAttribute("total",this.allGroups.length.toString()):this.allGroups=null}getAllGroups(){return this.allGroups}prepareNavigation(){var t,e;const i=this.querySelector("tp-lightbox-count");null==i||i.update();const s=this.querySelector("tp-lightbox-previous"),r=this.querySelector("tp-lightbox-next");if(!s&&!r)return;const
|
|
1
|
+
(()=>{"use strict";class t extends HTMLElement{constructor(){var t,e,i,s;super(),this.currentTemplate=null,this.currentGroup="",this.allGroups=null,this.touchStartX=0,this.touchStartY=0,this.swipeThreshold=200,this.previouslyFocusedElement=null,this.boundHandleKeyDown=this.handleKeyDown.bind(this),this.dialogElement=this.querySelector("dialog"),this.lightboxNavItems=this.querySelectorAll("tp-lightbox-nav-item"),null===(t=this.dialogElement)||void 0===t||t.addEventListener("click",this.handleDialogClick.bind(this)),null===(e=this.dialogElement)||void 0===e||e.addEventListener("touchstart",this.handleTouchStart.bind(this)),null===(i=this.dialogElement)||void 0===i||i.addEventListener("touchend",this.handleTouchEnd.bind(this)),null===(s=this.dialogElement)||void 0===s||s.addEventListener("close",this.handleDialogClose.bind(this))}static get observedAttributes(){return["open","index","total","close-on-overlay-click","loading"]}attributeChangedCallback(t="",e="",i=""){e!==i&&(this.dispatchEvent(new CustomEvent("change")),"index"===t&&this.triggerCurrentIndexTarget(),"open"!==t&&"index"!==t||this.updateNavCurrentItem())}isAriaEnabled(){return"no"!==this.getAttribute("aria")}get template(){return this.currentTemplate}set template(t){this.currentTemplate=t,this.dispatchEvent(new CustomEvent("template-set"));const e=this.querySelector("tp-lightbox-content");if(e)if(this.currentTemplate){const t=this.currentTemplate.content.cloneNode(!0);e.replaceChildren(t),this.dispatchEvent(new CustomEvent("content-change")),setTimeout((()=>{this.prepareImageLoading(),this.prepareNavigation()}),0)}else e.innerHTML=""}get group(){return this.currentGroup}set group(t){this.currentGroup=t}get currentIndex(){var t;return parseInt(null!==(t=this.getAttribute("index"))&&void 0!==t?t:"1")}set currentIndex(t){t<1&&(t=1),this.setAttribute("index",t.toString()),this.dispatchEvent(new CustomEvent("slide-set",{detail:{slideIndex:t}}))}triggerCurrentIndexTarget(){const t=this.getAllGroups();t&&t[this.currentIndex-1]&&t[this.currentIndex-1].trigger()}open(){const t=this.querySelector("dialog");t&&!t.open&&("no"!==this.getAttribute("manage-focus")&&(this.previouslyFocusedElement=this.ownerDocument.activeElement),""===this.group||this.allGroups||this.updateAllGroups(),t.showModal(),this.setAttribute("open","yes"),document.addEventListener("keydown",this.boundHandleKeyDown),"no"!==this.getAttribute("manage-focus")&&this.setInitialFocus())}close(){document.removeEventListener("keydown",this.boundHandleKeyDown);const t=this.querySelector("dialog");null==t||t.close(),this.removeAttribute("open"),"no"!==this.getAttribute("manage-focus")&&this.previouslyFocusedElement&&(this.previouslyFocusedElement.focus(),this.previouslyFocusedElement=null),this.allGroups=null}previous(){""!==this.group&&this.getAllGroups()&&this.currentIndex>1&&this.currentIndex--}next(){if(""===this.group)return;const t=this.getAllGroups();t&&this.currentIndex<t.length&&this.currentIndex++}updateAllGroups(t=null){if(t&&t.length)return this.allGroups=t,void this.setAttribute("total",this.allGroups.length.toString());this.allGroups=document.querySelectorAll(`tp-lightbox-trigger[group="${this.group}"]`),this.allGroups.length?this.setAttribute("total",this.allGroups.length.toString()):this.allGroups=null}getAllGroups(){return this.allGroups}prepareNavigation(){var t,e;const i=this.querySelector("tp-lightbox-count");null==i||i.update();const s=this.querySelector("tp-lightbox-previous"),r=this.querySelector("tp-lightbox-next");if(!s&&!r)return;const l=null!==(t=null==s?void 0:s.querySelector("button"))&&void 0!==t?t:null,n=null!==(e=null==r?void 0:r.querySelector("button"))&&void 0!==e?e:null,o=this.isAriaEnabled();if(""===this.group)return null==s||s.setAttribute("disabled","yes"),null==r||r.setAttribute("disabled","yes"),void(o&&(null==l||l.setAttribute("aria-disabled","true"),null==n||n.setAttribute("aria-disabled","true")));const u=this.getAllGroups();if(!u)return null==s||s.setAttribute("disabled","yes"),null==r||r.setAttribute("disabled","yes"),void(o&&(null==l||l.setAttribute("aria-disabled","true"),null==n||n.setAttribute("aria-disabled","true")));this.currentIndex<=1?(null==s||s.setAttribute("disabled","yes"),o&&(null==l||l.setAttribute("aria-disabled","true"))):(null==s||s.removeAttribute("disabled"),o&&(null==l||l.removeAttribute("aria-disabled"))),this.currentIndex<u.length?(null==r||r.removeAttribute("disabled"),o&&(null==n||n.removeAttribute("aria-disabled"))):(null==r||r.setAttribute("disabled","yes"),o&&(null==n||n.setAttribute("aria-disabled","true")))}prepareImageLoading(){const t=this.querySelector("tp-lightbox-content");if(!t)return;const e=t.querySelectorAll("img");if(!e.length)return void this.removeAttribute("loading");this.setAttribute("loading","yes");let i=0;const s=e.length,r=()=>{i++,i===s&&this.removeAttribute("loading")};e.forEach((t=>{t.complete?r():t.addEventListener("load",r,{once:!0})}))}handleDialogClick(t){"yes"===this.getAttribute("close-on-overlay-click")&&this.querySelector("dialog")===t.target&&this.close()}handleDialogClose(){this.hasAttribute("open")&&this.close()}handleTouchStart(t){"yes"===this.getAttribute("swipe")&&(this.touchStartX=t.touches[0].clientX,this.touchStartY=t.touches[0].clientY)}handleTouchEnd(t){var e;if("yes"!==this.getAttribute("swipe"))return;const i=t.changedTouches[0].clientX,s=t.changedTouches[0].clientY,r=i-this.touchStartX,l=s-this.touchStartY;Math.abs(r)>Math.abs(l)&&(this.swipeThreshold=Number(null!==(e=this.getAttribute("swipe-threshold"))&&void 0!==e?e:"200"),r>0?r<this.swipeThreshold&&this.previous():r<0&&r>-this.swipeThreshold&&this.next())}updateNavCurrentItem(){if(!this.lightboxNavItems)return;const t=this.isAriaEnabled();this.lightboxNavItems.forEach(((e,i)=>{const s=e.querySelector("button");this.currentIndex-1===i?(e.setAttribute("current","yes"),t&&s&&s.setAttribute("aria-current","true")):(e.removeAttribute("current"),t&&s&&s.removeAttribute("aria-current"))}))}setInitialFocus(){var t;const e=this.querySelector("[autofocus]");e?e.focus():null===(t=this.dialogElement)||void 0===t||t.focus()}handleKeyDown(t){"yes"===this.getAttribute("arrow-navigation")&&("ArrowLeft"===t.key?(t.preventDefault(),this.previous()):"ArrowRight"===t.key&&(t.preventDefault(),this.next()))}}class e extends HTMLElement{}class i extends HTMLElement{constructor(){var t;super(),null===(t=this.querySelector("button"))||void 0===t||t.addEventListener("click",this.close.bind(this))}close(){const t=this.closest("tp-lightbox");t&&setTimeout((()=>{t.close()}),0)}}class s extends HTMLElement{constructor(){var t;super(),null===(t=this.querySelector("button"))||void 0===t||t.addEventListener("click",this.previous.bind(this))}previous(){if("yes"===this.getAttribute("disabled"))return;const t=this.closest("tp-lightbox");t&&setTimeout((()=>{t.previous()}),0)}}class r extends HTMLElement{constructor(){var t;super(),null===(t=this.querySelector("button"))||void 0===t||t.addEventListener("click",this.next.bind(this))}next(){if("yes"===this.getAttribute("disabled"))return;const t=this.closest("tp-lightbox");t&&setTimeout((()=>{t.next()}),0)}}class l extends HTMLElement{static get observedAttributes(){return["format"]}get format(){var t;return null!==(t=this.getAttribute("format"))&&void 0!==t?t:"$current / $total"}set format(t){this.setAttribute("format",t)}attributeChangedCallback(){this.update()}update(){var t;const e=this.closest("tp-lightbox");if(!e)return;const i=e.currentIndex.toString(),s=null!==(t=e.getAttribute("total"))&&void 0!==t?t:"";this.textContent=this.format.replace("$current",i).replace("$total",s),this.setAttribute("current",i),this.setAttribute("total",s)}}class n extends HTMLElement{constructor(){var t;super(),null===(t=this.querySelector("button"))||void 0===t||t.addEventListener("click",this.trigger.bind(this))}trigger(){var t;const e=this.getAttribute("lightbox"),i=this.querySelector("template");if(!e||!i)return;const s=document.querySelector(`#${e.toString()}`);if(!s)return;const r=null!==(t=this.getAttribute("group"))&&void 0!==t?t:"";setTimeout((()=>{if(s.template=i,s.group=r,""!==r){const t=document.querySelectorAll(`tp-lightbox-trigger[group="${r}"]`);t.length&&(s.updateAllGroups(t),t.forEach(((t,e)=>{this===t&&(s.currentIndex=e+1)})))}s.open()}),0)}}class o extends HTMLElement{constructor(){var t;super(),this.template=null,this.template=this.querySelector("template"),this.lightbox=this.closest("tp-lightbox"),null===(t=this.lightbox)||void 0===t||t.addEventListener("template-set",this.setTemplate.bind(this))}setTemplate(){var t,e;if(!this.template)return;const i=Number(null!==(e=null===(t=this.lightbox)||void 0===t?void 0:t.getAttribute("total"))&&void 0!==e?e:0);this.innerHTML="";for(let t=0;t<i;t++){const t=this.template.content.cloneNode(!0);this.appendChild(t)}}}class u extends HTMLElement{constructor(){var t;super(),this.lightbox=this.closest("tp-lightbox"),null===(t=this.querySelector("button"))||void 0===t||t.addEventListener("click",this.handleClick.bind(this))}handleClick(){var t;this.lightbox&&(this.lightbox.currentIndex=null!==(t=Number(this.getIndex()))&&void 0!==t?t:1,this.lightbox.updateNavCurrentItem())}getIndex(){var t;if(!this.lightbox)return 0;const e=this.closest("tp-lightbox-nav");return Array.from(null!==(t=null==e?void 0:e.children)&&void 0!==t?t:[]).indexOf(this)+1}}customElements.define("tp-lightbox",t),customElements.define("tp-lightbox-content",e),customElements.define("tp-lightbox-close",i),customElements.define("tp-lightbox-previous",s),customElements.define("tp-lightbox-next",r),customElements.define("tp-lightbox-count",l),customElements.define("tp-lightbox-trigger",n),customElements.define("tp-lightbox-nav",o),customElements.define("tp-lightbox-nav-item",u)})();
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dist/lightbox/index.js","mappings":"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","sources":["webpack://@travelopia/web-components/./src/lightbox/tp-lightbox.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-content.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-close.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-previous.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-next.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-count.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-trigger.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-nav.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-nav-item.ts","webpack://@travelopia/web-components/./src/lightbox/index.ts"],"sourcesContent":["/**\n * Internal dependencies.\n */\nimport { TPLightboxContentElement } from './tp-lightbox-content';\nimport { TPLightboxPreviousElement } from './tp-lightbox-previous';\nimport { TPLightboxNextElement } from './tp-lightbox-next';\nimport { TPLightboxTriggerElement } from './tp-lightbox-trigger';\nimport { TPLightboxCountElement } from './tp-lightbox-count';\nimport { TPLightboxNavItemElement } from './tp-lightbox-nav-item';\n\n/**\n * TP Lightbox.\n */\nexport class TPLightboxElement extends HTMLElement {\n\t/**\n\t * Properties.\n\t */\n\tprotected currentTemplate: HTMLTemplateElement | null = null;\n\tprotected currentGroup: string = '';\n\tprotected allGroups: NodeListOf<TPLightboxTriggerElement> | null = null;\n\tprotected touchStartX: number = 0;\n\tprotected touchStartY: number = 0;\n\tprotected swipeThreshold: number = 200;\n\tprotected dialogElement: HTMLDialogElement | null;\n\tprotected lightboxNavItems: NodeListOf<TPLightboxNavItemElement> | null;\n\tprotected previouslyFocusedElement: HTMLElement | null = null;\n\tprotected readonly boundHandleKeyDown: ( e: KeyboardEvent ) => void;\n\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Bind event handlers.\n\t\tthis.boundHandleKeyDown = this.handleKeyDown.bind( this );\n\n\t\t// Initialize\n\t\tthis.dialogElement = this.querySelector( 'dialog' );\n\t\tthis.lightboxNavItems = this.querySelectorAll( 'tp-lightbox-nav-item' );\n\n\t\t// Event listeners.\n\t\tthis.dialogElement?.addEventListener( 'click', this.handleDialogClick.bind( this ) );\n\t\tthis.dialogElement?.addEventListener( 'touchstart', this.handleTouchStart.bind( this ) );\n\t\tthis.dialogElement?.addEventListener( 'touchend', this.handleTouchEnd.bind( this ) );\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Attributes to observe.\n\t\treturn [ 'open', 'index', 'total', 'close-on-overlay-click', 'loading' ];\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string = '', oldValue: string = '', newValue: string = '' ): void {\n\t\t// Prevent redundant updates.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Trigger change event.\n\t\tthis.dispatchEvent( new CustomEvent( 'change' ) );\n\n\t\t// Trigger current index target if index has changed.\n\t\tif ( 'index' === name ) {\n\t\t\tthis.triggerCurrentIndexTarget();\n\t\t}\n\n\t\t// Trigger navigation update if open or index has changed.\n\t\tif ( 'open' === name || 'index' === name ) {\n\t\t\tthis.updateNavCurrentItem();\n\t\t}\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA is enabled.\n\t */\n\tisAriaEnabled(): boolean {\n\t\t// Return whether ARIA management is enabled (default: yes).\n\t\treturn 'no' !== this.getAttribute( 'aria' );\n\t}\n\n\t/**\n\t * Get template.\n\t */\n\tget template(): HTMLTemplateElement | null {\n\t\t// Return current template.\n\t\treturn this.currentTemplate;\n\t}\n\n\t/**\n\t * Set template.\n\t *\n\t * @param {HTMLTemplateElement} template The template.\n\t */\n\tset template( template: HTMLTemplateElement | null ) {\n\t\t// Set the template.\n\t\tthis.currentTemplate = template;\n\t\tthis.dispatchEvent( new CustomEvent( 'template-set' ) );\n\n\t\t// Get lightbox content element.\n\t\tconst content: TPLightboxContentElement | null = this.querySelector( 'tp-lightbox-content' );\n\n\t\t// Check if we have a content.\n\t\tif ( ! content ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have a template.\n\t\tif ( this.currentTemplate ) {\n\t\t\t/**\n\t\t\t * We do, update content with template's content.\n\t\t\t * We do this rather than a string to avoid script injection.\n\t\t\t */\n\t\t\tconst templateContent: Node = this.currentTemplate.content.cloneNode( true );\n\t\t\tcontent.replaceChildren( templateContent );\n\t\t\tthis.dispatchEvent( new CustomEvent( 'content-change' ) );\n\n\t\t\t// Prepare image loading.\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// We do, prepare image loading.\n\t\t\t\tthis.prepareImageLoading();\n\t\t\t\tthis.prepareNavigation();\n\t\t\t}, 0 );\n\t\t} else {\n\t\t\t// We don't, set content as empty.\n\t\t\tcontent.innerHTML = '';\n\t\t}\n\t}\n\n\t/**\n\t * Get current group.\n\t */\n\tget group(): string {\n\t\t// Return current group.\n\t\treturn this.currentGroup;\n\t}\n\n\t/**\n\t * Set current group.\n\t *\n\t * @param {string} group Group name.\n\t */\n\tset group( group: string ) {\n\t\t// Set current group.\n\t\tthis.currentGroup = group;\n\t}\n\n\t/**\n\t * Get current index.\n\t */\n\tget currentIndex(): number {\n\t\t// Return current index.\n\t\treturn parseInt( this.getAttribute( 'index' ) ?? '1' );\n\t}\n\n\t/**\n\t * Set current index.\n\t *\n\t * @param {number} index Current index.\n\t */\n\tset currentIndex( index: number ) {\n\t\t// Set current index.\n\t\tif ( index < 1 ) {\n\t\t\tindex = 1;\n\t\t}\n\n\t\t// Setting this attributes triggers a re-trigger.\n\t\tthis.setAttribute( 'index', index.toString() );\n\n\t\t// dispatch slide-set event.\n\t\tthis.dispatchEvent( new CustomEvent( 'slide-set', {\n\t\t\tdetail: {\n\t\t\t\tslideIndex: index,\n\t\t\t},\n\t\t} ) );\n\t}\n\n\t/**\n\t * Trigger the target that matches the current index within current group.\n\t */\n\ttriggerCurrentIndexTarget(): void {\n\t\t// Get all groups and check if current index exists within group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Bail early if we don't have groups.\n\t\tif ( ! allGroups || ! allGroups[ this.currentIndex - 1 ] ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Trigger element within group.\n\t\tallGroups[ this.currentIndex - 1 ].trigger();\n\t}\n\n\t/**\n\t * Open lightbox.\n\t */\n\topen(): void {\n\t\t// Get the dialog element.\n\t\tconst dialog: HTMLDialogElement | null = this.querySelector( 'dialog' );\n\n\t\t// Check if dialog exists or is already open.\n\t\tif ( ! dialog || dialog.open ) {\n\t\t\t// Yes it is, Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Save the currently focused element to restore later (if manage-focus is enabled).\n\t\tif ( 'no' !== this.getAttribute( 'manage-focus' ) ) {\n\t\t\tthis.previouslyFocusedElement = this.ownerDocument.activeElement as HTMLElement;\n\t\t}\n\n\t\t// First, take this opportunity to update all groups (if it wasn't set from the trigger).\n\t\tif ( '' !== this.group && ! this.allGroups ) {\n\t\t\tthis.updateAllGroups();\n\t\t}\n\n\t\t// Now, show the modal.\n\t\tdialog.showModal();\n\t\tthis.setAttribute( 'open', 'yes' );\n\n\t\t// Add keyboard event listener for arrow navigation.\n\t\tdocument.addEventListener( 'keydown', this.boundHandleKeyDown );\n\n\t\t// Move focus into the lightbox (if manage-focus is enabled).\n\t\tif ( 'no' !== this.getAttribute( 'manage-focus' ) ) {\n\t\t\tthis.setInitialFocus();\n\t\t}\n\t}\n\n\t/**\n\t * Close lightbox.\n\t */\n\tclose(): void {\n\t\t// Remove keyboard event listener.\n\t\tdocument.removeEventListener( 'keydown', this.boundHandleKeyDown );\n\n\t\t// Find and close the dialog.\n\t\tconst dialog: HTMLDialogElement | null = this.querySelector( 'dialog' );\n\t\tdialog?.close();\n\t\tthis.removeAttribute( 'open' );\n\n\t\t// Restore focus to the previously focused element (if manage-focus is enabled).\n\t\tif ( 'no' !== this.getAttribute( 'manage-focus' ) && this.previouslyFocusedElement ) {\n\t\t\tthis.previouslyFocusedElement.focus();\n\t\t\tthis.previouslyFocusedElement = null;\n\t\t}\n\n\t\t// Clear groups from memory.\n\t\tthis.allGroups = null;\n\t}\n\n\t/**\n\t * Navigate previous.\n\t */\n\tprevious(): void {\n\t\t// Check if we even have a group.\n\t\tif ( '' === this.group ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have elements within group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Bail early if we don't have groups.\n\t\tif ( ! allGroups ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Decrement the current index.\n\t\tif ( this.currentIndex > 1 ) {\n\t\t\tthis.currentIndex--;\n\t\t}\n\t}\n\n\t/**\n\t * Navigate next.\n\t */\n\tnext(): void {\n\t\t// Check if we even have a group.\n\t\tif ( '' === this.group ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have elements within group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Bail early if we don't have groups.\n\t\tif ( ! allGroups ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Increment the current index.\n\t\tif ( this.currentIndex < allGroups.length ) {\n\t\t\tthis.currentIndex++;\n\t\t}\n\t}\n\n\t/**\n\t * Update all groups and save it to memory.\n\t *\n\t * @param {NodeList} allGroups All groups.\n\t */\n\tupdateAllGroups( allGroups: NodeListOf<TPLightboxTriggerElement> | null = null ): void {\n\t\t// Update all groups.\n\t\tif ( allGroups && allGroups.length ) {\n\t\t\tthis.allGroups = allGroups;\n\t\t\tthis.setAttribute( 'total', this.allGroups.length.toString() );\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get all groups.\n\t\tthis.allGroups = document.querySelectorAll( `tp-lightbox-trigger[group=\"${ this.group }\"]` );\n\n\t\t// Update total.\n\t\tif ( ! this.allGroups.length ) {\n\t\t\tthis.allGroups = null;\n\t\t} else {\n\t\t\tthis.setAttribute( 'total', this.allGroups.length.toString() );\n\t\t}\n\t}\n\n\t/**\n\t * Get all groups from memory.\n\t */\n\tgetAllGroups(): NodeListOf<TPLightboxTriggerElement> | null {\n\t\t// Return all groups.\n\t\treturn this.allGroups;\n\t}\n\n\t/**\n\t * Prepare navigation.\n\t */\n\tprepareNavigation(): void {\n\t\t// Update counter.\n\t\tconst count: TPLightboxCountElement | null = this.querySelector( 'tp-lightbox-count' );\n\t\tcount?.update();\n\n\t\t// Get previous and next elements.\n\t\tconst previous: TPLightboxPreviousElement | null = this.querySelector( 'tp-lightbox-previous' );\n\t\tconst next: TPLightboxNextElement | null = this.querySelector( 'tp-lightbox-next' );\n\n\t\t// Bail early if we don't have either.\n\t\tif ( ! previous && ! next ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get buttons inside prev/next for ARIA.\n\t\tconst previousButton: HTMLButtonElement | null = previous?.querySelector( 'button' ) ?? null;\n\t\tconst nextButton: HTMLButtonElement | null = next?.querySelector( 'button' ) ?? null;\n\t\tconst ariaEnabled: boolean = this.isAriaEnabled();\n\n\t\t// Check if we have a group.\n\t\tif ( '' === this.group ) {\n\t\t\tprevious?.setAttribute( 'disabled', 'yes' );\n\t\t\tnext?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on buttons.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t\tnextButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have elements within the group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Disable if we don't have any.\n\t\tif ( ! allGroups ) {\n\t\t\tprevious?.setAttribute( 'disabled', 'yes' );\n\t\t\tnext?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on buttons.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t\tnextButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Enable / disable previous navigation.\n\t\tif ( this.currentIndex <= 1 ) {\n\t\t\tprevious?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on previous button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\t\t} else {\n\t\t\tprevious?.removeAttribute( 'disabled' );\n\n\t\t\t// Remove aria-disabled from previous button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.removeAttribute( 'aria-disabled' );\n\t\t\t}\n\t\t}\n\n\t\t// Enable / disable next navigation.\n\t\tif ( this.currentIndex < allGroups.length ) {\n\t\t\tnext?.removeAttribute( 'disabled' );\n\n\t\t\t// Remove aria-disabled from next button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\t// Next is at the end, disable it.\n\t\t\t\tnextButton?.removeAttribute( 'aria-disabled' );\n\t\t\t}\n\t\t} else {\n\t\t\tnext?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on next button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tnextButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Prepare image loading.\n\t */\n\tprepareImageLoading(): void {\n\t\t// Get lightbox content element.\n\t\tconst content: TPLightboxContentElement | null = this.querySelector( 'tp-lightbox-content' );\n\n\t\t// Bail early if we don't have content.\n\t\tif ( ! content ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Bail if there are no images within current content.\n\t\tconst images: NodeListOf<HTMLImageElement> = content.querySelectorAll( 'img' );\n\n\t\t// Exit early if there are no images.\n\t\tif ( ! images.length ) {\n\t\t\tthis.removeAttribute( 'loading' );\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Start off by setting the state as loading.\n\t\tthis.setAttribute( 'loading', 'yes' );\n\n\t\t// Prepare increment variables.\n\t\tlet counter: number = 0;\n\t\tconst totalImages: number = images.length;\n\n\t\t/**\n\t\t * Increment counter.\n\t\t */\n\t\tconst incrementLoadingCounter = (): void => {\n\t\t\t// Increment\n\t\t\tcounter++;\n\n\t\t\t// Remove loading attribute once all images have loaded.\n\t\t\tif ( counter === totalImages ) {\n\t\t\t\tthis.removeAttribute( 'loading' );\n\t\t\t}\n\t\t};\n\n\t\t// Check if images have loaded, else add an event listener.\n\t\timages.forEach( ( image: HTMLImageElement ): void => {\n\t\t\t// Check if image has loaded.\n\t\t\tif ( image.complete ) {\n\t\t\t\tincrementLoadingCounter();\n\t\t\t} else {\n\t\t\t\timage.addEventListener( 'load', incrementLoadingCounter, { once: true } );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Handle when the dialog is clicked.\n\t *\n\t * @param {Event} e Click event.\n\t */\n\thandleDialogClick( e: MouseEvent ): void {\n\t\t// Close on overlay click.\n\t\tif (\n\t\t\t'yes' === this.getAttribute( 'close-on-overlay-click' ) &&\n\t\t\tthis.querySelector( 'dialog' ) === e.target\n\t\t) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/**\n\t * Handles the touch start event.\n\t *\n\t * @param { TouchEvent } evt The touch event.\n\t */\n\thandleTouchStart( evt: TouchEvent ): void {\n\t\t// Check if we should allow swiping?\n\t\tif ( 'yes' !== this.getAttribute( 'swipe' ) ) {\n\t\t\t// Nope.\n\t\t\treturn;\n\t\t}\n\n\t\t// Set the start points.\n\t\tthis.touchStartX = evt.touches[ 0 ].clientX;\n\t\tthis.touchStartY = evt.touches[ 0 ].clientY;\n\t}\n\n\t/**\n\t * Handles the touch end event.\n\t *\n\t * @param { TouchEvent } evt The touch event.\n\t */\n\thandleTouchEnd( evt: TouchEvent ): void {\n\t\t// Check if we should allow swiping?\n\t\tif ( 'yes' !== this.getAttribute( 'swipe' ) ) {\n\t\t\t// Nope.\n\t\t\treturn;\n\t\t}\n\n\t\t// Calculate the distances.\n\t\tconst touchEndX: number = evt.changedTouches[ 0 ].clientX;\n\t\tconst touchEndY: number = evt.changedTouches[ 0 ].clientY;\n\t\tconst swipeDistanceX: number = touchEndX - this.touchStartX;\n\t\tconst swipeDistanceY: number = touchEndY - this.touchStartY;\n\n\t\t// Is this horizontal swipe?\n\t\tconst isHorizontalSwipe = Math.abs( swipeDistanceX ) > Math.abs( swipeDistanceY );\n\n\t\t// Check if this was a horizontal swipe?\n\t\tif ( ! isHorizontalSwipe ) {\n\t\t\t// Bail.\n\t\t\treturn;\n\t\t}\n\n\t\t// Swipe settings\n\t\tthis.swipeThreshold = Number( this.getAttribute( 'swipe-threshold' ) ?? '200' );\n\n\t\t// Check if it's a right or left swipe.\n\t\tif ( swipeDistanceX > 0 ) {\n\t\t\t// Right-Swipe: Check if horizontal swipe distance is less than the threshold.\n\t\t\tif ( swipeDistanceX < this.swipeThreshold ) {\n\t\t\t\tthis.previous();\n\t\t\t}\n\t\t} else if ( swipeDistanceX < 0 ) {\n\t\t\t// Left-Swipe: Check if horizontal swipe distance is less than the threshold.\n\t\t\tif ( swipeDistanceX > -this.swipeThreshold ) {\n\t\t\t\tthis.next();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Update current item in navigation.\n\t */\n\tupdateNavCurrentItem(): void {\n\t\t// Bail if we don't have nav items.\n\t\tif ( ! this.lightboxNavItems ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if ARIA management is enabled.\n\t\tconst ariaEnabled = this.isAriaEnabled();\n\n\t\t// Update current item.\n\t\tthis.lightboxNavItems.forEach( ( navItem: TPLightboxNavItemElement, index: number ): void => {\n\t\t\t// Get the button inside the nav item.\n\t\t\tconst button: HTMLButtonElement | null = navItem.querySelector( 'button' );\n\n\t\t\t// Update current attribute.\n\t\t\tif ( this.currentIndex - 1 === index ) {\n\t\t\t\tnavItem.setAttribute( 'current', 'yes' );\n\n\t\t\t\t// Set aria-current on the button (if ARIA is enabled).\n\t\t\t\tif ( ariaEnabled && button ) {\n\t\t\t\t\tbutton.setAttribute( 'aria-current', 'true' );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnavItem.removeAttribute( 'current' );\n\n\t\t\t\t// Remove aria-current from the button (if ARIA is enabled).\n\t\t\t\tif ( ariaEnabled && button ) {\n\t\t\t\t\tbutton.removeAttribute( 'aria-current' );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Set initial focus when lightbox opens.\n\t * Looks for [autofocus] element, otherwise focuses the dialog.\n\t */\n\tprivate setInitialFocus(): void {\n\t\t// Look for an element with autofocus attribute.\n\t\tconst autofocusElement = this.querySelector<HTMLElement>( '[autofocus]' );\n\n\t\t// Do we have an autofocus element?\n\t\tif ( autofocusElement ) {\n\t\t\tautofocusElement.focus();\n\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise, focus the dialog itself.\n\t\tthis.dialogElement?.focus();\n\t}\n\n\t/**\n\t * Handle keydown events for arrow navigation.\n\t *\n\t * @param {KeyboardEvent} e Keyboard event.\n\t */\n\tprivate handleKeyDown( e: KeyboardEvent ): void {\n\t\t// Check if arrow navigation is enabled (disabled by default).\n\t\tif ( 'yes' !== this.getAttribute( 'arrow-navigation' ) ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Navigate on arrow keys.\n\t\tif ( 'ArrowLeft' === e.key ) {\n\t\t\te.preventDefault();\n\t\t\tthis.previous();\n\t\t} else if ( 'ArrowRight' === e.key ) {\n\t\t\te.preventDefault();\n\t\t\tthis.next();\n\t\t}\n\t}\n}\n","/**\n * TP Lightbox Content.\n */\nexport class TPLightboxContentElement extends HTMLElement {\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Close.\n */\nexport class TPLightboxCloseElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.close.bind( this ) );\n\t}\n\n\t/**\n\t * Close the lightbox.\n\t */\n\tclose(): void {\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( lightbox ) {\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// Close the lightbox.\n\t\t\t\tlightbox.close();\n\t\t\t}, 0 );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Close.\n */\nexport class TPLightboxPreviousElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.previous.bind( this ) );\n\t}\n\n\t/**\n\t * Navigate previous.\n\t */\n\tprevious(): void {\n\t\t// Check if we are disabled.\n\t\tif ( 'yes' === this.getAttribute( 'disabled' ) ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( lightbox ) {\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// Previous.\n\t\t\t\tlightbox.previous();\n\t\t\t}, 0 );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Close.\n */\nexport class TPLightboxNextElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.next.bind( this ) );\n\t}\n\n\t/**\n\t * Navigate next.\n\t */\n\tnext(): void {\n\t\t// Check if next is disabled.\n\t\tif ( 'yes' === this.getAttribute( 'disabled' ) ) {\n\t\t\t// Yes it is. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( lightbox ) {\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// Initiate next.\n\t\t\t\tlightbox.next();\n\t\t\t}, 0 );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Slider Count.\n */\nexport class TPLightboxCountElement extends HTMLElement {\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} Observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Attributes to observe.\n\t\treturn [ 'format' ];\n\t}\n\n\t/**\n\t * Get format.\n\t *\n\t * @return {string} Format.\n\t */\n\tget format(): string {\n\t\t// Get format.\n\t\treturn this.getAttribute( 'format' ) ?? '$current / $total';\n\t}\n\n\t/**\n\t * Set format.\n\t *\n\t * @param {string} format Format.\n\t */\n\tset format( format: string ) {\n\t\t// Set the 'format' attribute value.\n\t\tthis.setAttribute( 'format', format );\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t */\n\tattributeChangedCallback(): void {\n\t\t// On change of format attribute, update the component.\n\t\tthis.update();\n\t}\n\n\t/**\n\t * Update component.\n\t */\n\tupdate(): void {\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( ! lightbox ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get current and total.\n\t\tconst current: string = lightbox.currentIndex.toString();\n\t\tconst total: string = lightbox.getAttribute( 'total' ) ?? '';\n\n\t\t// Update variables in format attribute (using textContent for XSS protection).\n\t\tthis.textContent =\n\t\t\tthis.format\n\t\t\t\t.replace( '$current', current )\n\t\t\t\t.replace( '$total', total );\n\n\t\t// Update current and total attributes.\n\t\tthis.setAttribute( 'current', current );\n\t\tthis.setAttribute( 'total', total );\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Trigger.\n */\nexport class TPLightboxTriggerElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.trigger.bind( this ) );\n\t}\n\n\t/**\n\t * Trigger the lightbox.\n\t */\n\ttrigger(): void {\n\t\t// Get lightbox ID and template.\n\t\tconst lightboxId: string | null = this.getAttribute( 'lightbox' );\n\t\tconst template: HTMLTemplateElement | null = this.querySelector( 'template' );\n\n\t\t// We can't proceed without them.\n\t\tif ( ! lightboxId || ! template ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the lightbox.\n\t\tconst lightbox: TPLightboxElement | null = document.querySelector( `#${ lightboxId.toString() }` );\n\n\t\t// Check to see if we have a lightbox.\n\t\tif ( ! lightbox ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check to see if we have a group.\n\t\tconst group: string = this.getAttribute( 'group' ) ?? '';\n\n\t\t// Yield to main thread.\n\t\tsetTimeout( (): void => {\n\t\t\t// Prepare lightbox.\n\t\t\tlightbox.template = template;\n\t\t\tlightbox.group = group;\n\n\t\t\t// Set index and group if we have them.\n\t\t\tif ( '' !== group ) {\n\t\t\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> = document.querySelectorAll( `tp-lightbox-trigger[group=\"${ group }\"]` );\n\n\t\t\t\t// Update all groups.\n\t\t\t\tif ( allGroups.length ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * We do this when we're opening a lightbox, or navigating.\n\t\t\t\t\t * This allows consumers to inject elements at any point.\n\t\t\t\t\t */\n\t\t\t\t\tlightbox.updateAllGroups( allGroups );\n\n\t\t\t\t\t// Get current trigger's index within the group.\n\t\t\t\t\tallGroups.forEach( ( triggerElement: TPLightboxTriggerElement, index: number ): void => {\n\t\t\t\t\t\t// Update current index.\n\t\t\t\t\t\tif ( this === triggerElement ) {\n\t\t\t\t\t\t\tlightbox.currentIndex = index + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// All done, lets open the lightbox.\n\t\t\tlightbox.open();\n\t\t}, 0 );\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Nav.\n */\nexport class TPLightboxNavElement extends HTMLElement {\n\t/**\n\t * Properties.\n\t */\n\tprotected template: HTMLTemplateElement | null = null;\n\tprotected lightbox : TPLightboxElement | null;\n\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Initialize properties.\n\t\tthis.template = this.querySelector( 'template' );\n\t\tthis.lightbox = this.closest( 'tp-lightbox' );\n\n\t\t// Add event listener.\n\t\tthis.lightbox?.addEventListener( 'template-set', this.setTemplate.bind( this ) );\n\t}\n\n\t/**\n\t * Set the template.\n\t */\n\tsetTemplate(): void {\n\t\t// Bail if no template.\n\t\tif ( ! this.template ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Total slides.\n\t\tconst totalSlides = Number( this.lightbox?.getAttribute( 'total' ) ?? 0 );\n\n\t\t// Clear the navigation.\n\t\tthis.innerHTML = '';\n\n\t\t// Append the navigation items.\n\t\tfor ( let i = 0; i < totalSlides; i++ ) {\n\t\t\t// Clone the template.\n\t\t\tconst navItem = this.template.content.cloneNode( true );\n\n\t\t\t// Append the clone.\n\t\t\tthis.appendChild( navItem );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\nimport { TPLightboxNavElement } from './tp-lightbox-nav';\n\n/**\n * TP Lightbox Nav Item.\n */\nexport class TPLightboxNavItemElement extends HTMLElement {\n\t/**\n\t * Properties.\n\t */\n\tprotected lightbox : TPLightboxElement | null;\n\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\t\tthis.lightbox = this.closest( 'tp-lightbox' );\n\n\t\t// Get the nav-item button.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.handleClick.bind( this ) );\n\t}\n\n\t/**\n\t * Handle when the button is clicked.\n\t */\n\thandleClick(): void {\n\t\t// Check if lightbox exists.\n\t\tif ( ! this.lightbox ) {\n\t\t\t// No its not! Terminate.\n\t\t\treturn;\n\t\t}\n\n\t\t// Set current slide.\n\t\tthis.lightbox.currentIndex = Number( this.getIndex() ) ?? 1;\n\n\t\t// Update navigation current item.\n\t\tthis.lightbox.updateNavCurrentItem();\n\t}\n\n\t/**\n\t * Get index of this item inside the navigation.\n\t *\n\t * @return {number} Index.\n\t */\n\tgetIndex(): number {\n\t\t// Bail if no lightbox.\n\t\tif ( ! this.lightbox ) {\n\t\t\t// Exit.\n\t\t\treturn 0;\n\t\t}\n\n\t\t// No, find it in the navigation.\n\t\tconst lightboxNav: TPLightboxNavElement | null = this.closest( 'tp-lightbox-nav' );\n\n\t\t// Return index of this element considering the step value.\n\t\treturn ( Array.from( lightboxNav?.children ?? [] ).indexOf( this ) ) + 1;\n\t}\n}\n","/**\n * Styles.\n */\nimport './style.scss';\n\n/**\n * Components.\n */\nimport { TPLightboxElement } from './tp-lightbox';\nimport { TPLightboxContentElement } from './tp-lightbox-content';\nimport { TPLightboxCloseElement } from './tp-lightbox-close';\nimport { TPLightboxPreviousElement } from './tp-lightbox-previous';\nimport { TPLightboxNextElement } from './tp-lightbox-next';\nimport { TPLightboxCountElement } from './tp-lightbox-count';\nimport { TPLightboxTriggerElement } from './tp-lightbox-trigger';\nimport { TPLightboxNavElement } from './tp-lightbox-nav';\nimport { TPLightboxNavItemElement } from './tp-lightbox-nav-item';\n\n/**\n * Register Components.\n */\ncustomElements.define( 'tp-lightbox', TPLightboxElement );\ncustomElements.define( 'tp-lightbox-content', TPLightboxContentElement );\ncustomElements.define( 'tp-lightbox-close', TPLightboxCloseElement );\ncustomElements.define( 'tp-lightbox-previous', TPLightboxPreviousElement );\ncustomElements.define( 'tp-lightbox-next', TPLightboxNextElement );\ncustomElements.define( 'tp-lightbox-count', TPLightboxCountElement );\ncustomElements.define( 'tp-lightbox-trigger', TPLightboxTriggerElement );\ncustomElements.define( 'tp-lightbox-nav', TPLightboxNavElement );\ncustomElements.define( 'tp-lightbox-nav-item', TPLightboxNavItemElement );\n"],"names":["TPLightboxElement","HTMLElement","constructor","super","currentTemplate","currentGroup","allGroups","touchStartX","touchStartY","swipeThreshold","previouslyFocusedElement","this","boundHandleKeyDown","handleKeyDown","bind","dialogElement","querySelector","lightboxNavItems","querySelectorAll","addEventListener","handleDialogClick","handleTouchStart","handleTouchEnd","observedAttributes","attributeChangedCallback","name","oldValue","newValue","dispatchEvent","CustomEvent","triggerCurrentIndexTarget","updateNavCurrentItem","isAriaEnabled","getAttribute","template","content","templateContent","cloneNode","replaceChildren","setTimeout","prepareImageLoading","prepareNavigation","innerHTML","group","currentIndex","parseInt","index","setAttribute","toString","detail","slideIndex","getAllGroups","trigger","open","dialog","ownerDocument","activeElement","updateAllGroups","showModal","document","setInitialFocus","close","removeEventListener","removeAttribute","focus","previous","next","length","count","update","previousButton","nextButton","ariaEnabled","images","counter","totalImages","incrementLoadingCounter","forEach","image","complete","once","e","target","evt","touches","clientX","clientY","touchEndX","changedTouches","touchEndY","swipeDistanceX","swipeDistanceY","Math","abs","Number","navItem","button","autofocusElement","key","preventDefault","TPLightboxContentElement","TPLightboxCloseElement","lightbox","closest","TPLightboxPreviousElement","TPLightboxNextElement","TPLightboxCountElement","format","current","total","textContent","replace","TPLightboxTriggerElement","lightboxId","triggerElement","TPLightboxNavElement","setTemplate","totalSlides","i","appendChild","TPLightboxNavItemElement","handleClick","getIndex","lightboxNav","Array","from","children","indexOf","customElements","define"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"dist/lightbox/index.js","mappings":"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","sources":["webpack://@travelopia/web-components/./src/lightbox/tp-lightbox.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-content.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-close.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-previous.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-next.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-count.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-trigger.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-nav.ts","webpack://@travelopia/web-components/./src/lightbox/tp-lightbox-nav-item.ts","webpack://@travelopia/web-components/./src/lightbox/index.ts"],"sourcesContent":["/**\n * Internal dependencies.\n */\nimport { TPLightboxContentElement } from './tp-lightbox-content';\nimport { TPLightboxPreviousElement } from './tp-lightbox-previous';\nimport { TPLightboxNextElement } from './tp-lightbox-next';\nimport { TPLightboxTriggerElement } from './tp-lightbox-trigger';\nimport { TPLightboxCountElement } from './tp-lightbox-count';\nimport { TPLightboxNavItemElement } from './tp-lightbox-nav-item';\n\n/**\n * TP Lightbox.\n */\nexport class TPLightboxElement extends HTMLElement {\n\t/**\n\t * Properties.\n\t */\n\tprotected currentTemplate: HTMLTemplateElement | null = null;\n\tprotected currentGroup: string = '';\n\tprotected allGroups: NodeListOf<TPLightboxTriggerElement> | null = null;\n\tprotected touchStartX: number = 0;\n\tprotected touchStartY: number = 0;\n\tprotected swipeThreshold: number = 200;\n\tprotected dialogElement: HTMLDialogElement | null;\n\tprotected lightboxNavItems: NodeListOf<TPLightboxNavItemElement> | null;\n\tprotected previouslyFocusedElement: HTMLElement | null = null;\n\tprotected readonly boundHandleKeyDown: ( e: KeyboardEvent ) => void;\n\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Bind event handlers.\n\t\tthis.boundHandleKeyDown = this.handleKeyDown.bind( this );\n\n\t\t// Initialize\n\t\tthis.dialogElement = this.querySelector( 'dialog' );\n\t\tthis.lightboxNavItems = this.querySelectorAll( 'tp-lightbox-nav-item' );\n\n\t\t// Event listeners.\n\t\tthis.dialogElement?.addEventListener( 'click', this.handleDialogClick.bind( this ) );\n\t\tthis.dialogElement?.addEventListener( 'touchstart', this.handleTouchStart.bind( this ) );\n\t\tthis.dialogElement?.addEventListener( 'touchend', this.handleTouchEnd.bind( this ) );\n\t\tthis.dialogElement?.addEventListener( 'close', this.handleDialogClose.bind( this ) );\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Attributes to observe.\n\t\treturn [ 'open', 'index', 'total', 'close-on-overlay-click', 'loading' ];\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string = '', oldValue: string = '', newValue: string = '' ): void {\n\t\t// Prevent redundant updates.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Trigger change event.\n\t\tthis.dispatchEvent( new CustomEvent( 'change' ) );\n\n\t\t// Trigger current index target if index has changed.\n\t\tif ( 'index' === name ) {\n\t\t\tthis.triggerCurrentIndexTarget();\n\t\t}\n\n\t\t// Trigger navigation update if open or index has changed.\n\t\tif ( 'open' === name || 'index' === name ) {\n\t\t\tthis.updateNavCurrentItem();\n\t\t}\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA is enabled.\n\t */\n\tisAriaEnabled(): boolean {\n\t\t// Return whether ARIA management is enabled (default: yes).\n\t\treturn 'no' !== this.getAttribute( 'aria' );\n\t}\n\n\t/**\n\t * Get template.\n\t */\n\tget template(): HTMLTemplateElement | null {\n\t\t// Return current template.\n\t\treturn this.currentTemplate;\n\t}\n\n\t/**\n\t * Set template.\n\t *\n\t * @param {HTMLTemplateElement} template The template.\n\t */\n\tset template( template: HTMLTemplateElement | null ) {\n\t\t// Set the template.\n\t\tthis.currentTemplate = template;\n\t\tthis.dispatchEvent( new CustomEvent( 'template-set' ) );\n\n\t\t// Get lightbox content element.\n\t\tconst content: TPLightboxContentElement | null = this.querySelector( 'tp-lightbox-content' );\n\n\t\t// Check if we have a content.\n\t\tif ( ! content ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have a template.\n\t\tif ( this.currentTemplate ) {\n\t\t\t/**\n\t\t\t * We do, update content with template's content.\n\t\t\t * We do this rather than a string to avoid script injection.\n\t\t\t */\n\t\t\tconst templateContent: Node = this.currentTemplate.content.cloneNode( true );\n\t\t\tcontent.replaceChildren( templateContent );\n\t\t\tthis.dispatchEvent( new CustomEvent( 'content-change' ) );\n\n\t\t\t// Prepare image loading.\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// We do, prepare image loading.\n\t\t\t\tthis.prepareImageLoading();\n\t\t\t\tthis.prepareNavigation();\n\t\t\t}, 0 );\n\t\t} else {\n\t\t\t// We don't, set content as empty.\n\t\t\tcontent.innerHTML = '';\n\t\t}\n\t}\n\n\t/**\n\t * Get current group.\n\t */\n\tget group(): string {\n\t\t// Return current group.\n\t\treturn this.currentGroup;\n\t}\n\n\t/**\n\t * Set current group.\n\t *\n\t * @param {string} group Group name.\n\t */\n\tset group( group: string ) {\n\t\t// Set current group.\n\t\tthis.currentGroup = group;\n\t}\n\n\t/**\n\t * Get current index.\n\t */\n\tget currentIndex(): number {\n\t\t// Return current index.\n\t\treturn parseInt( this.getAttribute( 'index' ) ?? '1' );\n\t}\n\n\t/**\n\t * Set current index.\n\t *\n\t * @param {number} index Current index.\n\t */\n\tset currentIndex( index: number ) {\n\t\t// Set current index.\n\t\tif ( index < 1 ) {\n\t\t\tindex = 1;\n\t\t}\n\n\t\t// Setting this attributes triggers a re-trigger.\n\t\tthis.setAttribute( 'index', index.toString() );\n\n\t\t// dispatch slide-set event.\n\t\tthis.dispatchEvent( new CustomEvent( 'slide-set', {\n\t\t\tdetail: {\n\t\t\t\tslideIndex: index,\n\t\t\t},\n\t\t} ) );\n\t}\n\n\t/**\n\t * Trigger the target that matches the current index within current group.\n\t */\n\ttriggerCurrentIndexTarget(): void {\n\t\t// Get all groups and check if current index exists within group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Bail early if we don't have groups.\n\t\tif ( ! allGroups || ! allGroups[ this.currentIndex - 1 ] ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Trigger element within group.\n\t\tallGroups[ this.currentIndex - 1 ].trigger();\n\t}\n\n\t/**\n\t * Open lightbox.\n\t */\n\topen(): void {\n\t\t// Get the dialog element.\n\t\tconst dialog: HTMLDialogElement | null = this.querySelector( 'dialog' );\n\n\t\t// Check if dialog exists or is already open.\n\t\tif ( ! dialog || dialog.open ) {\n\t\t\t// Yes it is, Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Save the currently focused element to restore later (if manage-focus is enabled).\n\t\tif ( 'no' !== this.getAttribute( 'manage-focus' ) ) {\n\t\t\tthis.previouslyFocusedElement = this.ownerDocument.activeElement as HTMLElement;\n\t\t}\n\n\t\t// First, take this opportunity to update all groups (if it wasn't set from the trigger).\n\t\tif ( '' !== this.group && ! this.allGroups ) {\n\t\t\tthis.updateAllGroups();\n\t\t}\n\n\t\t// Now, show the modal.\n\t\tdialog.showModal();\n\t\tthis.setAttribute( 'open', 'yes' );\n\n\t\t// Add keyboard event listener for arrow navigation.\n\t\tdocument.addEventListener( 'keydown', this.boundHandleKeyDown );\n\n\t\t// Move focus into the lightbox (if manage-focus is enabled).\n\t\tif ( 'no' !== this.getAttribute( 'manage-focus' ) ) {\n\t\t\tthis.setInitialFocus();\n\t\t}\n\t}\n\n\t/**\n\t * Close lightbox.\n\t */\n\tclose(): void {\n\t\t// Remove keyboard event listener.\n\t\tdocument.removeEventListener( 'keydown', this.boundHandleKeyDown );\n\n\t\t// Find and close the dialog.\n\t\tconst dialog: HTMLDialogElement | null = this.querySelector( 'dialog' );\n\t\tdialog?.close();\n\t\tthis.removeAttribute( 'open' );\n\n\t\t// Restore focus to the previously focused element (if manage-focus is enabled).\n\t\tif ( 'no' !== this.getAttribute( 'manage-focus' ) && this.previouslyFocusedElement ) {\n\t\t\tthis.previouslyFocusedElement.focus();\n\t\t\tthis.previouslyFocusedElement = null;\n\t\t}\n\n\t\t// Clear groups from memory.\n\t\tthis.allGroups = null;\n\t}\n\n\t/**\n\t * Navigate previous.\n\t */\n\tprevious(): void {\n\t\t// Check if we even have a group.\n\t\tif ( '' === this.group ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have elements within group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Bail early if we don't have groups.\n\t\tif ( ! allGroups ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Decrement the current index.\n\t\tif ( this.currentIndex > 1 ) {\n\t\t\tthis.currentIndex--;\n\t\t}\n\t}\n\n\t/**\n\t * Navigate next.\n\t */\n\tnext(): void {\n\t\t// Check if we even have a group.\n\t\tif ( '' === this.group ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have elements within group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Bail early if we don't have groups.\n\t\tif ( ! allGroups ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Increment the current index.\n\t\tif ( this.currentIndex < allGroups.length ) {\n\t\t\tthis.currentIndex++;\n\t\t}\n\t}\n\n\t/**\n\t * Update all groups and save it to memory.\n\t *\n\t * @param {NodeList} allGroups All groups.\n\t */\n\tupdateAllGroups( allGroups: NodeListOf<TPLightboxTriggerElement> | null = null ): void {\n\t\t// Update all groups.\n\t\tif ( allGroups && allGroups.length ) {\n\t\t\tthis.allGroups = allGroups;\n\t\t\tthis.setAttribute( 'total', this.allGroups.length.toString() );\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get all groups.\n\t\tthis.allGroups = document.querySelectorAll( `tp-lightbox-trigger[group=\"${ this.group }\"]` );\n\n\t\t// Update total.\n\t\tif ( ! this.allGroups.length ) {\n\t\t\tthis.allGroups = null;\n\t\t} else {\n\t\t\tthis.setAttribute( 'total', this.allGroups.length.toString() );\n\t\t}\n\t}\n\n\t/**\n\t * Get all groups from memory.\n\t */\n\tgetAllGroups(): NodeListOf<TPLightboxTriggerElement> | null {\n\t\t// Return all groups.\n\t\treturn this.allGroups;\n\t}\n\n\t/**\n\t * Prepare navigation.\n\t */\n\tprepareNavigation(): void {\n\t\t// Update counter.\n\t\tconst count: TPLightboxCountElement | null = this.querySelector( 'tp-lightbox-count' );\n\t\tcount?.update();\n\n\t\t// Get previous and next elements.\n\t\tconst previous: TPLightboxPreviousElement | null = this.querySelector( 'tp-lightbox-previous' );\n\t\tconst next: TPLightboxNextElement | null = this.querySelector( 'tp-lightbox-next' );\n\n\t\t// Bail early if we don't have either.\n\t\tif ( ! previous && ! next ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get buttons inside prev/next for ARIA.\n\t\tconst previousButton: HTMLButtonElement | null = previous?.querySelector( 'button' ) ?? null;\n\t\tconst nextButton: HTMLButtonElement | null = next?.querySelector( 'button' ) ?? null;\n\t\tconst ariaEnabled: boolean = this.isAriaEnabled();\n\n\t\t// Check if we have a group.\n\t\tif ( '' === this.group ) {\n\t\t\tprevious?.setAttribute( 'disabled', 'yes' );\n\t\t\tnext?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on buttons.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t\tnextButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if we have elements within the group.\n\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> | null = this.getAllGroups();\n\n\t\t// Disable if we don't have any.\n\t\tif ( ! allGroups ) {\n\t\t\tprevious?.setAttribute( 'disabled', 'yes' );\n\t\t\tnext?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on buttons.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t\tnextButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Enable / disable previous navigation.\n\t\tif ( this.currentIndex <= 1 ) {\n\t\t\tprevious?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on previous button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\t\t} else {\n\t\t\tprevious?.removeAttribute( 'disabled' );\n\n\t\t\t// Remove aria-disabled from previous button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tpreviousButton?.removeAttribute( 'aria-disabled' );\n\t\t\t}\n\t\t}\n\n\t\t// Enable / disable next navigation.\n\t\tif ( this.currentIndex < allGroups.length ) {\n\t\t\tnext?.removeAttribute( 'disabled' );\n\n\t\t\t// Remove aria-disabled from next button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\t// Next is at the end, disable it.\n\t\t\t\tnextButton?.removeAttribute( 'aria-disabled' );\n\t\t\t}\n\t\t} else {\n\t\t\tnext?.setAttribute( 'disabled', 'yes' );\n\n\t\t\t// Set aria-disabled on next button.\n\t\t\tif ( ariaEnabled ) {\n\t\t\t\tnextButton?.setAttribute( 'aria-disabled', 'true' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Prepare image loading.\n\t */\n\tprepareImageLoading(): void {\n\t\t// Get lightbox content element.\n\t\tconst content: TPLightboxContentElement | null = this.querySelector( 'tp-lightbox-content' );\n\n\t\t// Bail early if we don't have content.\n\t\tif ( ! content ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Bail if there are no images within current content.\n\t\tconst images: NodeListOf<HTMLImageElement> = content.querySelectorAll( 'img' );\n\n\t\t// Exit early if there are no images.\n\t\tif ( ! images.length ) {\n\t\t\tthis.removeAttribute( 'loading' );\n\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Start off by setting the state as loading.\n\t\tthis.setAttribute( 'loading', 'yes' );\n\n\t\t// Prepare increment variables.\n\t\tlet counter: number = 0;\n\t\tconst totalImages: number = images.length;\n\n\t\t/**\n\t\t * Increment counter.\n\t\t */\n\t\tconst incrementLoadingCounter = (): void => {\n\t\t\t// Increment\n\t\t\tcounter++;\n\n\t\t\t// Remove loading attribute once all images have loaded.\n\t\t\tif ( counter === totalImages ) {\n\t\t\t\tthis.removeAttribute( 'loading' );\n\t\t\t}\n\t\t};\n\n\t\t// Check if images have loaded, else add an event listener.\n\t\timages.forEach( ( image: HTMLImageElement ): void => {\n\t\t\t// Check if image has loaded.\n\t\t\tif ( image.complete ) {\n\t\t\t\tincrementLoadingCounter();\n\t\t\t} else {\n\t\t\t\timage.addEventListener( 'load', incrementLoadingCounter, { once: true } );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Handle when the dialog is clicked.\n\t *\n\t * @param {Event} e Click event.\n\t */\n\thandleDialogClick( e: MouseEvent ): void {\n\t\t// Close on overlay click.\n\t\tif (\n\t\t\t'yes' === this.getAttribute( 'close-on-overlay-click' ) &&\n\t\t\tthis.querySelector( 'dialog' ) === e.target\n\t\t) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/**\n\t * Handle when the dialog is closed (e.g., via Escape key).\n\t * Syncs lightbox state with native dialog close behavior.\n\t */\n\thandleDialogClose(): void {\n\t\t// Only sync if the lightbox thinks it's still open.\n\t\tif ( this.hasAttribute( 'open' ) ) {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/**\n\t * Handles the touch start event.\n\t *\n\t * @param { TouchEvent } evt The touch event.\n\t */\n\thandleTouchStart( evt: TouchEvent ): void {\n\t\t// Check if we should allow swiping?\n\t\tif ( 'yes' !== this.getAttribute( 'swipe' ) ) {\n\t\t\t// Nope.\n\t\t\treturn;\n\t\t}\n\n\t\t// Set the start points.\n\t\tthis.touchStartX = evt.touches[ 0 ].clientX;\n\t\tthis.touchStartY = evt.touches[ 0 ].clientY;\n\t}\n\n\t/**\n\t * Handles the touch end event.\n\t *\n\t * @param { TouchEvent } evt The touch event.\n\t */\n\thandleTouchEnd( evt: TouchEvent ): void {\n\t\t// Check if we should allow swiping?\n\t\tif ( 'yes' !== this.getAttribute( 'swipe' ) ) {\n\t\t\t// Nope.\n\t\t\treturn;\n\t\t}\n\n\t\t// Calculate the distances.\n\t\tconst touchEndX: number = evt.changedTouches[ 0 ].clientX;\n\t\tconst touchEndY: number = evt.changedTouches[ 0 ].clientY;\n\t\tconst swipeDistanceX: number = touchEndX - this.touchStartX;\n\t\tconst swipeDistanceY: number = touchEndY - this.touchStartY;\n\n\t\t// Is this horizontal swipe?\n\t\tconst isHorizontalSwipe = Math.abs( swipeDistanceX ) > Math.abs( swipeDistanceY );\n\n\t\t// Check if this was a horizontal swipe?\n\t\tif ( ! isHorizontalSwipe ) {\n\t\t\t// Bail.\n\t\t\treturn;\n\t\t}\n\n\t\t// Swipe settings\n\t\tthis.swipeThreshold = Number( this.getAttribute( 'swipe-threshold' ) ?? '200' );\n\n\t\t// Check if it's a right or left swipe.\n\t\tif ( swipeDistanceX > 0 ) {\n\t\t\t// Right-Swipe: Check if horizontal swipe distance is less than the threshold.\n\t\t\tif ( swipeDistanceX < this.swipeThreshold ) {\n\t\t\t\tthis.previous();\n\t\t\t}\n\t\t} else if ( swipeDistanceX < 0 ) {\n\t\t\t// Left-Swipe: Check if horizontal swipe distance is less than the threshold.\n\t\t\tif ( swipeDistanceX > -this.swipeThreshold ) {\n\t\t\t\tthis.next();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Update current item in navigation.\n\t */\n\tupdateNavCurrentItem(): void {\n\t\t// Bail if we don't have nav items.\n\t\tif ( ! this.lightboxNavItems ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if ARIA management is enabled.\n\t\tconst ariaEnabled = this.isAriaEnabled();\n\n\t\t// Update current item.\n\t\tthis.lightboxNavItems.forEach( ( navItem: TPLightboxNavItemElement, index: number ): void => {\n\t\t\t// Get the button inside the nav item.\n\t\t\tconst button: HTMLButtonElement | null = navItem.querySelector( 'button' );\n\n\t\t\t// Update current attribute.\n\t\t\tif ( this.currentIndex - 1 === index ) {\n\t\t\t\tnavItem.setAttribute( 'current', 'yes' );\n\n\t\t\t\t// Set aria-current on the button (if ARIA is enabled).\n\t\t\t\tif ( ariaEnabled && button ) {\n\t\t\t\t\tbutton.setAttribute( 'aria-current', 'true' );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnavItem.removeAttribute( 'current' );\n\n\t\t\t\t// Remove aria-current from the button (if ARIA is enabled).\n\t\t\t\tif ( ariaEnabled && button ) {\n\t\t\t\t\tbutton.removeAttribute( 'aria-current' );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Set initial focus when lightbox opens.\n\t * Looks for [autofocus] element, otherwise focuses the dialog.\n\t */\n\tprivate setInitialFocus(): void {\n\t\t// Look for an element with autofocus attribute.\n\t\tconst autofocusElement = this.querySelector<HTMLElement>( '[autofocus]' );\n\n\t\t// Do we have an autofocus element?\n\t\tif ( autofocusElement ) {\n\t\t\tautofocusElement.focus();\n\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Otherwise, focus the dialog itself.\n\t\tthis.dialogElement?.focus();\n\t}\n\n\t/**\n\t * Handle keydown events for arrow navigation.\n\t *\n\t * @param {KeyboardEvent} e Keyboard event.\n\t */\n\tprivate handleKeyDown( e: KeyboardEvent ): void {\n\t\t// Check if arrow navigation is enabled (disabled by default).\n\t\tif ( 'yes' !== this.getAttribute( 'arrow-navigation' ) ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Navigate on arrow keys.\n\t\tif ( 'ArrowLeft' === e.key ) {\n\t\t\te.preventDefault();\n\t\t\tthis.previous();\n\t\t} else if ( 'ArrowRight' === e.key ) {\n\t\t\te.preventDefault();\n\t\t\tthis.next();\n\t\t}\n\t}\n}\n","/**\n * TP Lightbox Content.\n */\nexport class TPLightboxContentElement extends HTMLElement {\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Close.\n */\nexport class TPLightboxCloseElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.close.bind( this ) );\n\t}\n\n\t/**\n\t * Close the lightbox.\n\t */\n\tclose(): void {\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( lightbox ) {\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// Close the lightbox.\n\t\t\t\tlightbox.close();\n\t\t\t}, 0 );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Close.\n */\nexport class TPLightboxPreviousElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.previous.bind( this ) );\n\t}\n\n\t/**\n\t * Navigate previous.\n\t */\n\tprevious(): void {\n\t\t// Check if we are disabled.\n\t\tif ( 'yes' === this.getAttribute( 'disabled' ) ) {\n\t\t\t// No we don't. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( lightbox ) {\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// Previous.\n\t\t\t\tlightbox.previous();\n\t\t\t}, 0 );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Close.\n */\nexport class TPLightboxNextElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.next.bind( this ) );\n\t}\n\n\t/**\n\t * Navigate next.\n\t */\n\tnext(): void {\n\t\t// Check if next is disabled.\n\t\tif ( 'yes' === this.getAttribute( 'disabled' ) ) {\n\t\t\t// Yes it is. Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( lightbox ) {\n\t\t\tsetTimeout( (): void => {\n\t\t\t\t// Initiate next.\n\t\t\t\tlightbox.next();\n\t\t\t}, 0 );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Slider Count.\n */\nexport class TPLightboxCountElement extends HTMLElement {\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} Observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Attributes to observe.\n\t\treturn [ 'format' ];\n\t}\n\n\t/**\n\t * Get format.\n\t *\n\t * @return {string} Format.\n\t */\n\tget format(): string {\n\t\t// Get format.\n\t\treturn this.getAttribute( 'format' ) ?? '$current / $total';\n\t}\n\n\t/**\n\t * Set format.\n\t *\n\t * @param {string} format Format.\n\t */\n\tset format( format: string ) {\n\t\t// Set the 'format' attribute value.\n\t\tthis.setAttribute( 'format', format );\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t */\n\tattributeChangedCallback(): void {\n\t\t// On change of format attribute, update the component.\n\t\tthis.update();\n\t}\n\n\t/**\n\t * Update component.\n\t */\n\tupdate(): void {\n\t\t// Get lightbox.\n\t\tconst lightbox: TPLightboxElement | null = this.closest( 'tp-lightbox' );\n\n\t\t// Check if we have a lightbox.\n\t\tif ( ! lightbox ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get current and total.\n\t\tconst current: string = lightbox.currentIndex.toString();\n\t\tconst total: string = lightbox.getAttribute( 'total' ) ?? '';\n\n\t\t// Update variables in format attribute (using textContent for XSS protection).\n\t\tthis.textContent =\n\t\t\tthis.format\n\t\t\t\t.replace( '$current', current )\n\t\t\t\t.replace( '$total', total );\n\n\t\t// Update current and total attributes.\n\t\tthis.setAttribute( 'current', current );\n\t\tthis.setAttribute( 'total', total );\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Trigger.\n */\nexport class TPLightboxTriggerElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Events.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.trigger.bind( this ) );\n\t}\n\n\t/**\n\t * Trigger the lightbox.\n\t */\n\ttrigger(): void {\n\t\t// Get lightbox ID and template.\n\t\tconst lightboxId: string | null = this.getAttribute( 'lightbox' );\n\t\tconst template: HTMLTemplateElement | null = this.querySelector( 'template' );\n\n\t\t// We can't proceed without them.\n\t\tif ( ! lightboxId || ! template ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the lightbox.\n\t\tconst lightbox: TPLightboxElement | null = document.querySelector( `#${ lightboxId.toString() }` );\n\n\t\t// Check to see if we have a lightbox.\n\t\tif ( ! lightbox ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Check to see if we have a group.\n\t\tconst group: string = this.getAttribute( 'group' ) ?? '';\n\n\t\t// Yield to main thread.\n\t\tsetTimeout( (): void => {\n\t\t\t// Prepare lightbox.\n\t\t\tlightbox.template = template;\n\t\t\tlightbox.group = group;\n\n\t\t\t// Set index and group if we have them.\n\t\t\tif ( '' !== group ) {\n\t\t\t\tconst allGroups: NodeListOf<TPLightboxTriggerElement> = document.querySelectorAll( `tp-lightbox-trigger[group=\"${ group }\"]` );\n\n\t\t\t\t// Update all groups.\n\t\t\t\tif ( allGroups.length ) {\n\t\t\t\t\t/**\n\t\t\t\t\t * We do this when we're opening a lightbox, or navigating.\n\t\t\t\t\t * This allows consumers to inject elements at any point.\n\t\t\t\t\t */\n\t\t\t\t\tlightbox.updateAllGroups( allGroups );\n\n\t\t\t\t\t// Get current trigger's index within the group.\n\t\t\t\t\tallGroups.forEach( ( triggerElement: TPLightboxTriggerElement, index: number ): void => {\n\t\t\t\t\t\t// Update current index.\n\t\t\t\t\t\tif ( this === triggerElement ) {\n\t\t\t\t\t\t\tlightbox.currentIndex = index + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// All done, lets open the lightbox.\n\t\t\tlightbox.open();\n\t\t}, 0 );\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\n\n/**\n * TP Lightbox Nav.\n */\nexport class TPLightboxNavElement extends HTMLElement {\n\t/**\n\t * Properties.\n\t */\n\tprotected template: HTMLTemplateElement | null = null;\n\tprotected lightbox : TPLightboxElement | null;\n\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Initialize properties.\n\t\tthis.template = this.querySelector( 'template' );\n\t\tthis.lightbox = this.closest( 'tp-lightbox' );\n\n\t\t// Add event listener.\n\t\tthis.lightbox?.addEventListener( 'template-set', this.setTemplate.bind( this ) );\n\t}\n\n\t/**\n\t * Set the template.\n\t */\n\tsetTemplate(): void {\n\t\t// Bail if no template.\n\t\tif ( ! this.template ) {\n\t\t\t// Exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Total slides.\n\t\tconst totalSlides = Number( this.lightbox?.getAttribute( 'total' ) ?? 0 );\n\n\t\t// Clear the navigation.\n\t\tthis.innerHTML = '';\n\n\t\t// Append the navigation items.\n\t\tfor ( let i = 0; i < totalSlides; i++ ) {\n\t\t\t// Clone the template.\n\t\t\tconst navItem = this.template.content.cloneNode( true );\n\n\t\t\t// Append the clone.\n\t\t\tthis.appendChild( navItem );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPLightboxElement } from './tp-lightbox';\nimport { TPLightboxNavElement } from './tp-lightbox-nav';\n\n/**\n * TP Lightbox Nav Item.\n */\nexport class TPLightboxNavItemElement extends HTMLElement {\n\t/**\n\t * Properties.\n\t */\n\tprotected lightbox : TPLightboxElement | null;\n\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\t\tthis.lightbox = this.closest( 'tp-lightbox' );\n\n\t\t// Get the nav-item button.\n\t\tthis.querySelector( 'button' )?.addEventListener( 'click', this.handleClick.bind( this ) );\n\t}\n\n\t/**\n\t * Handle when the button is clicked.\n\t */\n\thandleClick(): void {\n\t\t// Check if lightbox exists.\n\t\tif ( ! this.lightbox ) {\n\t\t\t// No its not! Terminate.\n\t\t\treturn;\n\t\t}\n\n\t\t// Set current slide.\n\t\tthis.lightbox.currentIndex = Number( this.getIndex() ) ?? 1;\n\n\t\t// Update navigation current item.\n\t\tthis.lightbox.updateNavCurrentItem();\n\t}\n\n\t/**\n\t * Get index of this item inside the navigation.\n\t *\n\t * @return {number} Index.\n\t */\n\tgetIndex(): number {\n\t\t// Bail if no lightbox.\n\t\tif ( ! this.lightbox ) {\n\t\t\t// Exit.\n\t\t\treturn 0;\n\t\t}\n\n\t\t// No, find it in the navigation.\n\t\tconst lightboxNav: TPLightboxNavElement | null = this.closest( 'tp-lightbox-nav' );\n\n\t\t// Return index of this element considering the step value.\n\t\treturn ( Array.from( lightboxNav?.children ?? [] ).indexOf( this ) ) + 1;\n\t}\n}\n","/**\n * Styles.\n */\nimport './style.scss';\n\n/**\n * Components.\n */\nimport { TPLightboxElement } from './tp-lightbox';\nimport { TPLightboxContentElement } from './tp-lightbox-content';\nimport { TPLightboxCloseElement } from './tp-lightbox-close';\nimport { TPLightboxPreviousElement } from './tp-lightbox-previous';\nimport { TPLightboxNextElement } from './tp-lightbox-next';\nimport { TPLightboxCountElement } from './tp-lightbox-count';\nimport { TPLightboxTriggerElement } from './tp-lightbox-trigger';\nimport { TPLightboxNavElement } from './tp-lightbox-nav';\nimport { TPLightboxNavItemElement } from './tp-lightbox-nav-item';\n\n/**\n * Register Components.\n */\ncustomElements.define( 'tp-lightbox', TPLightboxElement );\ncustomElements.define( 'tp-lightbox-content', TPLightboxContentElement );\ncustomElements.define( 'tp-lightbox-close', TPLightboxCloseElement );\ncustomElements.define( 'tp-lightbox-previous', TPLightboxPreviousElement );\ncustomElements.define( 'tp-lightbox-next', TPLightboxNextElement );\ncustomElements.define( 'tp-lightbox-count', TPLightboxCountElement );\ncustomElements.define( 'tp-lightbox-trigger', TPLightboxTriggerElement );\ncustomElements.define( 'tp-lightbox-nav', TPLightboxNavElement );\ncustomElements.define( 'tp-lightbox-nav-item', TPLightboxNavItemElement );\n"],"names":["TPLightboxElement","HTMLElement","constructor","super","currentTemplate","currentGroup","allGroups","touchStartX","touchStartY","swipeThreshold","previouslyFocusedElement","this","boundHandleKeyDown","handleKeyDown","bind","dialogElement","querySelector","lightboxNavItems","querySelectorAll","addEventListener","handleDialogClick","handleTouchStart","handleTouchEnd","handleDialogClose","observedAttributes","attributeChangedCallback","name","oldValue","newValue","dispatchEvent","CustomEvent","triggerCurrentIndexTarget","updateNavCurrentItem","isAriaEnabled","getAttribute","template","content","templateContent","cloneNode","replaceChildren","setTimeout","prepareImageLoading","prepareNavigation","innerHTML","group","currentIndex","parseInt","index","setAttribute","toString","detail","slideIndex","getAllGroups","trigger","open","dialog","ownerDocument","activeElement","updateAllGroups","showModal","document","setInitialFocus","close","removeEventListener","removeAttribute","focus","previous","next","length","count","update","previousButton","nextButton","ariaEnabled","images","counter","totalImages","incrementLoadingCounter","forEach","image","complete","once","e","target","hasAttribute","evt","touches","clientX","clientY","touchEndX","changedTouches","touchEndY","swipeDistanceX","swipeDistanceY","Math","abs","Number","navItem","button","autofocusElement","key","preventDefault","TPLightboxContentElement","TPLightboxCloseElement","lightbox","closest","TPLightboxPreviousElement","TPLightboxNextElement","TPLightboxCountElement","format","current","total","textContent","replace","TPLightboxTriggerElement","lightboxId","triggerElement","TPLightboxNavElement","setTemplate","totalSlides","i","appendChild","TPLightboxNavItemElement","handleClick","getIndex","lightboxNav","Array","from","children","indexOf","customElements","define"],"sourceRoot":""}
|
package/dist/tabs/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(()=>{"use strict";class t extends HTMLElement{constructor(){super();const t=this.getTrigger();null==t||t.addEventListener("click",this.handleTriggerClick.bind(this)),this.setupAriaAttributes()}getTrigger(){return this.querySelector("button")||this.querySelector("a")}static get observedAttributes(){return["active"]}attributeChangedCallback(t,e,r){e!==r&&"active"===t&&this.updateAriaState("yes"===r)}isAriaEnabled(){var t;const e=this.closest("tp-tabs");return null===(t=null==e?void 0:e.isAriaEnabled())||void 0===t||t}setupAriaAttributes(){if(!this.isAriaEnabled())return;const t=this.getTrigger();if(!t)return;t.id||(t.id=`tp-tab-${Math.random().toString(36).substring(2,9)}`);const e=this.getPanelId();e&&!t.hasAttribute("aria-controls")&&t.setAttribute("aria-controls",e);const r="yes"===this.getAttribute("active");this.updateAriaState(r)}getPanelId(){var t,e;const r=this.getTrigger();return r?r instanceof HTMLAnchorElement?null!==(e=null===(t=r.getAttribute("href"))||void 0===t?void 0:t.replace("#",""))&&void 0!==e?e:"":r.getAttribute("aria-controls")||r.getAttribute("data-controls")||"":""}updateAriaState(t){if(!this.isAriaEnabled())return;const e=this.getTrigger();e&&(e.setAttribute("aria-selected",t?"true":"false"),e.setAttribute("tabindex",t?"0":"-1"))}handleTriggerClick(t){const e=this.closest("tp-tabs"),r=this.getTrigger(),i=this.getPanelId();e
|
|
1
|
+
(()=>{"use strict";class t extends HTMLElement{constructor(){super();const t=this.getTrigger();null==t||t.addEventListener("click",this.handleTriggerClick.bind(this)),this.setupAriaAttributes()}getTrigger(){return this.querySelector("button")||this.querySelector("a")}static get observedAttributes(){return["active"]}attributeChangedCallback(t,e,r){e!==r&&"active"===t&&this.updateAriaState("yes"===r)}isAriaEnabled(){var t;const e=this.closest("tp-tabs");return null===(t=null==e?void 0:e.isAriaEnabled())||void 0===t||t}setupAriaAttributes(){if(!this.isAriaEnabled())return;const t=this.getTrigger();if(!t)return;t.id||(t.id=`tp-tab-${Math.random().toString(36).substring(2,9)}`);const e=this.getPanelId();e&&!t.hasAttribute("aria-controls")&&t.setAttribute("aria-controls",e);const r="yes"===this.getAttribute("active");this.updateAriaState(r)}getPanelId(){var t,e;const r=this.getTrigger();return r?r instanceof HTMLAnchorElement?null!==(e=null===(t=r.getAttribute("href"))||void 0===t?void 0:t.replace("#",""))&&void 0!==e?e:"":r.getAttribute("aria-controls")||r.getAttribute("data-controls")||"":""}updateAriaState(t){if(!this.isAriaEnabled())return;const e=this.getTrigger();e&&(e.setAttribute("aria-selected",t?"true":"false"),e.setAttribute("tabindex",t?"0":"-1"))}handleTriggerClick(t){const e=this.closest("tp-tabs"),r=this.getTrigger(),i=this.getPanelId();if(!e||!r||""===i)return;r instanceof HTMLAnchorElement&&"yes"!==e.getAttribute("update-url")&&t.preventDefault();const s=document.getElementById(i);if(s){const t=s.closest("tp-tabs");if(t&&t!==e){t.setAttribute("current-tab",i);const r=t.closest("tp-tabs-tab");return void(r&&r.id&&(e.getAttribute("current-tab")===r.id?e.update():e.setAttribute("current-tab",r.id)))}}e.setAttribute("current-tab",i)}isCurrentTab(t=""){return t===this.getPanelId()}}class e extends HTMLElement{constructor(){super(),this.addEventListener("keydown",this.handleKeyDown.bind(this))}isAriaEnabled(){var t;const e=this.closest("tp-tabs");return null===(t=null==e?void 0:e.isAriaEnabled())||void 0===t||t}getTabTriggers(){const t=this.querySelectorAll("tp-tabs-nav-item"),e=[];return t.forEach((t=>{const r=t.querySelector("button")||t.querySelector("a");r&&e.push(r)})),e}handleKeyDown(t){if(!this.isAriaEnabled())return;const e=this.getTabTriggers();if(0===e.length)return;const r=e.findIndex((t=>t===this.ownerDocument.activeElement));if(-1===r)return;let i=r;switch(t.key){case"ArrowLeft":i=0===r?e.length-1:r-1;break;case"ArrowRight":i=r===e.length-1?0:r+1;break;case"Home":i=0;break;case"End":i=e.length-1;break;default:return}t.preventDefault();const s=e[i];s.click(),s.focus()}}class r extends HTMLElement{constructor(){super(),this.setupAriaAttributes()}static get observedAttributes(){return["open"]}attributeChangedCallback(t,e,r){e!==r&&"open"===t&&this.updateAriaState("yes"===r)}isAriaEnabled(){var t;const e=this.closest("tp-tabs");return null===(t=null==e?void 0:e.isAriaEnabled())||void 0===t||t}setupAriaAttributes(){if(!this.isAriaEnabled())return;const t=this.getAttribute("id");if(t){const e=this.closest("tp-tabs"),r=null==e?void 0:e.querySelector(`a[href="#${t}"]`);(null==r?void 0:r.id)&&!this.hasAttribute("aria-labelledby")&&this.setAttribute("aria-labelledby",r.id)}const e="yes"===this.getAttribute("open");this.updateAriaState(e)}updateAriaState(t){this.isAriaEnabled()&&(t?(this.removeAttribute("aria-hidden"),this.removeAttribute("inert"),this.setAttribute("tabindex","0")):(this.setAttribute("aria-hidden","true"),this.setAttribute("inert",""),this.removeAttribute("tabindex")))}}class i extends HTMLElement{constructor(){super(),this.updateTabFromUrlHash(),window.addEventListener("hashchange",this.updateTabFromUrlHash.bind(this))}static get observedAttributes(){return["current-tab","update-url","overflow","aria"]}isAriaEnabled(){return"no"!==this.getAttribute("aria")}attributeChangedCallback(t="",e="",r=""){e!==r&&(this.update(),"current-tab"===t&&this.dispatchEvent(new CustomEvent("change",{bubbles:!0})))}update(){setTimeout((()=>{var t;const e=null!==(t=this.getAttribute("current-tab"))&&void 0!==t?t:"";if(!this.querySelector(`tp-tabs-tab[id="${e}"]`))return;const r=this.getCurrentNestedTab(e),i=this.querySelectorAll("tp-tabs-nav-item");i&&i.forEach((t=>{t.isCurrentTab(e)||r&&t.isCurrentTab(r)?t.setAttribute("active","yes"):t.removeAttribute("active")}));const s=this.querySelectorAll("tp-tabs-tab");s&&s.forEach((t=>{e===t.getAttribute("id")||r&&r===t.getAttribute("id")?t.setAttribute("open","yes"):t.removeAttribute("open")}))}),0)}updateTabFromUrlHash(){"yes"===this.getAttribute("update-url")&&this.setCurrentTab()}setCurrentTab(t=""){""!==t&&this.setAttribute("current-tab",t);const e=window.location.hash;if(""!==e){const t=this.querySelector(`a[href="${e}"]`),r=null==t?void 0:t.closest("tp-tabs");null==r||r.setAttribute("current-tab",e.replace("#",""))}}getCurrentNestedTab(t=""){if(""===t)return"";const e=this.querySelector(`tp-tabs-tab[id="${t}"]`),r=null==e?void 0:e.querySelector("tp-tabs"),i=null==r?void 0:r.getAttribute("current-tab");return null!=i?i:""}}customElements.define("tp-tabs",i),customElements.define("tp-tabs-nav",e),customElements.define("tp-tabs-nav-item",t),customElements.define("tp-tabs-tab",r)})();
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/tabs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dist/tabs/index.js","mappings":"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","sources":["webpack://@travelopia/web-components/./src/tabs/tp-tabs-nav-item.ts","webpack://@travelopia/web-components/./src/tabs/tp-tabs-nav.ts","webpack://@travelopia/web-components/./src/tabs/tp-tabs-tab.ts","webpack://@travelopia/web-components/./src/tabs/tp-tabs.ts","webpack://@travelopia/web-components/./src/tabs/index.ts"],"sourcesContent":["/**\n * Internal dependencies.\n */\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * TP Tabs Nav Item Element.\n */\nexport class TPTabsNavItemElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Constructor function.\n\t\tsuper();\n\n\t\t// Get the trigger element (button or anchor).\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Add click event listener to the trigger.\n\t\ttrigger?.addEventListener( 'click', this.handleTriggerClick.bind( this ) );\n\n\t\t// Set up ARIA attributes.\n\t\tthis.setupAriaAttributes();\n\t}\n\n\t/**\n\t * Get the trigger element (button or anchor).\n\t *\n\t * @return {HTMLButtonElement | HTMLAnchorElement | null} The trigger element.\n\t */\n\tgetTrigger(): HTMLButtonElement | HTMLAnchorElement | null {\n\t\t// Look for button first, then anchor.\n\t\treturn this.querySelector( 'button' ) || this.querySelector( 'a' );\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Observe the active attribute to update ARIA state.\n\t\treturn [ 'active' ];\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string, oldValue: string, newValue: string ): void {\n\t\t// Early return if no change.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// No change.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update ARIA state when active attribute changes.\n\t\tif ( 'active' === name ) {\n\t\t\tthis.updateAriaState( 'yes' === newValue );\n\t\t}\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tprivate isAriaEnabled(): boolean {\n\t\t// Get parent tabs component.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\n\t\t// Return whether aria management is enabled.\n\t\treturn tabs?.isAriaEnabled() ?? true;\n\t}\n\n\t/**\n\t * Set up ARIA attributes on the trigger element.\n\t */\n\tprivate setupAriaAttributes(): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the trigger element.\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Bail if no trigger.\n\t\tif ( ! trigger ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Generate ID for the trigger if not present.\n\t\tif ( ! trigger.id ) {\n\t\t\ttrigger.id = `tp-tab-${ Math.random().toString( 36 ).substring( 2, 9 ) }`;\n\t\t}\n\n\t\t// Get the panel ID from href (anchor) or aria-controls (button).\n\t\tconst panelId = this.getPanelId();\n\n\t\t// Set aria-controls if we have a panel ID and it's not already set.\n\t\tif ( panelId && ! trigger.hasAttribute( 'aria-controls' ) ) {\n\t\t\ttrigger.setAttribute( 'aria-controls', panelId );\n\t\t}\n\n\t\t// Set initial ARIA state.\n\t\tconst isActive = 'yes' === this.getAttribute( 'active' );\n\t\tthis.updateAriaState( isActive );\n\t}\n\n\t/**\n\t * Get the panel ID that this nav item controls.\n\t *\n\t * @return {string} The panel ID.\n\t */\n\tgetPanelId(): string {\n\t\t// Get the trigger.\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Bail if no trigger.\n\t\tif ( ! trigger ) {\n\t\t\t// Bail.\n\t\t\treturn '';\n\t\t}\n\n\t\t// Check if trigger is a link.\n\t\tif ( trigger instanceof HTMLAnchorElement ) {\n\t\t\t// For anchors, get from href. For buttons, get from aria-controls or data-controls.\n\t\t\treturn trigger.getAttribute( 'href' )?.replace( '#', '' ) ?? '';\n\t\t}\n\n\t\t// For buttons, check aria-controls or data-controls.\n\t\treturn trigger.getAttribute( 'aria-controls' ) || trigger.getAttribute( 'data-controls' ) || '';\n\t}\n\n\t/**\n\t * Update ARIA state on the trigger element.\n\t *\n\t * @param {boolean} isActive Whether this tab is active.\n\t */\n\tprivate updateAriaState( isActive: boolean ): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the trigger element.\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Bail if no trigger.\n\t\tif ( ! trigger ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update aria-selected.\n\t\ttrigger.setAttribute( 'aria-selected', isActive ? 'true' : 'false' );\n\n\t\t// Update tabindex for roving tabindex pattern.\n\t\ttrigger.setAttribute( 'tabindex', isActive ? '0' : '-1' );\n\t}\n\n\t/**\n\t * Handle trigger click.\n\t *\n\t * @param {Event} e Click event.\n\t *\n\t * @protected\n\t */\n\tprotected handleTriggerClick( e: Event ): void {\n\t\t// Find the closest tp-tabs element.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\t\tconst trigger = this.getTrigger();\n\t\tconst panelId = this.getPanelId();\n\n\t\t// If the tabs component, trigger, or panel ID is missing, do nothing.\n\t\tif ( ! tabs || ! trigger || '' === panelId ) {\n\t\t\t// Exit if required elements are not found.\n\t\t\treturn;\n\t\t}\n\n\t\t// For anchors, prevent default if update-url is not enabled.\n\t\tif ( trigger instanceof HTMLAnchorElement && 'yes' !== tabs.getAttribute( 'update-url' ) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\t// Update the 'current-tab' attribute on the tabs component.\n\t\ttabs.setAttribute( 'current-tab', panelId );\n\t}\n\n\t/**\n\t * Check if this component contains the trigger for the current tab.\n\t *\n\t * @param {string} currentTab Current tab ID.\n\t *\n\t * @return {boolean} Whether it is the current tab or not.\n\t */\n\tisCurrentTab( currentTab: string = '' ): boolean {\n\t\t// Return true if this nav item's panel ID matches the current tab.\n\t\treturn currentTab === this.getPanelId();\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * TP Tabs Nav Element.\n */\nexport class TPTabsNavElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Add keyboard event listener for arrow key navigation.\n\t\tthis.addEventListener( 'keydown', this.handleKeyDown.bind( this ) );\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tprivate isAriaEnabled(): boolean {\n\t\t// Get parent tabs component.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\n\t\t// Return whether aria management is enabled.\n\t\treturn tabs?.isAriaEnabled() ?? true;\n\t}\n\n\t/**\n\t * Get all tab trigger elements (buttons or anchors).\n\t *\n\t * @return {Array<HTMLButtonElement | HTMLAnchorElement>} Array of trigger elements.\n\t */\n\tprivate getTabTriggers(): Array<HTMLButtonElement | HTMLAnchorElement> {\n\t\t// Get all nav items and collect their triggers.\n\t\tconst navItems = this.querySelectorAll( 'tp-tabs-nav-item' );\n\t\tconst triggers: Array<HTMLButtonElement | HTMLAnchorElement> = [];\n\n\t\t// Iterate over nav items to find triggers.\n\t\tnavItems.forEach( ( navItem ) => {\n\t\t\t// Look for button first, then anchor.\n\t\t\tconst trigger = navItem.querySelector( 'button' ) || navItem.querySelector( 'a' );\n\n\t\t\t// Add trigger to array if found.\n\t\t\tif ( trigger ) {\n\t\t\t\ttriggers.push( trigger );\n\t\t\t}\n\t\t} );\n\n\t\t// Return all triggers.\n\t\treturn triggers;\n\t}\n\n\t/**\n\t * Handle keydown events for keyboard navigation.\n\t *\n\t * @param {KeyboardEvent} e Keyboard event.\n\t */\n\tprivate handleKeyDown( e: KeyboardEvent ): void {\n\t\t// Only handle if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Bail early.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get all tab triggers.\n\t\tconst triggers = this.getTabTriggers();\n\n\t\t// Bail if no triggers.\n\t\tif ( triggers.length === 0 ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Find current focused trigger index using ownerDocument.\n\t\tconst currentIndex = triggers.findIndex( ( trigger ) => trigger === this.ownerDocument.activeElement );\n\n\t\t// Only handle if focus is on a trigger.\n\t\tif ( currentIndex === -1 ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get new index.\n\t\tlet newIndex = currentIndex;\n\n\t\t// Handle arrow keys, Home, and End.\n\t\tswitch ( e.key ) {\n\t\t\t// Move to previous tab, wrap to end if at start.\n\t\t\tcase 'ArrowLeft':\n\t\t\t\tnewIndex = currentIndex === 0 ? triggers.length - 1 : currentIndex - 1;\n\t\t\t\tbreak;\n\n\t\t\t// Move to next tab, wrap to start if at end.\n\t\t\tcase 'ArrowRight':\n\t\t\t\tnewIndex = currentIndex === triggers.length - 1 ? 0 : currentIndex + 1;\n\t\t\t\tbreak;\n\n\t\t\t// Move to first tab.\n\t\t\tcase 'Home':\n\t\t\t\tnewIndex = 0;\n\t\t\t\tbreak;\n\n\t\t\t// Move to last tab.\n\t\t\tcase 'End':\n\t\t\t\tnewIndex = triggers.length - 1;\n\t\t\t\tbreak;\n\n\t\t\t// Not a navigation key, bail.\n\t\t\tdefault:\n\n\t\t\t\t// Not a navigation key, bail.\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Prevent default browser behavior.\n\t\te.preventDefault();\n\n\t\t// Activate the new tab first (updates tabindex), then focus.\n\t\tconst newTrigger = triggers[ newIndex ];\n\t\tnewTrigger.click();\n\t\tnewTrigger.focus();\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * TP Tabs Tab Element.\n */\nexport class TPTabsTabElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Set up ARIA attributes.\n\t\tthis.setupAriaAttributes();\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Observe the open attribute to update ARIA state.\n\t\treturn [ 'open' ];\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string, oldValue: string, newValue: string ): void {\n\t\t// Early return if no change.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// No change.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update ARIA state when open attribute changes.\n\t\tif ( 'open' === name ) {\n\t\t\tthis.updateAriaState( 'yes' === newValue );\n\t\t}\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tprivate isAriaEnabled(): boolean {\n\t\t// Get parent tabs component.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\n\t\t// Return whether aria management is enabled.\n\t\treturn tabs?.isAriaEnabled() ?? true;\n\t}\n\n\t/**\n\t * Set up ARIA attributes on this tab panel.\n\t */\n\tprivate setupAriaAttributes(): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the panel ID.\n\t\tconst panelId = this.getAttribute( 'id' );\n\n\t\t// Find the corresponding tab trigger by matching href.\n\t\tif ( panelId ) {\n\t\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\t\t\tconst trigger = tabs?.querySelector( `a[href=\"#${ panelId }\"]` );\n\n\t\t\t// Set aria-labelledby if trigger has an ID.\n\t\t\tif ( trigger?.id && ! this.hasAttribute( 'aria-labelledby' ) ) {\n\t\t\t\tthis.setAttribute( 'aria-labelledby', trigger.id );\n\t\t\t}\n\t\t}\n\n\t\t// Set initial ARIA state.\n\t\tconst isOpen = 'yes' === this.getAttribute( 'open' );\n\t\tthis.updateAriaState( isOpen );\n\t}\n\n\t/**\n\t * Update ARIA state on this tab panel.\n\t *\n\t * @param {boolean} isOpen Whether this panel is open.\n\t */\n\tprivate updateAriaState( isOpen: boolean ): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update aria-hidden, inert, and tabindex based on open state.\n\t\tif ( isOpen ) {\n\t\t\tthis.removeAttribute( 'aria-hidden' );\n\t\t\tthis.removeAttribute( 'inert' );\n\t\t\tthis.setAttribute( 'tabindex', '0' );\n\t\t} else {\n\t\t\tthis.setAttribute( 'aria-hidden', 'true' );\n\t\t\tthis.setAttribute( 'inert', '' );\n\t\t\tthis.removeAttribute( 'tabindex' );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPTabsNavItemElement } from './tp-tabs-nav-item';\nimport { TPTabsTabElement } from './tp-tabs-tab';\n\n/**\n * TP Tabs.\n */\nexport class TPTabsElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Update the current tab based on the URL hash.\n\t\tthis.updateTabFromUrlHash();\n\n\t\t// Listen for hash changes in the URL and update the tab accordingly.\n\t\twindow.addEventListener( 'hashchange', this.updateTabFromUrlHash.bind( this ) );\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Attributes observed in the TPTabsElement web-component.\n\t\treturn [ 'current-tab', 'update-url', 'overflow', 'aria' ];\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tisAriaEnabled(): boolean {\n\t\t// Return whether aria management is enabled (default: yes).\n\t\treturn 'no' !== this.getAttribute( 'aria' );\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string = '', oldValue: string = '', newValue: string = '' ): void {\n\t\t// If the attribute value hasn't changed, do nothing.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update the component whenever an observed attribute changes.\n\t\tthis.update();\n\n\t\t// If the 'current-tab' attribute has changed, dispatch a 'change' event.\n\t\tif ( 'current-tab' === name ) {\n\t\t\tthis.dispatchEvent( new CustomEvent( 'change', { bubbles: true } ) );\n\t\t}\n\t}\n\n\t/**\n\t * Update this component.\n\t */\n\tupdate(): void {\n\t\t// Get current tab.\n\t\tconst currentTab: string = this.getAttribute( 'current-tab' ) ?? '';\n\n\t\t// Check if current tab exists.\n\t\tif ( ! this.querySelector( `tp-tabs-tab[id=\"${ currentTab }\"]` ) ) {\n\t\t\t// Exit if no matching tab is found.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get current nested tab if has.\n\t\tconst currentNestedTab = this.getCurrentNestedTab( currentTab );\n\n\t\t// Update nav items.\n\t\tconst navItems: NodeListOf<TPTabsNavItemElement> = this.querySelectorAll( 'tp-tabs-nav-item' );\n\n\t\t// Update the navigation items based on the current tab.\n\t\tif ( navItems ) {\n\t\t\tnavItems.forEach( ( navItem: TPTabsNavItemElement ): void => {\n\t\t\t\t// If the nav item corresponds to the current tab or nested tab, set it as active.\n\t\t\t\tif ( navItem.isCurrentTab( currentTab ) || ( currentNestedTab && navItem.isCurrentTab( currentNestedTab ) ) ) {\n\t\t\t\t\tnavItem.setAttribute( 'active', 'yes' );\n\t\t\t\t} else {\n\t\t\t\t\tnavItem.removeAttribute( 'active' );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t// Update tabs.\n\t\tconst tabs: NodeListOf<TPTabsTabElement> = this.querySelectorAll( 'tp-tabs-tab' );\n\n\t\t// Update the tab panels based on the current tab.\n\t\tif ( tabs ) {\n\t\t\ttabs.forEach( ( tab: TPTabsTabElement ): void => {\n\t\t\t\t// If the tab corresponds to the current tab or nested tab, open it.\n\t\t\t\tif ( currentTab === tab.getAttribute( 'id' ) || ( currentNestedTab && currentNestedTab === tab.getAttribute( 'id' ) ) ) {\n\t\t\t\t\ttab.setAttribute( 'open', 'yes' );\n\t\t\t\t} else {\n\t\t\t\t\ttab.removeAttribute( 'open' );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Update tab from URL hash.\n\t */\n\tupdateTabFromUrlHash(): void {\n\t\t// If 'update-url' attribute is not set to 'yes', do nothing.\n\t\tif ( 'yes' !== this.getAttribute( 'update-url' ) ) {\n\t\t\t// Exit if the 'update-url' attribute is not enabled.\n\t\t\treturn;\n\t\t}\n\n\t\t// Set current associated tab.\n\t\tthis.setCurrentTab();\n\t}\n\n\t/**\n\t * Set current tab.\n\t *\n\t * @param {string} tabId Tab ID.\n\t */\n\tsetCurrentTab( tabId: string = '' ): void {\n\t\t// If a tab ID is provided, set it as the current tab.\n\t\tif ( '' !== tabId ) {\n\t\t\tthis.setAttribute( 'current-tab', tabId );\n\t\t}\n\n\t\t// Set current tab based on current url hash.\n\t\tconst urlHash: string = window.location.hash;\n\n\t\t// Find the link that matches the URL hash.\n\t\tif ( '' !== urlHash ) {\n\t\t\tconst currentLink: HTMLAnchorElement | null = this.querySelector( `a[href=\"${ urlHash }\"]` );\n\t\t\tconst currentTab = currentLink?.closest( 'tp-tabs' );\n\t\t\tcurrentTab?.setAttribute( 'current-tab', urlHash.replace( '#', '' ) );\n\t\t}\n\t}\n\n\t/**\n\t * Get current nested tab.\n\t *\n\t * @param {string} currentTab Tab ID.\n\t *\n\t * @return {string} If has Nested current tab or empty.\n\t */\n\tgetCurrentNestedTab( currentTab: string = '' ): string {\n\t\t// If no current tab is provided, return an empty string.\n\t\tif ( '' === currentTab ) {\n\t\t\t// Exit if no current tab is provided.\n\t\t\treturn '';\n\t\t}\n\n\t\t// Find the element corresponding to the current tab ID.\n\t\tconst currentTabElement = this.querySelector( `tp-tabs-tab[id=\"${ currentTab }\"]` );\n\n\t\t// Find the nested tp-tabs element within the current tab.\n\t\tconst currentNestedTabElement = currentTabElement?.querySelector( 'tp-tabs' );\n\n\t\t// Get the ID of the current nested tab, if any.\n\t\tconst currentNestedTab = currentNestedTabElement?.getAttribute( 'current-tab' );\n\n\t\t// Return the nested tab ID, or an empty string if none exists.\n\t\treturn currentNestedTab ?? '';\n\t}\n}\n","/**\n * Styles.\n */\nimport './style.scss';\n\n/**\n * Components.\n */\nimport { TPTabsNavItemElement } from './tp-tabs-nav-item';\nimport { TPTabsNavElement } from './tp-tabs-nav';\nimport { TPTabsTabElement } from './tp-tabs-tab';\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * Register Components.\n */\n\n// Register parent first so children can find it during their constructor.\ncustomElements.define( 'tp-tabs', TPTabsElement );\ncustomElements.define( 'tp-tabs-nav', TPTabsNavElement );\ncustomElements.define( 'tp-tabs-nav-item', TPTabsNavItemElement );\ncustomElements.define( 'tp-tabs-tab', TPTabsTabElement );\n"],"names":["TPTabsNavItemElement","HTMLElement","constructor","super","trigger","this","getTrigger","addEventListener","handleTriggerClick","bind","setupAriaAttributes","querySelector","observedAttributes","attributeChangedCallback","name","oldValue","newValue","updateAriaState","isAriaEnabled","tabs","closest","id","Math","random","toString","substring","panelId","getPanelId","hasAttribute","setAttribute","isActive","getAttribute","HTMLAnchorElement","replace","e","preventDefault","isCurrentTab","currentTab","TPTabsNavElement","handleKeyDown","getTabTriggers","navItems","querySelectorAll","triggers","forEach","navItem","push","length","currentIndex","findIndex","ownerDocument","activeElement","newIndex","key","newTrigger","click","focus","TPTabsTabElement","isOpen","removeAttribute","TPTabsElement","updateTabFromUrlHash","window","update","dispatchEvent","CustomEvent","bubbles","currentNestedTab","getCurrentNestedTab","tab","setCurrentTab","tabId","urlHash","location","hash","currentLink","currentTabElement","currentNestedTabElement","customElements","define"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"dist/tabs/index.js","mappings":"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","sources":["webpack://@travelopia/web-components/./src/tabs/tp-tabs-nav-item.ts","webpack://@travelopia/web-components/./src/tabs/tp-tabs-nav.ts","webpack://@travelopia/web-components/./src/tabs/tp-tabs-tab.ts","webpack://@travelopia/web-components/./src/tabs/tp-tabs.ts","webpack://@travelopia/web-components/./src/tabs/index.ts"],"sourcesContent":["/**\n * Internal dependencies.\n */\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * TP Tabs Nav Item Element.\n */\nexport class TPTabsNavItemElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Constructor function.\n\t\tsuper();\n\n\t\t// Get the trigger element (button or anchor).\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Add click event listener to the trigger.\n\t\ttrigger?.addEventListener( 'click', this.handleTriggerClick.bind( this ) );\n\n\t\t// Set up ARIA attributes.\n\t\tthis.setupAriaAttributes();\n\t}\n\n\t/**\n\t * Get the trigger element (button or anchor).\n\t *\n\t * @return {HTMLButtonElement | HTMLAnchorElement | null} The trigger element.\n\t */\n\tgetTrigger(): HTMLButtonElement | HTMLAnchorElement | null {\n\t\t// Look for button first, then anchor.\n\t\treturn this.querySelector( 'button' ) || this.querySelector( 'a' );\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Observe the active attribute to update ARIA state.\n\t\treturn [ 'active' ];\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string, oldValue: string, newValue: string ): void {\n\t\t// Early return if no change.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// No change.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update ARIA state when active attribute changes.\n\t\tif ( 'active' === name ) {\n\t\t\tthis.updateAriaState( 'yes' === newValue );\n\t\t}\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tprivate isAriaEnabled(): boolean {\n\t\t// Get parent tabs component.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\n\t\t// Return whether aria management is enabled.\n\t\treturn tabs?.isAriaEnabled() ?? true;\n\t}\n\n\t/**\n\t * Set up ARIA attributes on the trigger element.\n\t */\n\tprivate setupAriaAttributes(): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the trigger element.\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Bail if no trigger.\n\t\tif ( ! trigger ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Generate ID for the trigger if not present.\n\t\tif ( ! trigger.id ) {\n\t\t\ttrigger.id = `tp-tab-${ Math.random().toString( 36 ).substring( 2, 9 ) }`;\n\t\t}\n\n\t\t// Get the panel ID from href (anchor) or aria-controls (button).\n\t\tconst panelId = this.getPanelId();\n\n\t\t// Set aria-controls if we have a panel ID and it's not already set.\n\t\tif ( panelId && ! trigger.hasAttribute( 'aria-controls' ) ) {\n\t\t\ttrigger.setAttribute( 'aria-controls', panelId );\n\t\t}\n\n\t\t// Set initial ARIA state.\n\t\tconst isActive = 'yes' === this.getAttribute( 'active' );\n\t\tthis.updateAriaState( isActive );\n\t}\n\n\t/**\n\t * Get the panel ID that this nav item controls.\n\t *\n\t * @return {string} The panel ID.\n\t */\n\tgetPanelId(): string {\n\t\t// Get the trigger.\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Bail if no trigger.\n\t\tif ( ! trigger ) {\n\t\t\t// Bail.\n\t\t\treturn '';\n\t\t}\n\n\t\t// Check if trigger is a link.\n\t\tif ( trigger instanceof HTMLAnchorElement ) {\n\t\t\t// For anchors, get from href. For buttons, get from aria-controls or data-controls.\n\t\t\treturn trigger.getAttribute( 'href' )?.replace( '#', '' ) ?? '';\n\t\t}\n\n\t\t// For buttons, check aria-controls or data-controls.\n\t\treturn trigger.getAttribute( 'aria-controls' ) || trigger.getAttribute( 'data-controls' ) || '';\n\t}\n\n\t/**\n\t * Update ARIA state on the trigger element.\n\t *\n\t * @param {boolean} isActive Whether this tab is active.\n\t */\n\tprivate updateAriaState( isActive: boolean ): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the trigger element.\n\t\tconst trigger = this.getTrigger();\n\n\t\t// Bail if no trigger.\n\t\tif ( ! trigger ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update aria-selected.\n\t\ttrigger.setAttribute( 'aria-selected', isActive ? 'true' : 'false' );\n\n\t\t// Update tabindex for roving tabindex pattern.\n\t\ttrigger.setAttribute( 'tabindex', isActive ? '0' : '-1' );\n\t}\n\n\t/**\n\t * Handle trigger click.\n\t *\n\t * @param {Event} e Click event.\n\t *\n\t * @protected\n\t */\n\tprotected handleTriggerClick( e: Event ): void {\n\t\t// Find the closest tp-tabs element.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\t\tconst trigger = this.getTrigger();\n\t\tconst panelId = this.getPanelId();\n\n\t\t// If the tabs component, trigger, or panel ID is missing, do nothing.\n\t\tif ( ! tabs || ! trigger || '' === panelId ) {\n\t\t\t// Exit if required elements are not found.\n\t\t\treturn;\n\t\t}\n\n\t\t// For anchors, prevent default if update-url is not enabled.\n\t\tif ( trigger instanceof HTMLAnchorElement && 'yes' !== tabs.getAttribute( 'update-url' ) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\t// Find the target panel.\n\t\tconst targetPanel: HTMLElement | null = document.getElementById( panelId );\n\n\t\t// Check if the target panel belongs to a nested tp-tabs.\n\t\tif ( targetPanel ) {\n\t\t\tconst panelTabs: TPTabsElement | null = targetPanel.closest( 'tp-tabs' );\n\n\t\t\t// If the panel belongs to a different (nested) tp-tabs, update that instead.\n\t\t\tif ( panelTabs && panelTabs !== tabs ) {\n\t\t\t\t// Update the nested tp-tabs.\n\t\t\t\tpanelTabs.setAttribute( 'current-tab', panelId );\n\n\t\t\t\t// Also ensure the parent tab containing the nested tp-tabs is open.\n\t\t\t\tconst parentTab = panelTabs.closest( 'tp-tabs-tab' );\n\n\t\t\t\t// Check if found a parent tab.\n\t\t\t\tif ( parentTab && parentTab.id ) {\n\t\t\t\t\t// Check if parent's current-tab is already the same value.\n\t\t\t\t\tif ( tabs.getAttribute( 'current-tab' ) === parentTab.id ) {\n\t\t\t\t\t\t// Force update since setAttribute won't trigger attributeChangedCallback.\n\t\t\t\t\t\ttabs.update();\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttabs.setAttribute( 'current-tab', parentTab.id );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Exit early since we've handled the nested case.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Update the 'current-tab' attribute on the tabs component.\n\t\ttabs.setAttribute( 'current-tab', panelId );\n\t}\n\n\t/**\n\t * Check if this component contains the trigger for the current tab.\n\t *\n\t * @param {string} currentTab Current tab ID.\n\t *\n\t * @return {boolean} Whether it is the current tab or not.\n\t */\n\tisCurrentTab( currentTab: string = '' ): boolean {\n\t\t// Return true if this nav item's panel ID matches the current tab.\n\t\treturn currentTab === this.getPanelId();\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * TP Tabs Nav Element.\n */\nexport class TPTabsNavElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Add keyboard event listener for arrow key navigation.\n\t\tthis.addEventListener( 'keydown', this.handleKeyDown.bind( this ) );\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tprivate isAriaEnabled(): boolean {\n\t\t// Get parent tabs component.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\n\t\t// Return whether aria management is enabled.\n\t\treturn tabs?.isAriaEnabled() ?? true;\n\t}\n\n\t/**\n\t * Get all tab trigger elements (buttons or anchors).\n\t *\n\t * @return {Array<HTMLButtonElement | HTMLAnchorElement>} Array of trigger elements.\n\t */\n\tprivate getTabTriggers(): Array<HTMLButtonElement | HTMLAnchorElement> {\n\t\t// Get all nav items and collect their triggers.\n\t\tconst navItems = this.querySelectorAll( 'tp-tabs-nav-item' );\n\t\tconst triggers: Array<HTMLButtonElement | HTMLAnchorElement> = [];\n\n\t\t// Iterate over nav items to find triggers.\n\t\tnavItems.forEach( ( navItem ) => {\n\t\t\t// Look for button first, then anchor.\n\t\t\tconst trigger = navItem.querySelector( 'button' ) || navItem.querySelector( 'a' );\n\n\t\t\t// Add trigger to array if found.\n\t\t\tif ( trigger ) {\n\t\t\t\ttriggers.push( trigger );\n\t\t\t}\n\t\t} );\n\n\t\t// Return all triggers.\n\t\treturn triggers;\n\t}\n\n\t/**\n\t * Handle keydown events for keyboard navigation.\n\t *\n\t * @param {KeyboardEvent} e Keyboard event.\n\t */\n\tprivate handleKeyDown( e: KeyboardEvent ): void {\n\t\t// Only handle if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Bail early.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get all tab triggers.\n\t\tconst triggers = this.getTabTriggers();\n\n\t\t// Bail if no triggers.\n\t\tif ( triggers.length === 0 ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Find current focused trigger index using ownerDocument.\n\t\tconst currentIndex = triggers.findIndex( ( trigger ) => trigger === this.ownerDocument.activeElement );\n\n\t\t// Only handle if focus is on a trigger.\n\t\tif ( currentIndex === -1 ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get new index.\n\t\tlet newIndex = currentIndex;\n\n\t\t// Handle arrow keys, Home, and End.\n\t\tswitch ( e.key ) {\n\t\t\t// Move to previous tab, wrap to end if at start.\n\t\t\tcase 'ArrowLeft':\n\t\t\t\tnewIndex = currentIndex === 0 ? triggers.length - 1 : currentIndex - 1;\n\t\t\t\tbreak;\n\n\t\t\t// Move to next tab, wrap to start if at end.\n\t\t\tcase 'ArrowRight':\n\t\t\t\tnewIndex = currentIndex === triggers.length - 1 ? 0 : currentIndex + 1;\n\t\t\t\tbreak;\n\n\t\t\t// Move to first tab.\n\t\t\tcase 'Home':\n\t\t\t\tnewIndex = 0;\n\t\t\t\tbreak;\n\n\t\t\t// Move to last tab.\n\t\t\tcase 'End':\n\t\t\t\tnewIndex = triggers.length - 1;\n\t\t\t\tbreak;\n\n\t\t\t// Not a navigation key, bail.\n\t\t\tdefault:\n\n\t\t\t\t// Not a navigation key, bail.\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Prevent default browser behavior.\n\t\te.preventDefault();\n\n\t\t// Activate the new tab first (updates tabindex), then focus.\n\t\tconst newTrigger = triggers[ newIndex ];\n\t\tnewTrigger.click();\n\t\tnewTrigger.focus();\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * TP Tabs Tab Element.\n */\nexport class TPTabsTabElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Set up ARIA attributes.\n\t\tthis.setupAriaAttributes();\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Observe the open attribute to update ARIA state.\n\t\treturn [ 'open' ];\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string, oldValue: string, newValue: string ): void {\n\t\t// Early return if no change.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// No change.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update ARIA state when open attribute changes.\n\t\tif ( 'open' === name ) {\n\t\t\tthis.updateAriaState( 'yes' === newValue );\n\t\t}\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tprivate isAriaEnabled(): boolean {\n\t\t// Get parent tabs component.\n\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\n\t\t// Return whether aria management is enabled.\n\t\treturn tabs?.isAriaEnabled() ?? true;\n\t}\n\n\t/**\n\t * Set up ARIA attributes on this tab panel.\n\t */\n\tprivate setupAriaAttributes(): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the panel ID.\n\t\tconst panelId = this.getAttribute( 'id' );\n\n\t\t// Find the corresponding tab trigger by matching href.\n\t\tif ( panelId ) {\n\t\t\tconst tabs: TPTabsElement | null = this.closest( 'tp-tabs' );\n\t\t\tconst trigger = tabs?.querySelector( `a[href=\"#${ panelId }\"]` );\n\n\t\t\t// Set aria-labelledby if trigger has an ID.\n\t\t\tif ( trigger?.id && ! this.hasAttribute( 'aria-labelledby' ) ) {\n\t\t\t\tthis.setAttribute( 'aria-labelledby', trigger.id );\n\t\t\t}\n\t\t}\n\n\t\t// Set initial ARIA state.\n\t\tconst isOpen = 'yes' === this.getAttribute( 'open' );\n\t\tthis.updateAriaState( isOpen );\n\t}\n\n\t/**\n\t * Update ARIA state on this tab panel.\n\t *\n\t * @param {boolean} isOpen Whether this panel is open.\n\t */\n\tprivate updateAriaState( isOpen: boolean ): void {\n\t\t// Check if aria management is enabled.\n\t\tif ( ! this.isAriaEnabled() ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update aria-hidden, inert, and tabindex based on open state.\n\t\tif ( isOpen ) {\n\t\t\tthis.removeAttribute( 'aria-hidden' );\n\t\t\tthis.removeAttribute( 'inert' );\n\t\t\tthis.setAttribute( 'tabindex', '0' );\n\t\t} else {\n\t\t\tthis.setAttribute( 'aria-hidden', 'true' );\n\t\t\tthis.setAttribute( 'inert', '' );\n\t\t\tthis.removeAttribute( 'tabindex' );\n\t\t}\n\t}\n}\n","/**\n * Internal dependencies.\n */\nimport { TPTabsNavItemElement } from './tp-tabs-nav-item';\nimport { TPTabsTabElement } from './tp-tabs-tab';\n\n/**\n * TP Tabs.\n */\nexport class TPTabsElement extends HTMLElement {\n\t/**\n\t * Constructor.\n\t */\n\tconstructor() {\n\t\t// Initialize parent.\n\t\tsuper();\n\n\t\t// Update the current tab based on the URL hash.\n\t\tthis.updateTabFromUrlHash();\n\n\t\t// Listen for hash changes in the URL and update the tab accordingly.\n\t\twindow.addEventListener( 'hashchange', this.updateTabFromUrlHash.bind( this ) );\n\t}\n\n\t/**\n\t * Get observed attributes.\n\t *\n\t * @return {Array} List of observed attributes.\n\t */\n\tstatic get observedAttributes(): string[] {\n\t\t// Attributes observed in the TPTabsElement web-component.\n\t\treturn [ 'current-tab', 'update-url', 'overflow', 'aria' ];\n\t}\n\n\t/**\n\t * Check if ARIA management is enabled.\n\t *\n\t * @return {boolean} Whether ARIA management is enabled.\n\t */\n\tisAriaEnabled(): boolean {\n\t\t// Return whether aria management is enabled (default: yes).\n\t\treturn 'no' !== this.getAttribute( 'aria' );\n\t}\n\n\t/**\n\t * Attribute changed callback.\n\t *\n\t * @param {string} name Attribute name.\n\t * @param {string} oldValue Old value.\n\t * @param {string} newValue New value.\n\t */\n\tattributeChangedCallback( name: string = '', oldValue: string = '', newValue: string = '' ): void {\n\t\t// If the attribute value hasn't changed, do nothing.\n\t\tif ( oldValue === newValue ) {\n\t\t\t// Early return.\n\t\t\treturn;\n\t\t}\n\n\t\t// Update the component whenever an observed attribute changes.\n\t\tthis.update();\n\n\t\t// If the 'current-tab' attribute has changed, dispatch a 'change' event.\n\t\tif ( 'current-tab' === name ) {\n\t\t\tthis.dispatchEvent( new CustomEvent( 'change', { bubbles: true } ) );\n\t\t}\n\t}\n\n\t/**\n\t * Update this component.\n\t */\n\tupdate(): void {\n\t\t// Wrap inside setTimeout to avoid high INP.\n\t\tsetTimeout( () => {\n\t\t\t// Get current tab.\n\t\t\tconst currentTab: string = this.getAttribute( 'current-tab' ) ?? '';\n\n\t\t\t// Check if current tab exists.\n\t\t\tif ( ! this.querySelector( `tp-tabs-tab[id=\"${ currentTab }\"]` ) ) {\n\t\t\t\t// Exit if no matching tab is found.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get current nested tab if has.\n\t\t\tconst currentNestedTab = this.getCurrentNestedTab( currentTab );\n\n\t\t\t// Update nav items.\n\t\t\tconst navItems: NodeListOf<TPTabsNavItemElement> = this.querySelectorAll( 'tp-tabs-nav-item' );\n\n\t\t\t// Update the navigation items based on the current tab.\n\t\t\tif ( navItems ) {\n\t\t\t\tnavItems.forEach( ( navItem: TPTabsNavItemElement ): void => {\n\t\t\t\t\t// If the nav item corresponds to the current tab or nested tab, set it as active.\n\t\t\t\t\tif ( navItem.isCurrentTab( currentTab ) || ( currentNestedTab && navItem.isCurrentTab( currentNestedTab ) ) ) {\n\t\t\t\t\t\tnavItem.setAttribute( 'active', 'yes' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnavItem.removeAttribute( 'active' );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Update tabs.\n\t\t\tconst tabs: NodeListOf<TPTabsTabElement> = this.querySelectorAll( 'tp-tabs-tab' );\n\n\t\t\t// Update the tab panels based on the current tab.\n\t\t\tif ( tabs ) {\n\t\t\t\ttabs.forEach( ( tab: TPTabsTabElement ): void => {\n\t\t\t\t\t// If the tab corresponds to the current tab or nested tab, open it.\n\t\t\t\t\tif ( currentTab === tab.getAttribute( 'id' ) || ( currentNestedTab && currentNestedTab === tab.getAttribute( 'id' ) ) ) {\n\t\t\t\t\t\ttab.setAttribute( 'open', 'yes' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttab.removeAttribute( 'open' );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}, 0 );\n\t}\n\n\t/**\n\t * Update tab from URL hash.\n\t */\n\tupdateTabFromUrlHash(): void {\n\t\t// If 'update-url' attribute is not set to 'yes', do nothing.\n\t\tif ( 'yes' !== this.getAttribute( 'update-url' ) ) {\n\t\t\t// Exit if the 'update-url' attribute is not enabled.\n\t\t\treturn;\n\t\t}\n\n\t\t// Set current associated tab.\n\t\tthis.setCurrentTab();\n\t}\n\n\t/**\n\t * Set current tab.\n\t *\n\t * @param {string} tabId Tab ID.\n\t */\n\tsetCurrentTab( tabId: string = '' ): void {\n\t\t// If a tab ID is provided, set it as the current tab.\n\t\tif ( '' !== tabId ) {\n\t\t\tthis.setAttribute( 'current-tab', tabId );\n\t\t}\n\n\t\t// Set current tab based on current url hash.\n\t\tconst urlHash: string = window.location.hash;\n\n\t\t// Find the link that matches the URL hash.\n\t\tif ( '' !== urlHash ) {\n\t\t\tconst currentLink: HTMLAnchorElement | null = this.querySelector( `a[href=\"${ urlHash }\"]` );\n\t\t\tconst currentTab = currentLink?.closest( 'tp-tabs' );\n\t\t\tcurrentTab?.setAttribute( 'current-tab', urlHash.replace( '#', '' ) );\n\t\t}\n\t}\n\n\t/**\n\t * Get current nested tab.\n\t *\n\t * @param {string} currentTab Tab ID.\n\t *\n\t * @return {string} If has Nested current tab or empty.\n\t */\n\tgetCurrentNestedTab( currentTab: string = '' ): string {\n\t\t// If no current tab is provided, return an empty string.\n\t\tif ( '' === currentTab ) {\n\t\t\t// Exit if no current tab is provided.\n\t\t\treturn '';\n\t\t}\n\n\t\t// Find the element corresponding to the current tab ID.\n\t\tconst currentTabElement = this.querySelector( `tp-tabs-tab[id=\"${ currentTab }\"]` );\n\n\t\t// Find the nested tp-tabs element within the current tab.\n\t\tconst currentNestedTabElement = currentTabElement?.querySelector( 'tp-tabs' );\n\n\t\t// Get the ID of the current nested tab, if any.\n\t\tconst currentNestedTab = currentNestedTabElement?.getAttribute( 'current-tab' );\n\n\t\t// Return the nested tab ID, or an empty string if none exists.\n\t\treturn currentNestedTab ?? '';\n\t}\n}\n","/**\n * Styles.\n */\nimport './style.scss';\n\n/**\n * Components.\n */\nimport { TPTabsNavItemElement } from './tp-tabs-nav-item';\nimport { TPTabsNavElement } from './tp-tabs-nav';\nimport { TPTabsTabElement } from './tp-tabs-tab';\nimport { TPTabsElement } from './tp-tabs';\n\n/**\n * Register Components.\n */\n\n// Register parent first so children can find it during their constructor.\ncustomElements.define( 'tp-tabs', TPTabsElement );\ncustomElements.define( 'tp-tabs-nav', TPTabsNavElement );\ncustomElements.define( 'tp-tabs-nav-item', TPTabsNavItemElement );\ncustomElements.define( 'tp-tabs-tab', TPTabsTabElement );\n"],"names":["TPTabsNavItemElement","HTMLElement","constructor","super","trigger","this","getTrigger","addEventListener","handleTriggerClick","bind","setupAriaAttributes","querySelector","observedAttributes","attributeChangedCallback","name","oldValue","newValue","updateAriaState","isAriaEnabled","tabs","closest","id","Math","random","toString","substring","panelId","getPanelId","hasAttribute","setAttribute","isActive","getAttribute","HTMLAnchorElement","replace","e","preventDefault","targetPanel","document","getElementById","panelTabs","parentTab","update","isCurrentTab","currentTab","TPTabsNavElement","handleKeyDown","getTabTriggers","navItems","querySelectorAll","triggers","forEach","navItem","push","length","currentIndex","findIndex","ownerDocument","activeElement","newIndex","key","newTrigger","click","focus","TPTabsTabElement","isOpen","removeAttribute","TPTabsElement","updateTabFromUrlHash","window","dispatchEvent","CustomEvent","bubbles","setTimeout","currentNestedTab","getCurrentNestedTab","tab","setCurrentTab","tabId","urlHash","location","hash","currentLink","currentTabElement","currentNestedTabElement","customElements","define"],"sourceRoot":""}
|