@abydahana/aksara-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/aksara.css +33499 -0
  4. package/dist/aksara.d.ts +284 -0
  5. package/dist/aksara.esm.js +1604 -0
  6. package/dist/aksara.js +1608 -0
  7. package/dist/aksara.min.css +1 -0
  8. package/dist/aksara.min.js +1 -0
  9. package/dist/components/buttons/button-group.d.ts +10 -0
  10. package/dist/components/buttons/button-group.js +12 -0
  11. package/dist/components/buttons/button.d.ts +18 -0
  12. package/dist/components/buttons/button.js +28 -0
  13. package/dist/components/buttons/close-button.d.ts +9 -0
  14. package/dist/components/buttons/close-button.js +13 -0
  15. package/dist/components/buttons/index.d.ts +3 -0
  16. package/dist/components/buttons/index.js +3 -0
  17. package/dist/components/data/accordion.d.ts +17 -0
  18. package/dist/components/data/accordion.js +37 -0
  19. package/dist/components/data/avatar.d.ts +26 -0
  20. package/dist/components/data/avatar.js +64 -0
  21. package/dist/components/data/card.d.ts +39 -0
  22. package/dist/components/data/card.js +34 -0
  23. package/dist/components/data/carousel.d.ts +15 -0
  24. package/dist/components/data/carousel.js +47 -0
  25. package/dist/components/data/index.d.ts +7 -0
  26. package/dist/components/data/index.js +7 -0
  27. package/dist/components/data/list-group.d.ts +22 -0
  28. package/dist/components/data/list-group.js +30 -0
  29. package/dist/components/data/media-grid.d.ts +19 -0
  30. package/dist/components/data/media-grid.js +47 -0
  31. package/dist/components/data/table.d.ts +35 -0
  32. package/dist/components/data/table.js +30 -0
  33. package/dist/components/feedback/alert.d.ts +10 -0
  34. package/dist/components/feedback/alert.js +19 -0
  35. package/dist/components/feedback/badge.d.ts +13 -0
  36. package/dist/components/feedback/badge.js +10 -0
  37. package/dist/components/feedback/index.d.ts +6 -0
  38. package/dist/components/feedback/index.js +6 -0
  39. package/dist/components/feedback/placeholder.d.ts +9 -0
  40. package/dist/components/feedback/placeholder.js +11 -0
  41. package/dist/components/feedback/progress.d.ts +14 -0
  42. package/dist/components/feedback/progress.js +22 -0
  43. package/dist/components/feedback/spinner.d.ts +9 -0
  44. package/dist/components/feedback/spinner.js +12 -0
  45. package/dist/components/feedback/toast.d.ts +22 -0
  46. package/dist/components/feedback/toast.js +36 -0
  47. package/dist/components/form/checkbox.d.ts +17 -0
  48. package/dist/components/form/checkbox.js +29 -0
  49. package/dist/components/form/floating-label.d.ts +9 -0
  50. package/dist/components/form/floating-label.js +14 -0
  51. package/dist/components/form/form-control.d.ts +30 -0
  52. package/dist/components/form/form-control.js +28 -0
  53. package/dist/components/form/index.d.ts +11 -0
  54. package/dist/components/form/index.js +11 -0
  55. package/dist/components/form/input-group.d.ts +16 -0
  56. package/dist/components/form/input-group.js +14 -0
  57. package/dist/components/form/input.d.ts +18 -0
  58. package/dist/components/form/input.js +19 -0
  59. package/dist/components/form/layout.d.ts +20 -0
  60. package/dist/components/form/layout.js +15 -0
  61. package/dist/components/form/radio.d.ts +32 -0
  62. package/dist/components/form/radio.js +49 -0
  63. package/dist/components/form/range.d.ts +13 -0
  64. package/dist/components/form/range.js +18 -0
  65. package/dist/components/form/select.d.ts +25 -0
  66. package/dist/components/form/select.js +37 -0
  67. package/dist/components/form/switch.d.ts +16 -0
  68. package/dist/components/form/switch.js +30 -0
  69. package/dist/components/form/textarea.d.ts +17 -0
  70. package/dist/components/form/textarea.js +19 -0
  71. package/dist/components/index.d.ts +7 -0
  72. package/dist/components/index.js +7 -0
  73. package/dist/components/navigation/breadcrumb.d.ts +13 -0
  74. package/dist/components/navigation/breadcrumb.js +25 -0
  75. package/dist/components/navigation/index.d.ts +5 -0
  76. package/dist/components/navigation/index.js +5 -0
  77. package/dist/components/navigation/navbar.d.ts +20 -0
  78. package/dist/components/navigation/navbar.js +22 -0
  79. package/dist/components/navigation/pagination.d.ts +15 -0
  80. package/dist/components/navigation/pagination.js +31 -0
  81. package/dist/components/navigation/scrollspy.d.ts +23 -0
  82. package/dist/components/navigation/scrollspy.js +43 -0
  83. package/dist/components/navigation/tabs.d.ts +15 -0
  84. package/dist/components/navigation/tabs.js +56 -0
  85. package/dist/components/overlay/collapse.d.ts +20 -0
  86. package/dist/components/overlay/collapse.js +27 -0
  87. package/dist/components/overlay/dropdown.d.ts +33 -0
  88. package/dist/components/overlay/dropdown.js +41 -0
  89. package/dist/components/overlay/index.d.ts +7 -0
  90. package/dist/components/overlay/index.js +7 -0
  91. package/dist/components/overlay/media-modal.d.ts +15 -0
  92. package/dist/components/overlay/media-modal.js +83 -0
  93. package/dist/components/overlay/modal.d.ts +32 -0
  94. package/dist/components/overlay/modal.js +47 -0
  95. package/dist/components/overlay/offcanvas.d.ts +20 -0
  96. package/dist/components/overlay/offcanvas.js +33 -0
  97. package/dist/components/overlay/popover.d.ts +19 -0
  98. package/dist/components/overlay/popover.js +24 -0
  99. package/dist/components/overlay/tooltip.d.ts +17 -0
  100. package/dist/components/overlay/tooltip.js +21 -0
  101. package/dist/components/utils.d.ts +3 -0
  102. package/dist/components/utils.js +25 -0
  103. package/package.json +111 -0
@@ -0,0 +1 @@
1
+ (function(){ const registry=new Map();const instances=new Set();const focusableSelector=["a[href]","area[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])","iframe","object","embed","[contenteditable]","[tabindex]:not([tabindex='-1'])"].join(",");function toElements(target){ if(!target)return[];if(typeof target==="string")return Array.from(document.querySelectorAll(target));if(target instanceof HTMLElement)return[target];if(target instanceof Element)return[target];if(target instanceof NodeList || Array.isArray(target)){ return Array.from(target).filter((item)=>item instanceof HTMLElement);} return[];} function resolveArgs(target,options,defaultSelector){ if(target && typeof target==="object" && !(target instanceof Element)&& !(target instanceof NodeList)&& !Array.isArray(target)){ const opts=target;const resolvedTarget=opts.target || opts.selector || defaultSelector;return { target:resolvedTarget,options:opts };} return { target:target || defaultSelector,options:(options || {})};} function dataName(name){ return name.replace(/[A-Z]/g,(match)=>`-${match.toLowerCase()}`);} function getData(element,component,name){ return element?.getAttribute(`data-${component}-${dataName(name)}`)??null;} function getOption(options,element,component,name,fallback){ if(options[name]!==undefined)return options[name];const value=getData(element,component,name);return value !==null?value:fallback;} function getBooleanOption(options,element,component,name,fallback){ const value=getOption(options,element,component,name,fallback);if(value==="true" || value===true)return true;if(value==="false" || value===false)return false;return Boolean(value);} function getNumberOption(options,element,component,name,fallback){ const value=getOption(options,element,component,name,fallback);const number=Number(value);return Number.isNaN(number)?fallback:number;} function clamp(value,min,max){ return Math.min(Math.max(value,min),max);} function emit(element,name,detail={}){ element.dispatchEvent(new CustomEvent(`aksara:${name}`,{ bubbles:true,detail }));} function getInstance(element,Type,options={}){ const key=Type.componentName;let map=registry.get(key);if(!map){ map=new WeakMap();registry.set(key,map);} if(!map.has(element)){ const instance=new Type(element,options);map.set(element,instance);instances.add(instance);} else if(options && Object.keys(options).length){ const instance=map.get(element);if(instance && typeof instance.updateOptions==="function"){ instance.updateOptions(options);} } return map.get(element);} function createInstanceList(instanceArray){ return new Proxy(instanceArray,{ get(target,prop){ if(prop in target){ const val=target[prop];return typeof val==="function"?val.bind(target):val;} return(...args)=>{ target.forEach((inst)=>{ const fn=inst[prop];if(typeof fn==="function"){ fn(...args);} });return createInstanceList(target);};} });} function createAll(target,Type,options={}){ const items=toElements(target);const insts=items.map((element)=>getInstance(element,Type,options));if(insts.length===1)return insts[0];return createInstanceList(insts);} class Component { element;options;cleanups;constructor(element,options={}){ this.element=element;this.options=options;this.cleanups=[];} updateOptions(options={}){ this.options={...this.options,...options };return this;} on(target,type,handler,options){ target.addEventListener(type,handler,options);this.cleanups.push(()=>target.removeEventListener(type,handler,options));} destroy(){ this.cleanups.splice(0).forEach((cleanup)=>cleanup());instances.delete(this);const ctor=this.constructor;emit(this.element,`${ctor.componentName || "component"}:destroy`,{ instance:this });} } class Modal extends Component { static componentName="modal";isOpen;previousFocus=null;dialog;dragState=null;backdrop;keyboard;focus;scrollLock;draggable;constructor(element,options={}){ super(element,options);this.isOpen=element.classList.contains("modal-open");this.dialog=element.querySelector(".modal-dialog");this.updateOptions(options);this.element.setAttribute("role",this.element.getAttribute("role")|| "dialog");this.element.setAttribute("aria-modal","true");this.element.setAttribute("aria-hidden",this.isOpen?"false":"true");this.on(this.element,"click",(event)=>{ if(event.target===this.element){ if(this.backdrop==="static"){ const staticClass=`${this.constructor.componentName}-static`;this.element.classList.add(staticClass);setTimeout(()=>this.element.classList.remove(staticClass),150);} else if(this.backdrop){ this.hide();} } });this.on(document,"keydown",(event)=>this.onKeydown(event));this.bindDrag();} updateOptions(options={}){ super.updateOptions(options);const component=this.constructor.componentName;const backdrop=getOption(this.options,this.element,component,"backdrop",true);this.backdrop=backdrop==="static"?"static":!(backdrop===false || backdrop==="false");this.keyboard=getBooleanOption(this.options,this.element,component,"keyboard",true);this.focus=getBooleanOption(this.options,this.element,component,"focus",true);this.scrollLock=getBooleanOption(this.options,this.element,component,"scrollLock",true);this.draggable=getBooleanOption(this.options,this.element,component,"draggable",true);return this;} bindDrag(){ if(!this.dialog)return;const header=this.dialog.querySelector(".modal-header");if(!header)return;this.on(header,"pointerdown",(event)=>this.startDrag(event));} startDrag(event){ if(!this.isOpen || !this.draggable || !this.dialog || event.button !==0)return;const target=event.target instanceof Element?event.target:null;if(target?.closest("button,a,input,select,textarea,label,[data-modal-close],[data-no-drag]"))return;const originX=Number.parseFloat(this.dialog.style.getPropertyValue("--aksara-modal-x"))|| 0;const originY=Number.parseFloat(this.dialog.style.getPropertyValue("--aksara-modal-y"))|| 0;const rect=this.dialog.getBoundingClientRect();const baseLeft=rect.left-originX;const baseTop=rect.top-originY;const padding=8;const move=(moveEvent)=>this.drag(moveEvent);const end=()=>{ document.removeEventListener("pointermove",move);document.removeEventListener("pointerup",end);document.removeEventListener("pointercancel",end);this.dialog?.classList.remove("is-dragging");this.dragState=null;};this.dragState={ originX,originY,pointerX:event.clientX,pointerY:event.clientY,minX:padding-baseLeft,maxX:window.innerWidth-padding-rect.width-baseLeft,minY:padding-baseTop,maxY:window.innerHeight-padding-rect.height-baseTop };this.dialog.classList.add("is-dragging");document.addEventListener("pointermove",move);document.addEventListener("pointerup",end);document.addEventListener("pointercancel",end);event.preventDefault();} drag(event){ if(!this.dialog || !this.dragState)return;const nextX=clamp(this.dragState.originX+event.clientX-this.dragState.pointerX,this.dragState.minX,this.dragState.maxX);const nextY=clamp(this.dragState.originY+event.clientY-this.dragState.pointerY,this.dragState.minY,this.dragState.maxY);this.dialog.style.setProperty("--aksara-modal-x",`${nextX}px`);this.dialog.style.setProperty("--aksara-modal-y",`${nextY}px`);} resetPosition(){ if(!this.dialog)return;this.dialog.style.removeProperty("--aksara-modal-x");this.dialog.style.removeProperty("--aksara-modal-y");this.dialog.classList.remove("is-dragging");} show(){ if(this.isOpen)return this;this.previousFocus=document.activeElement;this.isOpen=true;this.element.classList.add("modal-open");this.element.setAttribute("aria-hidden","false");if(this.scrollLock)document.documentElement.style.overflow="hidden";if(this.focus)this.focusFirst();emit(this.element,"modal:show",{ instance:this });return this;} hide(){ if(!this.isOpen)return this;this.isOpen=false;this.element.classList.remove("modal-open");this.element.setAttribute("aria-hidden","true");this.resetPosition();if(this.scrollLock)document.documentElement.style.overflow="";if(this.previousFocus && typeof this.previousFocus.focus==="function")this.previousFocus.focus();emit(this.element,"modal:hide",{ instance:this });return this;} toggle(){ return this.isOpen?this.hide():this.show();} focusFirst(){ const focusable=Array.from(this.element.querySelectorAll(focusableSelector));const first=focusable[0]|| this.element;if(!this.element.hasAttribute("tabindex"))this.element.setAttribute("tabindex","-1");first.focus({ preventScroll:true });} onKeydown(event){ if(!this.isOpen)return;if(event.key==="Escape"){ if(this.keyboard){ event.preventDefault();this.hide();} else if(this.backdrop==="static"){ const staticClass=`${this.constructor.componentName}-static`;this.element.classList.add(staticClass);setTimeout(()=>this.element.classList.remove(staticClass),150);} return;} if(event.key !=="Tab")return;const focusable=Array.from(this.element.querySelectorAll(focusableSelector));if(!focusable.length){ event.preventDefault();this.element.focus();return;} const first=focusable[0];const last=focusable[focusable.length-1];if(event.shiftKey && document.activeElement===first){ event.preventDefault();last.focus();} else if(!event.shiftKey && document.activeElement===last){ event.preventDefault();first.focus();} } } class Dropdown extends Component { static componentName="dropdown";trigger;menu;isOpen;originalParent;originalSibling;scrollHandler;placement;container;offset;keyboard;closeOnSelect;closeOnOutside;constructor(element,options={}){ super(element,options);let trigger;let menu=null;if(element.matches("[data-dropdown]")){ trigger=element;} else if(element.classList.contains("dropdown")){ trigger=element.querySelector("[data-dropdown]")|| element.querySelector("button,a");menu=element.querySelector(".dropdown-menu");} else { trigger=element;} this.trigger=trigger;if(!menu){ const menuSelector=options.menu || options.target ||(trigger &&(trigger.getAttribute("data-dropdown")|| trigger.getAttribute("data-target")));if(menuSelector && typeof menuSelector==="string"){ menu=document.querySelector(menuSelector);} else if(menuSelector instanceof HTMLElement){ menu=menuSelector;} if(!menu && trigger){ if(trigger.nextElementSibling && trigger.nextElementSibling.classList.contains("dropdown-menu")){ menu=trigger.nextElementSibling;} else { menu=trigger.parentElement?.querySelector(".dropdown-menu")|| null;} } } this.menu=menu;this.isOpen=false;this.originalParent=null;this.originalSibling=null;this.scrollHandler=null;this.updateOptions(options);if(this.trigger?.matches(".btn-sm,.input-sm,.form-control-sm,.form-select-sm")|| this.element.classList.contains("dropdown-sm")){ this.menu?.classList.add("dropdown-menu-sm");} if(this.trigger){ this.trigger.setAttribute("aria-haspopup","true");this.trigger.setAttribute("aria-expanded","false");this.on(this.trigger,"click",(event)=>{ const customEvent=event;if(customEvent.__aksaraDropdownHandled)return;customEvent.__aksaraDropdownHandled=true;event.preventDefault();this.toggle(event);});} this.on(document,"click",(event)=>{ if(!this.closeOnOutside)return;const target=event.target;if(!this.element.contains(target)&& !this.menu?.contains(target)){ this.hide();} });this.on(document,"keydown",(event)=>{ if(this.keyboard && event.key==="Escape")this.hide();});if(this.menu){ this.on(this.menu,"click",(event)=>{ const target=event.target;const item=target.closest(".dropdown-item");if(this.closeOnSelect && item && !item.disabled && !item.classList.contains("disabled")){ this.hide();} });} } updateOptions(options={}){ super.updateOptions(options);this.placement=getOption(this.options,this.trigger,"dropdown","placement",getData(this.element,"dropdown","placement")|| "bottom");this.container=getOption(this.options,this.trigger,"dropdown","container",getData(this.element,"dropdown","container")|| "body");this.offset=getNumberOption(this.options,this.trigger,"dropdown","offset",getNumberOption({},this.element,"dropdown","offset",4));this.keyboard=getBooleanOption(this.options,this.trigger,"dropdown","keyboard",getBooleanOption({},this.element,"dropdown","keyboard",true));this.closeOnSelect=getBooleanOption(this.options,this.trigger,"dropdown","closeOnSelect",getBooleanOption({},this.element,"dropdown","closeOnSelect",true));this.closeOnOutside=getBooleanOption(this.options,this.trigger,"dropdown","closeOnOutside",getBooleanOption({},this.element,"dropdown","closeOnOutside",true));return this;} position(){ if(!this.menu || !this.isOpen || !this.trigger)return;this.menu.style.display="block";this.menu.style.position="absolute";this.menu.style.zIndex="1000";const triggerRect=this.trigger.getBoundingClientRect();const menuRect=this.menu.getBoundingClientRect();const gap=this.offset;let top;let left;let placement=this.placement;if(placement==="auto"){ const spaceBelow=window.innerHeight-triggerRect.bottom;const spaceAbove=triggerRect.top;placement=spaceBelow>=menuRect.height || spaceBelow>=spaceAbove?"bottom":"top";} this.menu.classList.remove("dropdown-top","dropdown-bottom","dropdown-start","dropdown-end");this.menu.classList.add(`dropdown-${placement}`);const isRtl=document.documentElement.getAttribute("dir")==="rtl" || document.body?.getAttribute("dir")==="rtl";if(placement==="top"){ top=triggerRect.top-menuRect.height-gap;left=isRtl?triggerRect.right-menuRect.width:triggerRect.left;} else if(placement==="start"){ top=triggerRect.top;left=isRtl?triggerRect.right+gap:triggerRect.left-menuRect.width-gap;} else if(placement==="end"){ top=triggerRect.top;left=isRtl?triggerRect.left-menuRect.width-gap:triggerRect.right+gap;} else { top=triggerRect.bottom+gap;left=isRtl?triggerRect.right-menuRect.width:triggerRect.left;} const viewportWidth=window.innerWidth;left=Math.max(8,Math.min(left,viewportWidth-menuRect.width-8));this.menu.style.top=`${top+window.scrollY}px`;this.menu.style.left=`${left+window.scrollX}px`;this.menu.style.bottom="auto";this.menu.style.right="auto";} show(){ if(!this.menu || this.isOpen)return this;this.isOpen=true;this.originalParent=this.menu.parentNode;this.originalSibling=this.menu.nextSibling;let containerEl=document.body;if(typeof this.container==="string" && this.container !=="body"){ containerEl=document.querySelector(this.container)|| document.body;} else if(this.container instanceof HTMLElement){ containerEl=this.container;} containerEl.appendChild(this.menu);this.menu.classList.add("dropdown-open");this.trigger?.setAttribute("aria-expanded","true");this.position();this.scrollHandler=()=>this.position();window.addEventListener("scroll",this.scrollHandler,{ passive:true });window.addEventListener("resize",this.scrollHandler);emit(this.element,"dropdown:show",{ instance:this });return this;} hide(){ if(!this.menu || !this.isOpen)return this;this.isOpen=false;if(this.scrollHandler){ window.removeEventListener("scroll",this.scrollHandler);window.removeEventListener("resize",this.scrollHandler);this.scrollHandler=null;} this.menu.classList.remove("dropdown-open","dropdown-top","dropdown-bottom","dropdown-start","dropdown-end");this.trigger?.setAttribute("aria-expanded","false");if(this.originalParent){ this.originalParent.insertBefore(this.menu,this.originalSibling);} this.menu.style.display="";this.menu.style.position="";this.menu.style.top="";this.menu.style.left="";this.menu.style.zIndex="";emit(this.element,"dropdown:hide",{ instance:this });return this;} toggle(event){ const clickEvent=(event || window.event);if(clickEvent && clickEvent.type==="click"){ if(clickEvent.__aksaraDropdownHandled && !event){ return this;} clickEvent.__aksaraDropdownHandled=true;} return this.isOpen?this.hide():this.show();} destroy(){ this.hide();super.destroy();} } class FloatingText extends Component { static dataAttribute="data-floating";static role="tooltip";static componentName="floating";tip;showTimeout;hideTimeout;container;html;content;placement;trigger;offset;showDelay;hideDelay;keyboard;constructor(element,options={}){ super(element,options);this.tip=null;this.showTimeout=null;this.hideTimeout=null;this.updateOptions(options);this.bindTriggers();this.on(document,"keydown",(event)=>{ if(this.keyboard && event.key==="Escape")this.hide();});} updateOptions(options={}){ super.updateOptions(options);const ctor=this.constructor;const component=ctor.componentName;const rawContent=(this.options.content??this.options.text??getData(this.element,component,"content")??this.element.getAttribute(ctor.dataAttribute)??"");this.container=getOption(this.options,this.element,component,"container",this.element.getAttribute("data-container")|| "body");this.html=getBooleanOption(this.options,this.element,component,"html",this.element.getAttribute("data-html")==="true");this.content=rawContent;this.placement=getOption(this.options,this.element,component,"placement",this.element.getAttribute("data-placement")|| "top");this.trigger=getOption(this.options,this.element,component,"trigger","hover focus");this.offset=getNumberOption(this.options,this.element,component,"offset",8);this.showDelay=getNumberOption(this.options,this.element,component,"showDelay",0);this.hideDelay=getNumberOption(this.options,this.element,component,"hideDelay",0);this.keyboard=getBooleanOption(this.options,this.element,component,"keyboard",true);if(this.tip){ if(this.html){ this.tip.innerHTML=this.content;} else { this.tip.textContent=this.content;} this.position();} return this;} bindTriggers(){ const triggers=String(this.trigger).split(/\s+/).filter(Boolean);if(triggers.includes("hover")){ this.on(this.element,"mouseenter",()=>this.scheduleShow());this.on(this.element,"mouseleave",()=>this.scheduleHide());} if(triggers.includes("focus")){ this.on(this.element,"focus",()=>this.scheduleShow());this.on(this.element,"blur",()=>this.scheduleHide());} if(triggers.includes("click")){ this.on(this.element,"click",(event)=>{ event.preventDefault();this.toggle();});} } scheduleShow(){ if(this.hideTimeout)clearTimeout(this.hideTimeout);if(this.showTimeout)clearTimeout(this.showTimeout);this.showTimeout=setTimeout(()=>this.show(),this.showDelay);} scheduleHide(){ if(this.showTimeout)clearTimeout(this.showTimeout);if(this.hideTimeout)clearTimeout(this.hideTimeout);this.hideTimeout=setTimeout(()=>this.hide(),this.hideDelay);} show(){ if(this.tip || !this.content)return this;const ctor=this.constructor;this.tip=document.createElement("div");this.tip.className=ctor.componentName;if(this.html){ this.tip.innerHTML=this.content;} else { this.tip.textContent=this.content;} this.tip.setAttribute("role",ctor.role);let containerEl=document.body;if(typeof this.container==="string" && this.container !=="body"){ containerEl=document.querySelector(this.container)|| document.body;} else if(this.container instanceof HTMLElement){ containerEl=this.container;} containerEl.append(this.tip);this.position();emit(this.element,`${ctor.componentName}:show`,{ instance:this });return this;} toggle(){ return this.tip?this.hide():this.show();} hide(){ if(!this.tip)return this;const ctor=this.constructor;this.tip.remove();this.tip=null;emit(this.element,`${ctor.componentName}:hide`,{ instance:this });return this;} position(){ if(!this.tip)return;const rect=this.element.getBoundingClientRect();const tipRect=this.tip.getBoundingClientRect();const gap=this.offset;const isRtl=document.documentElement.getAttribute("dir")==="rtl" || document.body?.getAttribute("dir")==="rtl";let placement=this.placement;if(placement==="auto"){ const spaceBelow=window.innerHeight-rect.bottom;const spaceAbove=rect.top;placement=spaceAbove>=tipRect.height || spaceAbove>=spaceBelow?"top":"bottom";} let physicalPlacement=placement;if(placement==="start"){ physicalPlacement=isRtl?"right":"left";} else if(placement==="end"){ physicalPlacement=isRtl?"left":"right";} const ctor=this.constructor;this.tip.className=`${ctor.componentName} ${ctor.componentName}-${placement}`;const topMap={ top:rect.top-tipRect.height-gap,bottom:rect.bottom+gap,left:rect.top+rect.height/2-tipRect.height/2,right:rect.top+rect.height/2-tipRect.height/2 };const top=topMap[physicalPlacement]??rect.top-tipRect.height-gap;const leftMap={ top:rect.left+rect.width/2-tipRect.width/2,bottom:rect.left+rect.width/2-tipRect.width/2,left:rect.left-tipRect.width-gap,right:rect.right+gap };const left=leftMap[physicalPlacement]??rect.left;this.tip.style.top=`${Math.max(4,top+window.scrollY)}px`;this.tip.style.left=`${Math.max(4,left+window.scrollX)}px`;} destroy(){ if(this.showTimeout)clearTimeout(this.showTimeout);if(this.hideTimeout)clearTimeout(this.hideTimeout);this.hide();super.destroy();} } class Tooltip extends FloatingText { static componentName="tooltip";static dataAttribute="data-tooltip";static role="tooltip";} class Popover extends FloatingText { static componentName="popover";static dataAttribute="data-popover";static role="dialog";} function collapsePanel(panel,duration=250){ const animatedPanel=panel;if(animatedPanel._aksaraCollapseTimer){ clearTimeout(animatedPanel._aksaraCollapseTimer);delete animatedPanel._aksaraCollapseTimer;} if(animatedPanel._aksaraCollapseEnd){ panel.removeEventListener("transitionend",animatedPanel._aksaraCollapseEnd);delete animatedPanel._aksaraCollapseEnd;} if(duration<=0 ||(typeof window !=="undefined" && window.matchMedia?.("(prefers-reduced-motion:reduce)").matches)){ panel.hidden=true;panel.style.removeProperty("height");panel.style.removeProperty("overflow");panel.style.removeProperty("padding-top");panel.style.removeProperty("padding-bottom");panel.style.removeProperty("opacity");panel.style.removeProperty("transition");return;} const computed=window.getComputedStyle(panel);const currentHeight=panel.getBoundingClientRect().height;const currentPaddingTop=computed.paddingTop;const currentPaddingBottom=computed.paddingBottom;panel.style.overflow="hidden";panel.style.height=`${currentHeight}px`;panel.style.paddingTop=currentPaddingTop;panel.style.paddingBottom=currentPaddingBottom;panel.style.opacity="1";panel.style.transition=`height ${duration}ms cubic-bezier(0.4,0,0.2,1),padding-top ${duration}ms cubic-bezier(0.4,0,0.2,1),padding-bottom ${duration}ms cubic-bezier(0.4,0,0.2,1),opacity ${Math.round(duration*0.7)}ms ease`;void panel.offsetHeight;panel.style.height="0px";panel.style.paddingTop="0px";panel.style.paddingBottom="0px";panel.style.opacity="0";const cleanup=()=>{ panel.hidden=true;panel.style.removeProperty("height");panel.style.removeProperty("overflow");panel.style.removeProperty("padding-top");panel.style.removeProperty("padding-bottom");panel.style.removeProperty("opacity");panel.style.removeProperty("transition");if(animatedPanel._aksaraCollapseEnd){ panel.removeEventListener("transitionend",animatedPanel._aksaraCollapseEnd);delete animatedPanel._aksaraCollapseEnd;} delete animatedPanel._aksaraCollapseTimer;};const onEnd=(e)=>{ if(e.target===panel && e.propertyName==="height"){ cleanup();} };animatedPanel._aksaraCollapseEnd=onEnd;panel.addEventListener("transitionend",onEnd);animatedPanel._aksaraCollapseTimer=setTimeout(cleanup,duration+60);} function expandPanel(panel,duration=250){ const animatedPanel=panel;if(animatedPanel._aksaraCollapseTimer){ clearTimeout(animatedPanel._aksaraCollapseTimer);delete animatedPanel._aksaraCollapseTimer;} if(animatedPanel._aksaraCollapseEnd){ panel.removeEventListener("transitionend",animatedPanel._aksaraCollapseEnd);delete animatedPanel._aksaraCollapseEnd;} if(duration<=0 ||(typeof window !=="undefined" && window.matchMedia?.("(prefers-reduced-motion:reduce)").matches)){ panel.hidden=false;panel.style.removeProperty("height");panel.style.removeProperty("overflow");panel.style.removeProperty("padding-top");panel.style.removeProperty("padding-bottom");panel.style.removeProperty("opacity");panel.style.removeProperty("transition");return;} panel.hidden=false;panel.style.removeProperty("height");panel.style.removeProperty("padding-top");panel.style.removeProperty("padding-bottom");panel.style.removeProperty("opacity");panel.style.removeProperty("transition");const computed=window.getComputedStyle(panel);const targetPaddingTop=computed.paddingTop;const targetPaddingBottom=computed.paddingBottom;const targetHeight=panel.getBoundingClientRect().height;panel.style.overflow="hidden";panel.style.height="0px";panel.style.paddingTop="0px";panel.style.paddingBottom="0px";panel.style.opacity="0";void panel.offsetHeight;panel.style.transition=`height ${duration}ms cubic-bezier(0.4,0,0.2,1),padding-top ${duration}ms cubic-bezier(0.4,0,0.2,1),padding-bottom ${duration}ms cubic-bezier(0.4,0,0.2,1),opacity ${duration}ms ease`;panel.style.height=`${targetHeight}px`;panel.style.paddingTop=targetPaddingTop;panel.style.paddingBottom=targetPaddingBottom;panel.style.opacity="1";const cleanup=()=>{ panel.style.removeProperty("height");panel.style.removeProperty("overflow");panel.style.removeProperty("padding-top");panel.style.removeProperty("padding-bottom");panel.style.removeProperty("opacity");panel.style.removeProperty("transition");if(animatedPanel._aksaraCollapseEnd){ panel.removeEventListener("transitionend",animatedPanel._aksaraCollapseEnd);delete animatedPanel._aksaraCollapseEnd;} delete animatedPanel._aksaraCollapseTimer;};const onEnd=(e)=>{ if(e.target===panel && e.propertyName==="height"){ cleanup();} };animatedPanel._aksaraCollapseEnd=onEnd;panel.addEventListener("transitionend",onEnd);animatedPanel._aksaraCollapseTimer=setTimeout(cleanup,duration+60);} class Accordion extends Component { static componentName="accordion";parent;collapsible;buttonSelector;duration;constructor(element,options={}){ super(element,options);this.updateOptions(options);this.on(element,"click",(event)=>{ const target=event.target;const button=target.closest(this.buttonSelector);if(!button || !element.contains(button))return;const panelSelector=button.getAttribute("data-accordion");if(!panelSelector)return;const panel=document.querySelector(panelSelector);if(!panel)return;const expanded=button.getAttribute("aria-expanded")==="true";if(expanded && !this.collapsible)return;const parentScope=this.getParentScope();if(!expanded && parentScope){ parentScope.querySelectorAll(this.buttonSelector).forEach((otherButton)=>{ if(otherButton===button)return;otherButton.setAttribute("aria-expanded","false");const otherPanelSelector=otherButton.getAttribute("data-accordion");if(otherPanelSelector){ const otherPanel=document.querySelector(otherPanelSelector);if(otherPanel &&(!otherPanel.hidden || otherPanel.offsetHeight>0)){ collapsePanel(otherPanel,this.duration);} } });} button.setAttribute("aria-expanded",String(!expanded));if(expanded){ collapsePanel(panel,this.duration);} else { expandPanel(panel,this.duration);} emit(element,"accordion:toggle",{ button,panel,expanded:!expanded });});} updateOptions(options={}){ super.updateOptions(options);const parentVal=getOption(this.options,this.element,"accordion","parent",true);if(parentVal==="true")this.parent=true;else if(parentVal==="false")this.parent=false;else this.parent=parentVal;this.collapsible=getBooleanOption(this.options,this.element,"accordion","collapsible",true);this.buttonSelector=getOption(this.options,this.element,"accordion","buttonSelector","[data-accordion]");this.duration=getNumberOption(this.options,this.element,"accordion","duration",250);return this;} getParentScope(){ if(this.parent===false)return null;if(this.parent===true)return this.element;if(this.parent instanceof Element)return this.parent;if(typeof this.parent==="string")return document.querySelector(this.parent)|| this.element;return this.element;} } class Tabs extends Component { static componentName="tabs";tabSelector;panelSelector;active;activeIndex;keyboard;loop;orientation;constructor(element,options={}){ super(element,options);this.updateOptions(options);this.on(element,"click",(event)=>{ const target=event.target;const tab=target.closest(this.tabSelector);if(!tab || !element.contains(tab))return;event.preventDefault();this.show(tab);});this.on(element,"keydown",(event)=>{ if(!this.keyboard)return;const keyEvent=event;const keys=this.orientation==="vertical"?["ArrowUp","ArrowDown"]:["ArrowLeft","ArrowRight"];if(!keys.includes(keyEvent.key))return;const tabs=Array.from(element.querySelectorAll(this.tabSelector));const index=tabs.indexOf(document.activeElement);if(index<0)return;event.preventDefault();const isNext=keyEvent.key==="ArrowRight" || keyEvent.key==="ArrowDown";const fallback=this.loop?(isNext?tabs[0]:tabs[tabs.length-1]):tabs[index];const next=isNext?tabs[index+1]|| fallback:tabs[index-1]|| fallback;if(next){ next.focus();this.show(next);} });this.activateInitial();} updateOptions(options={}){ const shouldActivate=(options.active !==undefined || options.activeIndex !==undefined)&& this.cleanups.length>0;super.updateOptions(options);this.tabSelector=getOption(this.options,this.element,"tabs","tabSelector","[data-tabs]");this.panelSelector=getOption(this.options,this.element,"tabs","panelSelector",null);this.active=getOption(this.options,this.element,"tabs","active",null);this.activeIndex=getNumberOption(this.options,this.element,"tabs","activeIndex",-1);this.keyboard=getBooleanOption(this.options,this.element,"tabs","keyboard",true);this.loop=getBooleanOption(this.options,this.element,"tabs","loop",true);this.orientation=getOption(this.options,this.element,"tabs","orientation",this.element.getAttribute("aria-orientation")|| "horizontal");this.element.setAttribute("role",this.element.getAttribute("role")|| "tablist");this.element.setAttribute("aria-orientation",this.orientation);if(shouldActivate)this.activateInitial();return this;} activateInitial(){ const tabs=Array.from(this.element.querySelectorAll(this.tabSelector));if(!tabs.length)return;let initial=null;if(this.active instanceof HTMLElement){ initial=this.active;} else if(typeof this.active==="string"){ initial=this.element.querySelector(this.active)|| document.querySelector(this.active);} if(!initial && this.activeIndex>=0){ initial=tabs[this.activeIndex]|| null;} if(!initial){ initial=tabs.find((tab)=>tab.getAttribute("aria-selected")==="true")|| tabs[0];} if(initial)this.show(initial);} show(tab){ const selector=tab.getAttribute("data-tabs");const panel=selector?document.querySelector(selector):null;if(!panel)return this;this.element.querySelectorAll(this.tabSelector).forEach((item)=>{ const selected=item===tab;item.setAttribute("role",item.getAttribute("role")|| "tab");item.setAttribute("aria-selected",String(selected));item.tabIndex=selected?0:-1;const targetSelector=item.getAttribute("data-tabs");const target=targetSelector?document.querySelector(targetSelector):null;if(target)target.hidden=!selected;});if(this.panelSelector){ document.querySelectorAll(this.panelSelector).forEach((item)=>{ if(item !==panel)item.hidden=true;});} panel.setAttribute("role",panel.getAttribute("role")|| "tabpanel");emit(this.element,"tabs:show",{ tab,panel,instance:this });return this;} } class Toast extends Component { static componentName="toast";timeout=null;delay;autohide;constructor(element,options={}){ super(element,options);this.updateOptions(options);element.setAttribute("role",element.getAttribute("role")|| "status");element.setAttribute("aria-live",element.getAttribute("aria-live")|| "polite");} updateOptions(options={}){ super.updateOptions(options);this.delay=getNumberOption(this.options,this.element,"toast","delay",5000);this.autohide=getBooleanOption(this.options,this.element,"toast","autohide",true);return this;} show(){ this.element.classList.add("toast-show");if(this.timeout)clearTimeout(this.timeout);if(this.autohide && this.delay>0)this.timeout=setTimeout(()=>this.hide(),this.delay);emit(this.element,"toast:show",{ instance:this });return this;} hide(){ this.element.classList.remove("toast-show");if(this.timeout)clearTimeout(this.timeout);emit(this.element,"toast:hide",{ instance:this });return this;} destroy(){ if(this.timeout)clearTimeout(this.timeout);super.destroy();} } class Carousel extends Component { static componentName="carousel";timeout=null;items;index;interval;autoplay;pauseOnHover;keyboard;loop;constructor(element,options={}){ super(element,options);this.items=Array.from(element.querySelectorAll("[data-carousel-item]"));this.index=this.resolveInitialIndex();this.updateOptions(options);this.show(this.index);this.on(element,"click",(event)=>{ const target=event.target;const action=target.closest("[data-carousel]");if(!action)return;const value=action.getAttribute("data-carousel");if(value==="next")this.next();if(value==="prev")this.prev();if(value !=="next" && value !=="prev" && value !=="")this.show(Number(value));});this.on(element,"keydown",(event)=>{ const keyEvent=event;if(!this.keyboard || !["ArrowLeft","ArrowRight"].includes(keyEvent.key))return;event.preventDefault();if(keyEvent.key==="ArrowRight")this.next();if(keyEvent.key==="ArrowLeft")this.prev();});if(this.pauseOnHover){ this.on(element,"mouseenter",()=>this.pause());this.on(element,"mouseleave",()=>this.play());} if(this.autoplay)this.play();} updateOptions(options={}){ super.updateOptions(options);this.interval=getNumberOption(this.options,this.element,"carousel","interval",5000);this.autoplay=getBooleanOption(this.options,this.element,"carousel","autoplay",false);this.pauseOnHover=getBooleanOption(this.options,this.element,"carousel","pauseOnHover",true);this.keyboard=getBooleanOption(this.options,this.element,"carousel","keyboard",true);this.loop=getBooleanOption(this.options,this.element,"carousel","loop",true);const activeIndex=getNumberOption(this.options,this.element,"carousel","activeIndex",-1);if(activeIndex>=0)this.show(activeIndex);if(this.autoplay)this.play();if(!this.autoplay)this.pause();return this;} resolveInitialIndex(){ const configured=getNumberOption(this.options,this.element,"carousel","activeIndex",-1);if(configured>=0)return configured;return Math.max(0,this.items.findIndex((item)=>!item.hidden));} show(index){ if(!this.items.length)return this;if(!this.loop &&(index<0 || index>=this.items.length))return this;this.index=(index+this.items.length)% this.items.length;this.items.forEach((item,itemIndex)=>{ item.hidden=itemIndex !==this.index;});emit(this.element,"carousel:show",{ index:this.index,instance:this });return this;} next(){ return this.show(this.index+1);} prev(){ return this.show(this.index-1);} play(){ if(this.timeout)clearInterval(this.timeout);if(this.autoplay && this.interval>0){ this.timeout=setInterval(()=>this.next(),this.interval);} return this;} pause(){ if(this.timeout)clearInterval(this.timeout);this.timeout=null;return this;} destroy(){ this.pause();super.destroy();} } class Offcanvas extends Modal { static componentName="offcanvas";show(){ if(this.isOpen)return this;this.previousFocus=document.activeElement;this.isOpen=true;this.element.classList.add("offcanvas-open");this.element.setAttribute("aria-hidden","false");if(this.scrollLock)document.documentElement.style.overflow="hidden";if(this.focus)this.focusFirst();emit(this.element,"offcanvas:show",{ instance:this });return this;} hide(){ if(!this.isOpen)return this;this.isOpen=false;this.element.classList.remove("offcanvas-open");this.element.setAttribute("aria-hidden","true");if(this.scrollLock)document.documentElement.style.overflow="";if(this.previousFocus && typeof this.previousFocus.focus==="function")this.previousFocus.focus();emit(this.element,"offcanvas:hide",{ instance:this });return this;} } function readTriggerOptions(trigger,component,names){ return names.reduce((options,name)=>{ const value=getData(trigger,component,name);if(value !==null)options[name]=value;return options;},{});} function dismissTarget(target){ if(!target)return;if(target.classList.contains("modal")){ getInstance(target,Modal).hide();} else if(target.classList.contains("offcanvas")){ getInstance(target,Offcanvas).hide();} else if(target.classList.contains("toast")){ getInstance(target,Toast).hide();} else if(target.classList.contains("dropdown")|| target.matches("[data-dropdown]")){ getInstance(target,Dropdown).hide();} else { target.remove();} } function resolveDismissTargets(trigger){ const selector=trigger.getAttribute("data-dismiss");if(selector){ try { return Array.from(document.querySelectorAll(selector));} catch { return[];} } const localTarget=trigger.closest(".alert,.toast,.modal,.offcanvas,.dropdown,.popover,.tooltip");return localTarget?[localTarget]:[];} function bindDataApi(){ document.querySelectorAll("[data-dismiss]").forEach((trigger)=>{ const customTrigger=trigger;if(customTrigger.__aksaraDismissTrigger)return;customTrigger.__aksaraDismissTrigger=true;trigger.addEventListener("click",(event)=>{ event.preventDefault();resolveDismissTargets(trigger).forEach((target)=>dismissTarget(target));});});document.querySelectorAll("[data-modal-close]").forEach((trigger)=>{ const customTrigger=trigger;if(customTrigger.__aksaraModalCloseTrigger)return;customTrigger.__aksaraModalCloseTrigger=true;trigger.addEventListener("click",(event)=>{ event.preventDefault();const targetSelector=trigger.getAttribute("data-modal-close");const modal=targetSelector?document.querySelector(targetSelector):trigger.closest(".modal");if(modal)getInstance(modal,Modal).hide();});});document.querySelectorAll("[data-modal]").forEach((trigger)=>{ const customTrigger=trigger;if(customTrigger.__aksaraModalTrigger)return;customTrigger.__aksaraModalTrigger=true;trigger.addEventListener("click",(event)=>{ event.preventDefault();const targetSelector=trigger.getAttribute("data-modal");if(targetSelector){ const target=document.querySelector(targetSelector);if(target){ const options=readTriggerOptions(trigger,"modal",["backdrop","keyboard","focus","scrollLock","draggable"]);getInstance(target,Modal,options).show();} } });});document.querySelectorAll("[data-offcanvas-close]").forEach((trigger)=>{ const customTrigger=trigger;if(customTrigger.__aksaraOffcanvasCloseTrigger)return;customTrigger.__aksaraOffcanvasCloseTrigger=true;trigger.addEventListener("click",(event)=>{ event.preventDefault();const targetSelector=trigger.getAttribute("data-offcanvas-close");const panel=targetSelector?document.querySelector(targetSelector):trigger.closest(".offcanvas");if(panel)getInstance(panel,Offcanvas).hide();});});document.querySelectorAll("[data-offcanvas]").forEach((trigger)=>{ const customTrigger=trigger;if(customTrigger.__aksaraOffcanvasTrigger)return;customTrigger.__aksaraOffcanvasTrigger=true;trigger.addEventListener("click",(event)=>{ event.preventDefault();const targetSelector=trigger.getAttribute("data-offcanvas");if(targetSelector){ const target=document.querySelector(targetSelector);if(target){ const options=readTriggerOptions(trigger,"offcanvas",["backdrop","keyboard","focus","scrollLock"]);getInstance(target,Offcanvas,options).show();} } });});document.querySelectorAll("[data-toast]").forEach((trigger)=>{ const customTrigger=trigger;if(customTrigger.__aksaraToastTrigger)return;customTrigger.__aksaraToastTrigger=true;trigger.addEventListener("click",(event)=>{ event.preventDefault();const targetSelector=trigger.getAttribute("data-toast");if(targetSelector){ const target=document.querySelector(targetSelector);if(target){ const options=readTriggerOptions(trigger,"toast",["delay","autohide"]);getInstance(target,Toast,options).show();} } });});} const injectedArbitraryRules=new Set();let arbitrarySheet=null;let arbitraryRuleIndex=0;function getArbitrarySheet(){ if(typeof document==="undefined")return null;if(!arbitrarySheet){ if("adoptedStyleSheets" in document && typeof CSSStyleSheet !=="undefined"){ arbitrarySheet=new CSSStyleSheet();document.adoptedStyleSheets=[...document.adoptedStyleSheets,arbitrarySheet];} } return arbitrarySheet;} function escapeArbitraryClass(className){ return Array.from(className).map((char,index)=>{ if(/^[a-zA-Z_-]$/.test(char))return char;if(/^[0-9]$/.test(char)){ return index===0?`\\${char.charCodeAt(0).toString(16).padStart(6,"0")}`:char;} return `\\${char}`;}).join("");} const runtimeArbitraryPropertyMap={ m:(v)=>`margin:${v}`,mt:(v)=>`margin-block-start:${v}`,mb:(v)=>`margin-block-end:${v}`,ms:(v)=>`margin-inline-start:${v}`,me:(v)=>`margin-inline-end:${v}`,mx:(v)=>`margin-inline:${v}`,my:(v)=>`margin-block:${v}`,p:(v)=>`padding:${v}`,pt:(v)=>`padding-block-start:${v}`,pb:(v)=>`padding-block-end:${v}`,ps:(v)=>`padding-inline-start:${v}`,pe:(v)=>`padding-inline-end:${v}`,px:(v)=>`padding-inline:${v}`,py:(v)=>`padding-block:${v}`,gap:(v)=>`gap:${v}`,"row-gap":(v)=>`row-gap:${v}`,"col-gap":(v)=>`column-gap:${v}`,g:(v)=>`--aksara-gutter-x:${v};--aksara-gutter-y:${v}`,gx:(v)=>`--aksara-gutter-x:${v}`,gy:(v)=>`--aksara-gutter-y:${v}`,w:(v)=>`width:${v}`,h:(v)=>`height:${v}`,"min-w":(v)=>`min-width:${v}`,"max-w":(v)=>`max-width:${v}`,"min-h":(v)=>`min-height:${v}`,"max-h":(v)=>`max-height:${v}`,top:(v)=>`inset-block-start:${v}`,bottom:(v)=>`inset-block-end:${v}`,start:(v)=>`inset-inline-start:${v}`,end:(v)=>`inset-inline-end:${v}`,inset:(v)=>`inset:${v}`,"inset-x":(v)=>`inset-inline:${v}`,"inset-y":(v)=>`inset-block:${v}`,"translate-x":(v)=>`transform:translateX(${v})`,"translate-y":(v)=>`transform:translateY(${v})`,rotate:(v)=>`transform:rotate(${v})`,scale:(v)=>`transform:scale(${v})`,rounded:(v)=>`border-radius:${v}`,border:(v)=>`border-width:${v}`,opacity:(v)=>`opacity:${v}`,z:(v)=>`z-index:${v}`,leading:(v)=>`line-height:${v}`,tracking:(v)=>`letter-spacing:${v}`,text:(v)=>(/^(#[0-9a-fA-F]+|rgb|hsl)/.test(v)?`color:${v}`:`font-size:${v}`),bg:(v)=>`background-color:${v}`,overscroll:(v)=>`overscroll-behavior:${v}`,"overscroll-x":(v)=>`overscroll-behavior-x:${v}`,"overscroll-y":(v)=>`overscroll-behavior-y:${v}` };const runtimeBreakpoints={ sm:"36rem",md:"48rem",lg:"62rem",xl:"75rem","2xl":"87.5rem","3xl":"100rem" };const runtimeStateSelectors={ hover:":hover",focus:":focus",active:":active",disabled:":disabled",checked:":checked",selected:'[aria-selected="true"]',visited:":visited",first:":first-child",last:":last-child",odd:":nth-child(odd)",even:":nth-child(even)" };function injectArbitraryClass(className){ if(injectedArbitraryRules.has(className))return;injectedArbitraryRules.add(className);const parts=className.split(":");const utility=parts.pop();if(!utility)return;const match=utility.match(/^(-)?([a-zA-Z0-9_-]+)-\[(.+)\]$/);if(!match)return;const isNegative=Boolean(match[1]);const prop=match[2];let val=match[3];const resolver=runtimeArbitraryPropertyMap[prop];if(!resolver)return;if(isNegative && !val.startsWith("-")){ val=`-${val}`;} const declarations=resolver(val);const escaped=escapeArbitraryClass(className);let selector=`.${escaped}`;let stateSelector="";let themeVariant="";let breakpointVariant="";for(const v of parts){ if(v==="dark" || v==="light")themeVariant=v;else if(runtimeBreakpoints[v])breakpointVariant=v;else if(runtimeStateSelectors[v])stateSelector+=runtimeStateSelectors[v];} selector+=stateSelector;let rule=`${selector}{${declarations}}`;if(themeVariant){ rule=themeVariant==="dark"?`[data-theme="dark"]${selector},.dark ${selector}{${declarations}}`:`[data-theme="light"]${selector},.light ${selector}{${declarations}}`;} if(breakpointVariant){ rule=`@media(min-width:${runtimeBreakpoints[breakpointVariant]}){${rule}}`;} const sheet=getArbitrarySheet();if(sheet){ try { sheet.insertRule(rule,arbitraryRuleIndex++);} catch { } } } function processElementClasses(el){ const classAttr=el.getAttribute("class");if(!classAttr || !classAttr.includes("-["))return;const tokens=classAttr.split(/\s+/);for(const token of tokens){ if(token.includes("-[")&& token.endsWith("]")){ injectArbitraryClass(token);} } } function scanArbitraryDom(root=document){ if(typeof document==="undefined")return;if(root instanceof Element){ processElementClasses(root);} root.querySelectorAll('[class*="-["]').forEach(processElementClasses);} let mutationObserverStarted=false;function setupArbitraryObserver(){ if(mutationObserverStarted || typeof MutationObserver==="undefined" || typeof document==="undefined")return;mutationObserverStarted=true;const observer=new MutationObserver((mutations)=>{ for(const m of mutations){ if(m.type==="attributes" && m.target instanceof Element){ processElementClasses(m.target);} else if(m.type==="childList"){ m.addedNodes.forEach((node)=>{ if(node instanceof Element){ scanArbitraryDom(node);} });} } });observer.observe(document.documentElement,{ subtree:true,childList:true,attributes:true,attributeFilter:["class"]});} const Aksara={ Modal,Tooltip,Popover,Accordion,Dropdown,Tabs,Toast,Carousel,Offcanvas,modal:(target,options)=>{ const args=resolveArgs(target,options,"[data-modal],.modal");return createAll(args.target,Modal,args.options);},tooltip:(target,options)=>{ const args=resolveArgs(target,options,"[data-tooltip]");return createAll(args.target,Tooltip,args.options);},popover:(target,options)=>{ const args=resolveArgs(target,options,"[data-popover]");return createAll(args.target,Popover,args.options);},accordion:(target,options)=>{ const args=resolveArgs(target,options,".accordion");return createAll(args.target,Accordion,args.options);},dropdown:(target,options)=>{ const args=resolveArgs(target,options,"[data-dropdown],.dropdown");return createAll(args.target,Dropdown,args.options);},tabs:(target,options)=>{ const args=resolveArgs(target,options,".tabs");return createAll(args.target,Tabs,args.options);},toast:(target,options)=>{ const args=resolveArgs(target,options,".toast");return createAll(args.target,Toast,args.options);},carousel:(target,options)=>{ const args=resolveArgs(target,options,".carousel");return createAll(args.target,Carousel,args.options);},offcanvas:(target,options)=>{ const args=resolveArgs(target,options,".offcanvas");return createAll(args.target,Offcanvas,args.options);},init(root=document){ scanArbitraryDom(root);setupArbitraryObserver();createAll(root.querySelectorAll("[data-tooltip]"),Tooltip);createAll(root.querySelectorAll("[data-popover]"),Popover);const dropdowns=new Set();root.querySelectorAll(".dropdown").forEach((el)=>dropdowns.add(el));root.querySelectorAll("[data-dropdown]").forEach((el)=>{ if(!el.closest(".dropdown")){ dropdowns.add(el);} });createAll(Array.from(dropdowns),Dropdown);createAll(root.querySelectorAll(".accordion"),Accordion);createAll(root.querySelectorAll(".tabs"),Tabs);createAll(root.querySelectorAll(".toast"),Toast);createAll(root.querySelectorAll(".carousel"),Carousel);createAll(root.querySelectorAll(".modal"),Modal);createAll(root.querySelectorAll(".offcanvas"),Offcanvas);bindDataApi();emit(document.documentElement,"init",{ root });return this;},destroy(){ Array.from(instances).forEach((instance)=>instance.destroy());registry.clear();emit(document.documentElement,"destroy");return this;} };if(typeof document !=="undefined"){ document.addEventListener("DOMContentLoaded",()=>Aksara.init());} window.Aksara=Aksara;})();
@@ -0,0 +1,10 @@
1
+ export interface ButtonGroupProps {
2
+ children?: string;
3
+ size?: "sm" | "lg";
4
+ vertical?: boolean;
5
+ ariaLabel?: string;
6
+ className?: string;
7
+ attributes?: Record<string, unknown>;
8
+ }
9
+ export declare function ButtonGroup(props?: ButtonGroupProps): string;
10
+ export declare const buttonGroup: typeof ButtonGroup;
@@ -0,0 +1,12 @@
1
+ import { classNames, toAttributes } from "../utils";
2
+ export function ButtonGroup(props = {}) {
3
+ const { children = "", size, vertical = false, ariaLabel = "Button group", className = "", attributes } = props;
4
+ const classes = classNames(vertical ? "btn-group-vertical" : "btn-group", size === "sm" && "btn-group-sm", size === "lg" && "btn-group-lg", className);
5
+ const baseAttrs = toAttributes({
6
+ role: "group",
7
+ "aria-label": ariaLabel,
8
+ ...attributes
9
+ });
10
+ return `<div class="${classes}"${baseAttrs}>${children}</div>`.trim();
11
+ }
12
+ export const buttonGroup = ButtonGroup;
@@ -0,0 +1,18 @@
1
+ export type ButtonVariant = "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "dark" | "light" | "link";
2
+ export interface ButtonProps {
3
+ label?: string;
4
+ children?: string;
5
+ type?: "button" | "submit" | "reset";
6
+ variant?: ButtonVariant;
7
+ outline?: boolean;
8
+ soft?: boolean;
9
+ ghost?: boolean;
10
+ size?: "sm" | "lg";
11
+ pill?: boolean;
12
+ disabled?: boolean;
13
+ href?: string;
14
+ className?: string;
15
+ attributes?: Record<string, unknown>;
16
+ }
17
+ export declare function Button(props?: ButtonProps): string;
18
+ export declare const button: typeof Button;
@@ -0,0 +1,28 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Button(props = {}) {
3
+ const { label, children, type = "button", variant = "primary", outline = false, soft = false, ghost = false, size, pill = false, disabled = false, href, className = "", attributes } = props;
4
+ let variantClass = `btn-${variant}`;
5
+ if (ghost) {
6
+ variantClass = "btn-ghost";
7
+ }
8
+ else if (outline) {
9
+ variantClass = `btn-outline-${variant}`;
10
+ }
11
+ else if (soft) {
12
+ variantClass = `btn-soft-${variant}`;
13
+ }
14
+ const classes = classNames("btn", variantClass, size === "sm" && "btn-sm", size === "lg" && "btn-lg", pill && "rounded-pill", disabled && "disabled", className);
15
+ const isLink = Boolean(href);
16
+ const Tag = isLink ? "a" : "button";
17
+ const baseAttrs = toAttributes({
18
+ href,
19
+ type: isLink ? undefined : type,
20
+ disabled: !isLink && disabled ? true : undefined,
21
+ "aria-disabled": isLink && disabled ? "true" : undefined,
22
+ tabindex: isLink && disabled ? "-1" : undefined,
23
+ ...attributes
24
+ });
25
+ const content = children !== undefined ? children : label !== undefined ? escapeHtml(label) : "";
26
+ return `<${Tag} class="${classes}"${baseAttrs}>${content}</${Tag}>`.trim();
27
+ }
28
+ export const button = Button;
@@ -0,0 +1,9 @@
1
+ export interface CloseButtonProps {
2
+ white?: boolean;
3
+ disabled?: boolean;
4
+ ariaLabel?: string;
5
+ className?: string;
6
+ attributes?: Record<string, unknown>;
7
+ }
8
+ export declare function CloseButton(props?: CloseButtonProps): string;
9
+ export declare const closeButton: typeof CloseButton;
@@ -0,0 +1,13 @@
1
+ import { classNames, toAttributes } from "../utils";
2
+ export function CloseButton(props = {}) {
3
+ const { white = false, disabled = false, ariaLabel = "Close", className = "", attributes } = props;
4
+ const classes = classNames("btn-close", white && "btn-close-white", className);
5
+ const baseAttrs = toAttributes({
6
+ type: "button",
7
+ "aria-label": ariaLabel,
8
+ disabled: disabled ? true : undefined,
9
+ ...attributes
10
+ });
11
+ return `<button class="${classes}"${baseAttrs}></button>`.trim();
12
+ }
13
+ export const closeButton = CloseButton;
@@ -0,0 +1,3 @@
1
+ export * from "./button";
2
+ export * from "./button-group";
3
+ export * from "./close-button";
@@ -0,0 +1,3 @@
1
+ export * from "./button";
2
+ export * from "./button-group";
3
+ export * from "./close-button";
@@ -0,0 +1,17 @@
1
+ export interface AccordionProps {
2
+ children?: string;
3
+ flush?: boolean;
4
+ className?: string;
5
+ attributes?: Record<string, unknown>;
6
+ }
7
+ export declare function Accordion(props?: AccordionProps): string;
8
+ export declare const accordion: typeof Accordion;
9
+ export interface AccordionItemProps {
10
+ id: string;
11
+ title: string;
12
+ body: string;
13
+ expanded?: boolean;
14
+ className?: string;
15
+ }
16
+ export declare function AccordionItem(props: AccordionItemProps): string;
17
+ export declare const accordionItem: typeof AccordionItem;
@@ -0,0 +1,37 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Accordion(props = {}) {
3
+ const { children = "", flush = false, className = "", attributes } = props;
4
+ const classes = classNames("accordion", flush && "accordion-flush", className);
5
+ const baseAttrs = toAttributes(attributes);
6
+ return `<div class="${classes}"${baseAttrs}>${children}</div>`.trim();
7
+ }
8
+ export const accordion = Accordion;
9
+ export function AccordionItem(props) {
10
+ const { id, title, body, expanded = false, className = "" } = props;
11
+ const buttonClasses = classNames("accordion-button", expanded && "accordion-button-active", !expanded && "collapsed");
12
+ const panelClasses = classNames("accordion-panel", expanded && "accordion-panel-open");
13
+ const targetSelector = id.startsWith("#") ? id : `#${id}`;
14
+ const rawId = id.replace(/^#/, "");
15
+ return `
16
+ <div class="${classNames("accordion-item", className)}">
17
+ <h2 class="accordion-header m-0">
18
+ <button
19
+ class="${buttonClasses}"
20
+ type="button"
21
+ data-accordion="${escapeHtml(targetSelector)}"
22
+ aria-expanded="${expanded ? "true" : "false"}"
23
+ aria-controls="${escapeHtml(rawId)}"
24
+ >
25
+ <span>${escapeHtml(title)}</span>
26
+ <span class="accordion-icon" aria-hidden="true"></span>
27
+ </button>
28
+ </h2>
29
+ <div id="${escapeHtml(rawId)}" class="${panelClasses}" role="region">
30
+ <div class="accordion-body">
31
+ ${body}
32
+ </div>
33
+ </div>
34
+ </div>
35
+ `.trim();
36
+ }
37
+ export const accordionItem = AccordionItem;
@@ -0,0 +1,26 @@
1
+ export type AvatarSize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
2
+ export type AvatarShape = "circle" | "rounded" | "square";
3
+ export type AvatarStatus = "online" | "offline" | "busy" | "away";
4
+ export interface AvatarProps {
5
+ src?: string;
6
+ alt?: string;
7
+ initials?: string;
8
+ size?: AvatarSize;
9
+ shape?: AvatarShape;
10
+ status?: AvatarStatus | boolean;
11
+ variant?: "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "dark" | "light";
12
+ className?: string;
13
+ attributes?: Record<string, unknown>;
14
+ }
15
+ export declare function Avatar(props?: AvatarProps): string;
16
+ export declare const avatar: typeof Avatar;
17
+ export interface AvatarGroupProps {
18
+ children?: string;
19
+ avatars?: AvatarProps[];
20
+ max?: number;
21
+ size?: AvatarSize;
22
+ className?: string;
23
+ attributes?: Record<string, unknown>;
24
+ }
25
+ export declare function AvatarGroup(props?: AvatarGroupProps): string;
26
+ export declare const avatarGroup: typeof AvatarGroup;
@@ -0,0 +1,64 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Avatar(props = {}) {
3
+ const { src, alt = "Avatar", initials, size = "md", shape = "circle", status, variant = "primary", className = "", attributes } = props;
4
+ const shapeClass = shape === "circle" ? "rounded-full" : shape === "rounded" ? "rounded-8" : "rounded-none";
5
+ const sizeClass = `avatar-${size}`;
6
+ const classes = classNames("avatar", sizeClass, shapeClass, !src && !className.includes("bg-") && `avatar-${variant} bg-${variant}/15 text-${variant}`, "position-relative inline-flex items-center justify-center font-bold select-none shrink-0 overflow-hidden", className);
7
+ const baseAttrs = toAttributes(attributes);
8
+ let contentHtml;
9
+ if (src) {
10
+ contentHtml = `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" class="avatar-img w-full h-full object-cover block" loading="lazy" />`;
11
+ }
12
+ else if (initials) {
13
+ contentHtml = `<span class="avatar-initials uppercase text-center leading-none">${escapeHtml(initials)}</span>`;
14
+ }
15
+ else {
16
+ // Default fallback icon
17
+ contentHtml = `<span class="avatar-fallback mdi mdi-account opacity-75"></span>`;
18
+ }
19
+ let statusHtml = "";
20
+ if (status) {
21
+ let statusVariant = "bg-success";
22
+ if (status === "offline")
23
+ statusVariant = "bg-subtle border border-subtle";
24
+ else if (status === "busy")
25
+ statusVariant = "bg-danger";
26
+ else if (status === "away")
27
+ statusVariant = "bg-warning";
28
+ statusHtml = `<span class="avatar-status position-absolute rounded-full ${statusVariant} border-2 border-body" aria-hidden="true"></span>`;
29
+ }
30
+ return `
31
+ <span class="${classes}"${baseAttrs}>
32
+ ${contentHtml}
33
+ ${statusHtml}
34
+ </span>
35
+ `.trim();
36
+ }
37
+ export const avatar = Avatar;
38
+ export function AvatarGroup(props = {}) {
39
+ const { children, avatars = [], max, size = "md", className = "", attributes } = props;
40
+ const classes = classNames("avatar-group inline-flex items-center", className);
41
+ const baseAttrs = toAttributes(attributes);
42
+ if (children) {
43
+ return `<div class="${classes}"${baseAttrs}>${children}</div>`.trim();
44
+ }
45
+ const count = avatars.length;
46
+ const maxDisplay = max && max > 0 && count > max ? max : count;
47
+ const displayed = avatars.slice(0, maxDisplay);
48
+ const extraCount = count - maxDisplay;
49
+ const renderedAvatars = displayed.map((item) => Avatar({ ...item, size: item.size ?? size })).join("\n");
50
+ const extraPill = extraCount > 0
51
+ ? `
52
+ <span class="avatar avatar-${size} rounded-full bg-subtle text-subtle text-xs font-bold inline-flex items-center justify-center border-2 border-body">
53
+ +${extraCount}
54
+ </span>
55
+ `.trim()
56
+ : "";
57
+ return `
58
+ <div class="${classes}"${baseAttrs}>
59
+ ${renderedAvatars}
60
+ ${extraPill}
61
+ </div>
62
+ `.trim();
63
+ }
64
+ export const avatarGroup = AvatarGroup;
@@ -0,0 +1,39 @@
1
+ export interface CardProps {
2
+ children?: string;
3
+ className?: string;
4
+ attributes?: Record<string, unknown>;
5
+ }
6
+ export declare function Card(props?: CardProps): string;
7
+ export declare const card: typeof Card;
8
+ export interface CardHeaderProps {
9
+ children?: string;
10
+ className?: string;
11
+ }
12
+ export declare function CardHeader(props?: CardHeaderProps): string;
13
+ export declare const cardHeader: typeof CardHeader;
14
+ export interface CardBodyProps {
15
+ children?: string;
16
+ className?: string;
17
+ }
18
+ export declare function CardBody(props?: CardBodyProps): string;
19
+ export declare const cardBody: typeof CardBody;
20
+ export interface CardFooterProps {
21
+ children?: string;
22
+ className?: string;
23
+ }
24
+ export declare function CardFooter(props?: CardFooterProps): string;
25
+ export declare const cardFooter: typeof CardFooter;
26
+ export interface CardTitleProps {
27
+ title: string;
28
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
29
+ className?: string;
30
+ }
31
+ export declare function CardTitle(props: CardTitleProps): string;
32
+ export declare const cardTitle: typeof CardTitle;
33
+ export interface CardSubtitleProps {
34
+ subtitle: string;
35
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p";
36
+ className?: string;
37
+ }
38
+ export declare function CardSubtitle(props: CardSubtitleProps): string;
39
+ export declare const cardSubtitle: typeof CardSubtitle;
@@ -0,0 +1,34 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Card(props = {}) {
3
+ const { children = "", className = "", attributes } = props;
4
+ const classes = classNames("card", className);
5
+ const baseAttrs = toAttributes(attributes);
6
+ return `<div class="${classes}"${baseAttrs}>${children}</div>`.trim();
7
+ }
8
+ export const card = Card;
9
+ export function CardHeader(props = {}) {
10
+ const { children = "", className = "" } = props;
11
+ return `<div class="${classNames("card-header", className)}">${children}</div>`.trim();
12
+ }
13
+ export const cardHeader = CardHeader;
14
+ export function CardBody(props = {}) {
15
+ const { children = "", className = "" } = props;
16
+ return `<div class="${classNames("card-body", className)}">${children}</div>`.trim();
17
+ }
18
+ export const cardBody = CardBody;
19
+ export function CardFooter(props = {}) {
20
+ const { children = "", className = "" } = props;
21
+ return `<div class="${classNames("card-footer", className)}">${children}</div>`.trim();
22
+ }
23
+ export const cardFooter = CardFooter;
24
+ export function CardTitle(props) {
25
+ const { title, as: Tag = "h5", className = "" } = props;
26
+ return `<${Tag} class="${classNames("card-title", className)}">${escapeHtml(title)}</${Tag}>`.trim();
27
+ }
28
+ export const cardTitle = CardTitle;
29
+ export function CardSubtitle(props) {
30
+ const { subtitle, as: Tag = "h6", className = "" } = props;
31
+ const classes = classNames("card-subtitle mb-2 text-muted", className);
32
+ return `<${Tag} class="${classes}">${escapeHtml(subtitle)}</${Tag}>`.trim();
33
+ }
34
+ export const cardSubtitle = CardSubtitle;
@@ -0,0 +1,15 @@
1
+ export interface CarouselSlide {
2
+ content: string;
3
+ active?: boolean;
4
+ }
5
+ export interface CarouselProps {
6
+ id?: string;
7
+ slides: CarouselSlide[];
8
+ fade?: boolean;
9
+ indicators?: boolean;
10
+ controls?: boolean;
11
+ className?: string;
12
+ attributes?: Record<string, unknown>;
13
+ }
14
+ export declare function Carousel(props: CarouselProps): string;
15
+ export declare const carousel: typeof Carousel;
@@ -0,0 +1,47 @@
1
+ import { classNames, toAttributes } from "../utils";
2
+ export function Carousel(props) {
3
+ const { id, slides = [], fade = false, indicators = true, controls = true, className = "", attributes } = props;
4
+ const classes = classNames("carousel", fade && "carousel-fade", className);
5
+ const baseAttrs = toAttributes({
6
+ id,
7
+ ...attributes
8
+ });
9
+ const hasActive = slides.some((s) => s.active);
10
+ const activeIdx = hasActive ? slides.findIndex((s) => s.active) : 0;
11
+ const indicatorsHtml = indicators && slides.length > 1
12
+ ? `
13
+ <div class="carousel-indicators">
14
+ ${slides
15
+ .map((_, i) => `<button type="button" class="carousel-indicator${i === activeIdx ? " active" : ""}" data-carousel-to="${i}" aria-label="Slide ${i + 1}"></button>`)
16
+ .join("")}
17
+ </div>
18
+ `.trim()
19
+ : "";
20
+ const slidesHtml = slides
21
+ .map((slide, i) => {
22
+ const isVisible = i === activeIdx;
23
+ const hiddenAttr = isVisible ? "" : " hidden";
24
+ return `<div class="carousel-item" data-carousel-item${hiddenAttr}>${slide.content}</div>`;
25
+ })
26
+ .join("\n");
27
+ const controlsHtml = controls && slides.length > 1
28
+ ? `
29
+ <button class="carousel-control carousel-prev" type="button" data-carousel="prev" aria-label="Previous slide">
30
+ <span class="mdi mdi-chevron-left mdi-24px"></span>
31
+ </button>
32
+ <button class="carousel-control carousel-next" type="button" data-carousel="next" aria-label="Next slide">
33
+ <span class="mdi mdi-chevron-right mdi-24px"></span>
34
+ </button>
35
+ `.trim()
36
+ : "";
37
+ return `
38
+ <div class="${classes}"${baseAttrs}>
39
+ ${indicatorsHtml}
40
+ <div class="carousel-inner">
41
+ ${slidesHtml}
42
+ </div>
43
+ ${controlsHtml}
44
+ </div>
45
+ `.trim();
46
+ }
47
+ export const carousel = Carousel;
@@ -0,0 +1,7 @@
1
+ export * from "./card";
2
+ export * from "./table";
3
+ export * from "./list-group";
4
+ export * from "./accordion";
5
+ export * from "./carousel";
6
+ export * from "./media-grid";
7
+ export * from "./avatar";
@@ -0,0 +1,7 @@
1
+ export * from "./card";
2
+ export * from "./table";
3
+ export * from "./list-group";
4
+ export * from "./accordion";
5
+ export * from "./carousel";
6
+ export * from "./media-grid";
7
+ export * from "./avatar";
@@ -0,0 +1,22 @@
1
+ export interface ListGroupProps {
2
+ children?: string;
3
+ flush?: boolean;
4
+ numbered?: boolean;
5
+ horizontal?: boolean | "sm" | "md" | "lg" | "xl" | "xxl";
6
+ className?: string;
7
+ attributes?: Record<string, unknown>;
8
+ }
9
+ export declare function ListGroup(props?: ListGroupProps): string;
10
+ export declare const listGroup: typeof ListGroup;
11
+ export interface ListGroupItemProps {
12
+ content?: string;
13
+ active?: boolean;
14
+ disabled?: boolean;
15
+ action?: boolean;
16
+ href?: string;
17
+ variant?: "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark";
18
+ className?: string;
19
+ attributes?: Record<string, unknown>;
20
+ }
21
+ export declare function ListGroupItem(props?: ListGroupItemProps): string;
22
+ export declare const listGroupItem: typeof ListGroupItem;
@@ -0,0 +1,30 @@
1
+ import { classNames, toAttributes } from "../utils";
2
+ export function ListGroup(props = {}) {
3
+ const { children = "", flush = false, numbered = false, horizontal = false, className = "", attributes } = props;
4
+ const horizontalClass = horizontal === true
5
+ ? "list-group-horizontal"
6
+ : typeof horizontal === "string"
7
+ ? `list-group-horizontal-${horizontal}`
8
+ : null;
9
+ const classes = classNames("list-group", flush && "list-group-flush", numbered && "list-group-numbered", horizontalClass, className);
10
+ const Tag = numbered ? "ol" : "div";
11
+ const baseAttrs = toAttributes(attributes);
12
+ return `<${Tag} class="${classes}"${baseAttrs}>${children}</${Tag}>`.trim();
13
+ }
14
+ export const listGroup = ListGroup;
15
+ export function ListGroupItem(props = {}) {
16
+ const { content = "", active = false, disabled = false, action = false, href, variant, className = "", attributes } = props;
17
+ const isLink = Boolean(href);
18
+ const Tag = isLink ? "a" : action ? "button" : "div";
19
+ const classes = classNames("list-group-item", (action || isLink) && "list-group-item-action", active && "active", disabled && "disabled", variant && `list-group-item-${variant}`, className);
20
+ const baseAttrs = toAttributes({
21
+ href,
22
+ type: Tag === "button" ? "button" : undefined,
23
+ disabled: Tag === "button" && disabled ? true : undefined,
24
+ "aria-current": active ? "true" : undefined,
25
+ "aria-disabled": disabled ? "true" : undefined,
26
+ ...attributes
27
+ });
28
+ return `<${Tag} class="${classes}"${baseAttrs}>${content}</${Tag}>`.trim();
29
+ }
30
+ export const listGroupItem = ListGroupItem;
@@ -0,0 +1,19 @@
1
+ export interface MediaGridItem {
2
+ src: string;
3
+ alt?: string;
4
+ caption?: string;
5
+ dataIndex?: number;
6
+ attributes?: Record<string, unknown>;
7
+ }
8
+ export interface MediaGridProps {
9
+ items: MediaGridItem[];
10
+ maxDisplay?: number;
11
+ gap?: 1 | 2 | 3 | 4;
12
+ rounded?: boolean;
13
+ onItemClickAttribute?: string;
14
+ itemClickDataId?: string;
15
+ className?: string;
16
+ attributes?: Record<string, unknown>;
17
+ }
18
+ export declare function MediaGrid(props: MediaGridProps): string;
19
+ export declare const mediaGrid: typeof MediaGrid;