UNPKG

@flexilla/accordion

Version:

A versatile and interactive accordion component for creating collapsible sections in web applications, conserving space and improving user experience

2 lines (1 loc) 9.17 kB
(function(c,a){typeof exports=="object"&&typeof module<"u"?a(exports):typeof define=="function"&&define.amd?define(["exports"],a):(c=typeof globalThis<"u"?globalThis:c||self,a(c["@flexilla/accordion"]={}))})(this,function(c){"use strict";var k=Object.defineProperty;var $=(c,a,d)=>a in c?k(c,a,{enumerable:!0,configurable:!0,writable:!0,value:d}):c[a]=d;var l=(c,a,d)=>$(c,typeof a!="symbol"?a+"":a,d);const a=(i,t=document.body)=>t.querySelector(i),d=(i,t=document.body)=>{const e=f(i,t);return Array.from(e).find(n=>n.parentElement===t)},f=(i,t=document.body)=>Array.from(t.querySelectorAll(i)),b=(i,t,e)=>{const n=new CustomEvent(t,{detail:e});i.dispatchEvent(n)},A=({container:i,attributeToWatch:t,onChildAdded:e})=>{const n=new MutationObserver(s=>{for(const o of s)if(o.type==="childList"&&Array.from(o.addedNodes).some(r=>r instanceof HTMLElement&&r.hasAttribute(t))){e();break}});return n.observe(i,{childList:!0}),()=>{n.disconnect()}},y=i=>{const t=d("[data-accordion-trigger]",i),e=d("[data-accordion-content]",i),n=i.hasAttribute("data-default-open");if(!(t instanceof HTMLButtonElement))throw new Error("The element does't have a Valid Trigger");if(!(e instanceof HTMLDivElement))throw new Error("No Valid Content Element");const s=i.getAttribute("data-accordion-value")??"",o=t.getAttribute("aria-expanded")==="true";return{accordionTriggerElement:t,accordionContentElement:e,accordionItemValue:s,isItemExpanded:o,defaultOpened:n}},I=({element:i,callback:t,type:e,keysCheck:n})=>{const s=getComputedStyle(i),o=s.transition;if(o!=="none"&&o!==""&&!n.includes(o)){const r="transitionend",h=()=>{i.removeEventListener(r,h),t()};i.addEventListener(r,h,{once:!0})}else t()},w=({element:i,callback:t})=>{I({element:i,callback:t,type:"transition",keysCheck:["all 0s ease 0s","all"]})},m=(i,t)=>{i.setAttribute("aria-hidden",t==="open"?"false":"true"),i.setAttribute("data-state",t)},x=(i,t="close",e="0px")=>{i.style.height=t==="open"?"auto":e,m(i,t)},T=i=>{if(i.getAttribute("data-state")==="open")return;m(i,"open");const t=i.scrollHeight;i.style.height=`${t}px`,w({element:i,callback:()=>{i.getAttribute("data-state")==="open"&&(i.style.height="auto")}})},C=(i,t="0px")=>{i.getAttribute("data-state")!=="close"&&(i.style.height=`${i.scrollHeight}px`,i.offsetHeight,i.style.height=t,m(i,"close"))},L=(i,t,e)=>{const n=f(":scope > [data-accordion-item]",e),s=i.parentElement;if(!n.includes(s))return null;const o=n.indexOf(s),r=t?o-1:o+1,h=n[r]??(t?n[n.length-1]:n[0]),g=d(":scope > [data-accordion-trigger]",h);return g instanceof HTMLElement?g:null},O=(i,t)=>{if(!(document.activeElement instanceof HTMLElement))return;const e=document.activeElement,n=e.parentElement;if(!(!e.matches("[data-accordion-trigger]")||!(n!=null&&n.matches("[data-accordion-item]"))||n.parentElement!==t)&&(i.key==="ArrowUp"||i.key==="ArrowDown")){i.preventDefault();const s=L(e,i.key==="ArrowUp",t);s&&s.focus()}},E=(i,t)=>{i.ariaExpanded=t==="open"?"true":"false"},S=({collapsible:i,triggerElement:t,state:e,onInit:n})=>{n?(x(i,e),E(t,e)):e==="open"?(E(t,"open"),T(i)):(E(t,"close"),C(i))};class p{static initGlobalRegistry(){window.$flexillaInstances||(window.$flexillaInstances={})}static register(t,e,n){return this.initGlobalRegistry(),window.$flexillaInstances[t]||(window.$flexillaInstances[t]=[]),this.getInstance(t,e)||(window.$flexillaInstances[t].push({element:e,instance:n}),n)}static getInstance(t,e){var n,s;return this.initGlobalRegistry(),(s=(n=window.$flexillaInstances[t])==null?void 0:n.find(o=>o.element===e))==null?void 0:s.instance}static removeInstance(t,e){this.initGlobalRegistry(),window.$flexillaInstances[t]&&(window.$flexillaInstances[t]=window.$flexillaInstances[t].filter(n=>n.element!==e))}}const u=class u{constructor(t,e={}){l(this,"accordionEl");l(this,"options");l(this,"items");l(this,"eventListeners",[]);l(this,"cleanupObserver",null);l(this,"handleKeyEvents",t=>{O(t,this.accordionEl)});l(this,"reload",()=>{this.cleanup(),this.items=f("[data-accordion-item]",this.accordionEl).filter(t=>t.parentElement&&t.parentElement===this.accordionEl),this.initAccordion()});l(this,"triggerItemState",(t,e,n)=>{this.options.preventClosingAll&&(this.options.accordionType==="single"&&n||this.options.accordionType==="multiple"&&this.items.filter(s=>s.getAttribute("data-state")==="open").length===1&&n)||(this.setItemState(t,e),this.options.accordionType==="single"&&this.closeOther({current:t}),this.dispatchedEvent(t))});l(this,"cleanup",()=>{this.accordionEl&&(this.items.forEach(t=>{t&&t.hasAttribute("data-state")&&t.removeAttribute("data-state")}),this.eventListeners.forEach(({element:t,type:e,listener:n})=>{t&&t.removeEventListener&&t.removeEventListener(e,n)}),this.cleanupObserver&&(this.cleanupObserver(),this.cleanupObserver=null),this.eventListeners=[],this.items=[],p.removeInstance("accordion",this.accordionEl))});if(this.accordionEl=typeof t=="string"?a(t):t,!this.accordionEl)throw new Error(`Accordion element not found: ${typeof t=="string"?`No element matches selector "${t}"`:"Provided HTMLElement is null or undefined"}`);const n=p.getInstance("accordion",this.accordionEl);if(n)return n;this.options={accordionType:this.accordionEl.dataset.accordionType||e.accordionType||"single",preventClosingAll:this.accordionEl.hasAttribute("data-prevent-closing-all")||e.preventClosingAll||!1,defaultValue:this.accordionEl.dataset.defaultValue||e.defaultValue||"",allowCloseFromContent:this.accordionEl.hasAttribute("data-allow-close-from-content")||e.allowCloseFromContent||!1,onChangeItem:e.onChangeItem},this.items=f("[data-accordion-item]",this.accordionEl).filter(s=>s.parentElement&&s.parentElement===this.accordionEl),this.initAccordion()}initAccordion(){if(!this.accordionEl)return;const{accordionType:t,defaultValue:e,preventClosingAll:n}=this.options;let s=d(`[data-accordion-item][data-accordion-value="${e}"]`,this.accordionEl);if(t==="single")this.options.preventClosingAll&&!(s instanceof HTMLElement)&&(s=this.items[0]),this.closeOther({current:s}),s&&this.setItemState(s,"open",!0);else{this.closeAll(!0);const o=this.items.some(r=>r.getAttribute("data-state")==="open");if(n&&!o)this.setItemState(this.items[0],"open",!0);else{const r=this.items.filter(h=>h.getAttribute("data-state")==="open");for(const h of r)this.setItemState(h,"open",!0)}}this.addEventListeners(),this.accordionEl.addEventListener("keydown",this.handleKeyEvents),this.eventListeners.push({element:this.accordionEl,type:"keydown",listener:this.handleKeyEvents}),p.register("accordion",this.accordionEl,this),this.cleanupObserver=A({container:this.accordionEl,attributeToWatch:"data-accordion-item",onChildAdded:this.reload})}destroy(){this.accordionEl&&(this.items.forEach(t=>{t&&t.hasAttribute("data-state")&&t.removeAttribute("data-state")}),this.eventListeners.forEach(({element:t,type:e,listener:n})=>{t&&t.removeEventListener&&t.removeEventListener(e,n)}),this.eventListeners=[],this.items=[],p.removeInstance("accordion",this.accordionEl),this.cleanupObserver&&(this.cleanupObserver(),this.cleanupObserver=null))}setItemState(t,e,n){t.setAttribute("data-state",e);const{accordionContentElement:s,accordionTriggerElement:o}=y(t);S({collapsible:s,triggerElement:o,state:e,onInit:n})}closeOther({current:t,onInit:e}){this.items.forEach(n=>{n!==t&&(e&&this.options.accordionType==="multiple"?n.hasAttribute("data-default-open")?this.setItemState(n,"open"):this.setItemState(n,"close"):this.setItemState(n,"close"))})}closeAll(t){this.closeOther({onInit:t})}dispatchedEvent(t){const{accordionContentElement:e,accordionTriggerElement:n,isItemExpanded:s,accordionItemValue:o}=y(t);this.options.onChangeItem&&this.options.onChangeItem({expandedItem:{accordionItem:this.accordionEl,trigger:n,content:e,value:o,isExpanded:s}}),b(this.accordionEl,"change-item",{targetElement:{trigger:n,content:e,isExpanded:s},items:this.items})}addEventListeners(){this.items.forEach(t=>{const e=a("[data-accordion-trigger]",t),n=a("[data-accordion-content]",t),s=()=>this.triggerItemState(t,"close",!0),o=r=>{r.preventDefault();const h=t.getAttribute("data-state")==="open";let g=h?"close":"open";this.triggerItemState(t,g,h)};e&&(e.addEventListener("click",o),this.eventListeners.push({element:e,type:"click",listener:o})),this.options.allowCloseFromContent&&n&&(n.addEventListener("click",s),this.eventListeners.push({element:n,type:"click",listener:s}))})}show(t){const e=d(`[data-accordion-item][data-accordion-value="${t}"]`,this.accordionEl);!e||e.getAttribute("data-state")==="open"||(this.options.accordionType==="single"&&this.closeOther({current:e}),this.setItemState(e,"open"),this.dispatchedEvent(e))}hide(t){const e=d(`[data-accordion-item][data-accordion-value="${t}"]`,this.accordionEl);if(!(!e||!(e.getAttribute("data-state")==="open"))){if(this.options.preventClosingAll){const s=this.items.filter(o=>o.getAttribute("data-state")==="open");if(s.length===1&&e===s[0])return}this.setItemState(e,"close"),this.dispatchedEvent(e)}}};l(u,"autoInit",(t="[data-fx-accordion]")=>{const e=f(t,document.documentElement);for(const n of e)new u(n)}),l(u,"init",(t,e={})=>new u(t,e));let v=u;c.Accordion=v,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});