@spectrum-web-components/breadcrumbs
Version:
Web component implementation of a Spectrum design Breadcrumbs
34 lines (32 loc) • 5.24 kB
JavaScript
"use strict";var d=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var s=(o,a,e,t)=>{for(var i=t>1?void 0:t?c(a,e):a,l=o.length-1,r;l>=0;l--)(r=o[l])&&(i=(t?r(a,e,i):r(i))||i);return t&&i&&d(a,e,i),i};import{html as u,SpectrumElement as p}from"@spectrum-web-components/base";import{property as n,query as f,queryAssignedElements as h,state as b}from"@spectrum-web-components/base/src/decorators.js";import"@spectrum-web-components/breadcrumbs/sp-breadcrumb-item.js";import"@spectrum-web-components/icons-workflow/icons/sp-icon-folder-open.js";import"@spectrum-web-components/action-menu/sp-action-menu.js";import"@spectrum-web-components/menu/sp-menu-item.js";import{createRef as v,ref as g}from"@spectrum-web-components/base/src/directives.js";import E from"./breadcrumbs.css.js";import{ifDefined as I}from"@spectrum-web-components/base/src/directives.js";export class Breadcrumbs extends p{constructor(){super(...arguments);this.maxVisibleItems=4;this.label="";this.menuLabel="More items";this.compact=!1;this.items=[];this.visibleItems=0;this.firstRender=!0;this.menuRef=v()}static get styles(){return[E]}get hasMenu(){var e,t;return this.visibleItems<((t=(e=this.breadcrumbsElements)==null?void 0:e.length)!=null?t:0)}connectedCallback(){super.connectedCallback(),this.hasAttribute("role")||this.setAttribute("role","navigation"),this.resizeObserver=new ResizeObserver(()=>{if(this.firstRender){this.firstRender=!1;return}this.adjustOverflow()}),this.resizeObserver.observe(this)}disconnectedCallback(){var e;(e=this.resizeObserver)==null||e.unobserve(this),super.disconnectedCallback()}updated(e){super.updated(e),e.has("label")&&this.setAttribute("aria-label",this.label||"Breadcrumbs"),(e.has("maxVisibleItems")||e.has("compact"))&&(this.calculateBreadcrumbItemsWidth(),this.adjustOverflow()),e.has("visibleItems")&&this.items.forEach((t,i)=>{this.breadcrumbsElements[i].isLastOfType=i===this.breadcrumbsElements.length-1,this.breadcrumbsElements[i].toggleAttribute("hidden",!t.isVisible)})}calculateBreadcrumbItemsWidth(){this.items=this.breadcrumbsElements.map((e,t)=>{let i=e.offsetWidth;return e.hasAttribute("hidden")&&(e.removeAttribute("hidden"),i=e.offsetWidth,e.setAttribute("hidden","")),{label:e.innerText,href:e.href,value:e.value||t.toString(),offsetWidth:i,isVisible:!0}})}adjustOverflow(){let e=0,t=0;const i=this.list.clientWidth;this.hasMenu&&this.menuRef.value&&(e+=this.menuRef.value.offsetWidth||0),this.rootElement.length>0&&(e+=this.rootElement[0].offsetWidth);const l=0;for(let r=this.items.length-1;r>=l;r--)if(e+=this.items[r].offsetWidth,e<i&&t<Math.max(this.maxVisibleItems,1))this.items[r].isVisible=!0,t++;else{for(let m=r;m>=l;m--)this.items[m].isVisible=!1;break}t===0&&(this.items[this.items.length-1].isVisible=!0,t++),t!==this.visibleItems&&(this.visibleItems=t)}announceChange(e){const t={value:e},i=new CustomEvent("change",{bubbles:!0,composed:!0,detail:t});this.dispatchEvent(i)}handleSelect(e){e.stopPropagation(),this.announceChange(e.detail.value)}handleMenuChange(e){e.stopPropagation(),this.announceChange(e.target.value)}renderMenu(){return u`
<sp-breadcrumb-item role="listitem" class="is-menu">
<sp-action-menu
${g(this.menuRef)}
quiet
label=${this.menuLabel}
selects="single"
value=${this.items[this.items.length-1].value}
=${this.handleMenuChange}
slot="menu"
>
<slot slot="icon" name="icon">
<sp-icon-folder-open class="icon"></sp-icon-folder-open>
</slot>
${this.items.map(e=>u`
<sp-menu-item
href=${I(e.href)}
value=${e.value}
>
${e.label}
</sp-menu-item>
`)}
</sp-action-menu>
</sp-breadcrumb-item>
`}async slotChangeHandler(){if(this.breadcrumbsElements.length===0){this.items=[],this.visibleItems=0;return}await Promise.all(this.breadcrumbsElements.map(e=>e.updateComplete)),this.calculateBreadcrumbItemsWidth(),this.adjustOverflow()}render(){return u`
<ul -select=${this.handleSelect} id="list">
<slot name="root"></slot>
${this.hasMenu?this.renderMenu():""}
<slot =${this.slotChangeHandler}></slot>
</ul>
`}}s([n({type:Number,attribute:"max-visible-items"})],Breadcrumbs.prototype,"maxVisibleItems",2),s([n({type:String})],Breadcrumbs.prototype,"label",2),s([n({type:String,attribute:"menu-label"})],Breadcrumbs.prototype,"menuLabel",2),s([n({type:Boolean})],Breadcrumbs.prototype,"compact",2),s([h({selector:"sp-breadcrumb-item"})],Breadcrumbs.prototype,"breadcrumbsElements",2),s([h({slot:"root",selector:"sp-breadcrumb-item"})],Breadcrumbs.prototype,"rootElement",2),s([f("#list")],Breadcrumbs.prototype,"list",2),s([b()],Breadcrumbs.prototype,"items",2),s([b()],Breadcrumbs.prototype,"visibleItems",2);
//# sourceMappingURL=Breadcrumbs.js.map