UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

3 lines (2 loc) 11.6 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0/LICENSE.txt */ import{a as W,b as F,c as z}from"./I6VZ7VH7.js";import{a as y}from"./HXIMHC6U.js";import{a as g}from"./WAA77FNZ.js";import{a as O}from"./SQ6RHDDF.js";import"./QUTTHRH3.js";import"./MNIRD7Q7.js";import{e as k,l as B,n as p,y as E}from"./ZQBZ5QPB.js";import"./CIYXQ5G6.js";import{D as w,E as C,F as b,K as x,Q as S,g as I,h as u,p as T}from"./G7AHLVJ5.js";var $={chevronRight:"chevron-right",chevronLeft:"chevron-left"},c={container:"container",scrollButton:"scroll-button",scrollButtonContainer:"scroll-button-container",scrollBackwardButton:"scroll-button--backward",scrollForwardButton:"scroll-button--forward",tabTitleSlotWrapper:"tab-titles-slot-wrapper",scale:h=>`scale-${h}`,position:h=>`position-${h}`},V=I`:host{position:relative;display:flex}:host([bordered]) .scroll-button--forward calcite-button{--calcite-internal-button-border-inline-end-color: var(--calcite-tab-border-color, var(--calcite-color-border-1))}:host([bordered]) .scroll-button--backward calcite-button{--calcite-internal-button-border-inline-start-color: var( --calcite-tab-border-color, var(--calcite-color-border-1) )}.scale-s{--calcite-internal-tab-nav-button-width: 24px;min-block-size:1.5rem}.scale-m{--calcite-internal-tab-nav-button-width: 32px;min-block-size:2rem}.scale-l{--calcite-internal-tab-nav-button-width: 44px;min-block-size:2.75rem}.container::-webkit-scrollbar{display:none;-ms-overflow-style:none;scrollbar-width:none}:host([layout=center]) ::slotted(calcite-tab-title){display:flex;flex-grow:1;flex-shrink:0;min-inline-size:auto;white-space:nowrap}:host([layout=center]) ::slotted(calcite-tab-title[selected]){overflow:unset}:host(:not([bordered])) .scale-l{--calcite-internal-tab-nav-gap: var(--calcite-spacing-xxl)}:host(:not([bordered])) .scale-m{--calcite-internal-tab-nav-gap: var(--calcite-spacing-xl)}:host(:not([bordered])) .scale-s{--calcite-internal-tab-nav-gap: var(--calcite-spacing-lg)}:host(:not([bordered])) .tab-titles-slot-wrapper{gap:var(--calcite-internal-tab-nav-gap)}:host([layout=center]:not([bordered])) .tab-titles-slot-wrapper{padding-inline:var(--calcite-spacing-xl)}.tab-titles-slot-wrapper{flex:1 1 0%}.container,.tab-titles-slot-wrapper{display:flex;inline-size:100%;justify-content:flex-start;overflow:hidden;white-space:nowrap}.scroll-button{position:absolute;inset-block:0px}.scroll-button calcite-button{--calcite-button-text-color: var(--calcite-tab-text-color, var(--calcite-color-text-3));--calcite-button-background-color: var(--calcite-color-transparent);--calcite-offset-invert-focus: 1;block-size:var(--calcite-container-size-content-fluid)}.scroll-button-container{display:flex;inset-block-start:var(--calcite-border-width-md);inset-block-end:var(--calcite-border-width-md);inset-inline-end:0;inline-size:calc(2 * var(--calcite-internal-tab-nav-button-width))}.scroll-button--forward{inset-inline-end:0;z-index:var(--calcite-z-index)}.scroll-button--backward{inset-inline-end:var(--calcite-internal-tab-nav-button-width);z-index:var(--calcite-z-index)}:host(:not([bordered])) .scroll-button--backward:before{background-color:var(--calcite-tab-border-color, var(--calcite-color-border-3));content:"";inline-size:var(--calcite-border-width-sm);inset-block-start:var(--calcite-border-width-md);inset-block-end:var(--calcite-border-width-md);position:absolute;inset-inline-start:0}:host([hidden]){display:none}[hidden]{display:none}`,v=class extends C{constructor(){super(),this.effectiveDir="ltr",this.lastScrollWheelAxis="x",this.resizeObserver=g("resize",()=>{this.updateScrollingState()}),this.makeFirstVisibleTabClosable=!1,this.messages=O(),this.hasOverflowingEndTabTitle=!1,this.hasOverflowingStartTabTitle=!1,this.bordered=!1,this.layout="inline",this.position="bottom",this.scale="m",this.selectedTitle=null,this.calciteInternalTabChange=T({cancelable:!1}),this.calciteInternalTabNavSlotChange=T(),this.calciteTabChange=T({cancelable:!1}),this.listen("calciteInternalTabsFocusPrevious",this.focusPreviousTabHandler),this.listen("calciteInternalTabsFocusNext",this.focusNextTabHandler),this.listen("calciteInternalTabsFocusFirst",this.focusFirstTabHandler),this.listen("calciteInternalTabsFocusLast",this.focusLastTabHandler),this.listen("calciteInternalTabsActivate",this.internalActivateTabHandler),this.listen("calciteInternalTabsClose",this.internalCloseTabHandler),this.listen("calciteInternalTabTitleRegister",this.updateTabTitles),this.listenOn(document.body,"calciteInternalTabChange",this.globalInternalTabChangeHandler)}static{this.properties={hasOverflowingEndTabTitle:[16,{},{state:!0}],hasOverflowingStartTabTitle:[16,{},{state:!0}],selectedTabId:[16,{},{state:!0}],bordered:[7,{},{reflect:!0,type:Boolean}],layout:[3,{},{reflect:!0}],messageOverrides:[0,{},{attribute:!1}],position:1,scale:1,selectedTitle:[0,{},{attribute:!1}],storageId:[3,{},{reflect:!0}],syncId:[3,{},{reflect:!0}]}}static{this.styles=V}connectedCallback(){super.connectedCallback(),this.parentTabsEl=this.el.closest("calcite-tabs"),this.resizeObserver?.observe(this.el)}async load(){let t=`calcite-tab-nav-${this.storageId}`;if(localStorage&&this.storageId&&localStorage.getItem(t)){let e=JSON.parse(localStorage.getItem(t));this.selectedTabId=e}}willUpdate(t){t.has("selectedTitle")&&(this.hasUpdated||this.selectedTitle!==null)&&this.calciteInternalTabChange.emit({tab:this.selectedTabId}),t.has("selectedTabId")&&this.selectedTabIdChanged();let{parentTabsEl:e}=this;this.layout=e?.layout,this.bordered=e?.bordered,this.effectiveDir=k(this.el)}loaded(){this.scrollTabTitleIntoView(this.selectedTitle,"instant"),this.tabTitles.length&&this.tabTitles.every(t=>!t.selected)&&!this.selectedTabId&&this.tabTitles[0].getTabIdentifier().then(t=>{this.calciteInternalTabChange.emit({tab:t})})}disconnectedCallback(){super.disconnectedCallback(),this.resizeObserver?.disconnect()}get enabledTabTitles(){return p(this.el,"calcite-tab-title:not([disabled])").filter(t=>!t.closed)}get scrollerButtonWidth(){let{scale:t}=this;return parseInt(t==="s"?W:t==="m"?F:z)}get tabTitles(){return p(this.el,"calcite-tab-title")}focusPreviousTabHandler(t){this.handleTabFocus(t,t.target,"previous")}focusNextTabHandler(t){this.handleTabFocus(t,t.target,"next")}focusFirstTabHandler(t){this.handleTabFocus(t,t.target,"first")}focusLastTabHandler(t){this.handleTabFocus(t,t.target,"last")}internalActivateTabHandler(t){let e=t.target,i=this.selectedTitle;this.selectedTabId=t.detail.tab?t.detail.tab:this.getIndexOfTabTitle(e),t.stopPropagation(),this.selectedTitle=e,i?.id!==e.id&&t.detail.userTriggered&&this.calciteTabChange.emit(),this.scrollTabTitleIntoView(e)}scrollTabTitleIntoView(t,e="smooth"){t&&requestAnimationFrame(()=>{let i=this.tabTitleContainerEl;if(!i)return;let l=i.getBoundingClientRect(),a=t.getBoundingClientRect(),s=i.scrollLeft;if(a.left<l.left){let o=s+(a.left-l.left);i.scrollTo({left:o,behavior:e})}else if(a.right>l.right){let o=s+(a.right-l.right);i.scrollTo({left:o,behavior:e})}})}internalCloseTabHandler(t){let e=t.target;this.handleTabTitleClose(e),t.stopPropagation()}async updateTabTitles(t){t.target.selected&&(this.selectedTabId=t.detail,this.selectedTitle=await this.getTabTitleById(this.selectedTabId))}globalInternalTabChangeHandler(t){this.syncId&&t.target!==this.el&&t.target.syncId===this.syncId&&this.selectedTabId!==t.detail.tab&&(this.selectedTabId=t.detail.tab),t.stopPropagation()}async selectedTabIdChanged(){await this.componentOnReady(),localStorage&&this.storageId&&this.selectedTabId!==void 0&&this.selectedTabId!==null&&localStorage.setItem(`calcite-tab-nav-${this.storageId}`,JSON.stringify(this.selectedTabId)),this.calciteInternalTabChange.emit({tab:this.selectedTabId})}onTabTitleWheel(t){t.preventDefault();let{deltaX:e,deltaY:i}=t,l=Math.abs(e),a=Math.abs(i),s;l===a?s=this.lastScrollWheelAxis==="x"?e:i:l>a?(s=e,this.lastScrollWheelAxis="x"):(s=i,this.lastScrollWheelAxis="y");let o=(this.effectiveDir==="rtl"?-1:1)*s;t.currentTarget.scrollBy(o,0)}onSlotChange(){this.intersectionObserver?.disconnect();let t=this.tabTitles;t.forEach(l=>{this.intersectionObserver?.observe(l)});let e=this.getVisibleTabTitlesIndices(t);e.length>1&&this.makeFirstVisibleTabClosable&&(t[e[0]].closable=!0,this.makeFirstVisibleTabClosable=!1),this.calciteInternalTabNavSlotChange.emit(t)}setTabTitleContainerEl(t){this.tabTitleContainerEl=t,this.intersectionObserver?.disconnect(),t&&(this.intersectionObserver=g("intersection",()=>this.updateScrollingState(),{root:t,threshold:[0,.5,1]}))}updateScrollingState(){let t=this.tabTitleContainerEl;if(!t)return;let e,i,l=t.scrollLeft,a=t.clientWidth,s=t.scrollWidth;this.effectiveDir==="ltr"?(e=l>0,i=l+a<s):(e=l<0,i=l!==-(s-a)),this.hasOverflowingStartTabTitle=e,this.hasOverflowingEndTabTitle=i}scrollToTabTitles(t){requestAnimationFrame(()=>{let e=this.tabTitleContainerEl;if(!e)return;let i=e.getBoundingClientRect(),l=Array.from(this.el.querySelectorAll("calcite-tab-title")),{effectiveDir:a}=this;t==="forward"&&l.reverse();let s=null;l.forEach(n=>{let r=n.getBoundingClientRect(),f=i.x+i.width,d=r.x+r.width;t==="forward"&&a==="ltr"||t==="backward"&&a==="rtl"?(r.x>f||d>f&&r.x>i.x)&&(s=n):(d<i.x||r.x<i.x&&d>i.x)&&(s=n)});let o;if(s){let n=2*this.scrollerButtonWidth,r=t==="forward"&&a==="ltr"||t==="backward"&&a==="rtl"?-n:s.offsetWidth-(e.clientWidth+n);o=s.offsetLeft+r}else{let n=e.scrollLeft,r=i.width,d=e.scrollWidth-(r+Math.abs(n));d>0&&(o=n+(a==="ltr"?1:-1)*d)}e.scrollTo({left:o,behavior:"smooth"})})}scrollToNextTabTitles(){this.scrollToTabTitles("forward")}scrollToPreviousTabTitles(){this.scrollToTabTitles("backward")}handleTabFocus(t,e,i){let l=E(this.enabledTabTitles,e,i);this.scrollTabTitleIntoView(l,"instant"),t.stopPropagation()}getIndexOfTabTitle(t,e=this.tabTitles){return e.indexOf(t)}onTabTitleScroll(){this.updateScrollingState()}async getTabTitleById(t){return Promise.all(this.tabTitles.map(e=>e.getTabIdentifier())).then(e=>this.tabTitles[e.indexOf(t)])}getVisibleTabTitlesIndices(t){return t.reduce((e,i,l)=>i.closed?e:[...e,l],[])}handleTabTitleClose(t){let{tabTitles:e}=this,i=t.selected,l=this.getVisibleTabTitlesIndices(e),a=l.length;if(a===1&&e[l[0]].closable)this.makeFirstVisibleTabClosable=!0,e[l[0]].closable=!1,this.selectedTabId=l[0],i&&e[l[0]].activateTab();else if(a>1){let s=e.findIndex(n=>n===t),o=l.find(n=>n>s);this.selectedTabId===s&&(this.selectedTabId=o||a-1,e[this.selectedTabId].activateTab())}requestAnimationFrame(()=>{B(e[this.selectedTabId])})}render(){return this.el.role="tablist",u`<div class=${b({[c.container]:!0,[c.scale(this.scale)]:!0,[c.position(this.position)]:!0,[x.rtl]:this.effectiveDir==="rtl"})}><div class=${b({[c.tabTitleSlotWrapper]:!0})} @scroll=${this.onTabTitleScroll} @wheel=${this.onTabTitleWheel} ${w(this.setTabTitleContainerEl)}><slot @slotchange=${this.onSlotChange}></slot></div><div class=${b(c.scrollButtonContainer)} .hidden=${!this.hasOverflowingEndTabTitle&&!this.hasOverflowingStartTabTitle}>${this.renderScrollButton("start")}${this.renderScrollButton("end")}</div></div>`}renderScrollButton(t){let{messages:e,scale:i,hasOverflowingEndTabTitle:l,hasOverflowingStartTabTitle:a}=this,s=t==="end";return y(t,u`<div class=${b({[c.scrollButton]:!0,[c.scrollBackwardButton]:!s,[c.scrollForwardButton]:s})}><calcite-button .ariaLabel=${s?e.nextTabTitles:e.previousTabTitles} .disabled=${s?!l:!a} icon-flip-rtl=both .iconStart=${s?$.chevronRight:$.chevronLeft} kind=neutral @click=${s?this.scrollToNextTabTitles:this.scrollToPreviousTabTitles} .scale=${i} tabindex=-1></calcite-button></div>`)}};S("calcite-tab-nav",v);export{v as TabNav};