@nordhealth/components 4.3.0 → 4.4.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.
package/lib/TabGroup.js CHANGED
@@ -1,2 +1,2 @@
1
- import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as e,LitElement as r,html as a,isServer as s}from"lit";import{property as o,state as i,customElement as n}from"lit/decorators.js";import{s as l}from"./Component-DSU3Qp0O.js";import{s as d}from"./Sticky-DqnqENYN.js";import b from"./Tab.js";import{D as c}from"./DirectionController-ChvNGESZ.js";import"./observe-D0n0zOfU.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";const p=e`:host{--_n-tab-group-padding:var(--n-tab-group-padding, 0);--_n-tab-group-list-background:var(--n-color-surface);--_n-tab-group-list-border:inset 0 -1px 0 0 var(--n-color-border);--_n-tab-group-list-shadow:var(--n-box-shadow-header);--_n-sticky-size:46px;border-radius:var(--n-border-radius) var(--n-border-radius) 0 0}.n-tab-group-list{list-style:none;display:flex;overflow-x:auto;overflow-y:hidden;overscroll-behavior:none;box-shadow:var(--_n-tab-group-list-border);border-radius:var(--n-border-radius) var(--n-border-radius) 0 0;gap:var(--n-space-s);background-color:var(--_n-tab-group-list-background);background-image:radial-gradient(ellipse farthest-side at 0 50%,var(--n-color-border-strong) 0,var(--_n-tab-group-list-background)),radial-gradient(ellipse farthest-side at 100% 50%,var(--n-color-border-strong) 0,var(--_n-tab-group-list-background));background-repeat:no-repeat;background-position:0 var(--n-space-xs),100% var(--n-space-xs);background-size:var(--n-space-s) var(--n-space-xl),var(--n-space-s) var(--n-space-xl)}.n-tab-group-list::after,.n-tab-group-list::before{content:"";box-sizing:content-box;align-self:stretch;min-inline-size:var(--n-space-l);margin-block-end:1px}.n-tab-group-list::before{margin-inline-end:calc(-1 * (var(--n-space-l) + var(--n-space-s)));padding-inline-start:var(--_n-tab-group-padding)}.n-tab-group-list::after{margin-inline-start:calc(-1 * (var(--n-space-l) + var(--n-space-s)));padding-inline-end:var(--_n-tab-group-padding);flex:1}.n-tab-group-list::before,.n-tab-group.is-rtl .n-tab-group-list::after{box-shadow:inset var(--n-space-l) 0 var(--n-space-s) calc(-1 * var(--n-space-s)) var(--_n-tab-group-list-background)}.n-tab-group-list::after,.n-tab-group.is-rtl .n-tab-group-list::before{box-shadow:inset calc(-1 * var(--n-space-l)) 0 var(--n-space-s) calc(-1 * var(--n-space-s)) var(--_n-tab-group-list-background)}::slotted(nord-tab-panel){display:none;padding:var(--_n-tab-group-padding)}::slotted(nord-tab-panel[aria-hidden=false]){display:block}::slotted(nord-tab){z-index:var(--n-index-default)}:host([padding="m"]){--_n-tab-group-padding:var(--n-tab-group-padding, var(--n-space-m))}:host([padding="l"]){--_n-tab-group-padding:var(--n-tab-group-padding, var(--n-space-l))}:host([sticky]) .n-sticky{box-shadow:var(--_n-tab-group-list-border),var(--_n-tab-group-list-shadow);inset-inline:0;inset-block-end:auto}:host([sticky]),:host([sticky]) .n-tab-group-list{border-radius:0}`;var u;let g=1,h=u=class extends r{constructor(){super(...arguments),this.direction=new c(this),this.tabGroupId="nord-tab-group-"+g++,this.label="",this.padding="m",this.sticky=!1,this.selectedTab=this.initialSelectedTab,this.handleMutation=t=>{t.forEach((t=>{var e,r;if("selected"===t.attributeName&&null===t.oldValue){const a=t.target;null===(e=this.observer)||void 0===e||e.disconnect(),this.updateSelectedTab(a),null===(r=this.observer)||void 0===r||r.observe(this,u.observerOptions)}}))}}render(){return a`<div class="n-tab-group is-${this.direction.dir}"><div class="n-tab-group-list n-sticky" role="tablist" aria-label="${this.label}" @click="${this.handleTabChange}" @keydown="${this.handleKeydown}"><slot name="tab"></slot></div><slot></slot></div>`}connectedCallback(){super.connectedCallback(),this.updateSlots()}updateSlots(){this.setupTabs(),this.setupPanels()}firstUpdated(){var t;this.observer=new MutationObserver(this.handleMutation),null===(t=this.observer)||void 0===t||t.observe(this,u.observerOptions)}get initialSelectedTab(){return s?null:this.querySelector("nord-tab[selected]")||this.querySelector("nord-tab")}setupTabs(){this.querySelectorAll("nord-tab").forEach(((t,e)=>{t.setAttribute("id",`${this.tabGroupId}-tab-${e+1}`),t.setAttribute("aria-controls",`${this.tabGroupId}-panel-${e+1}`),t.toggleAttribute("selected",t===this.selectedTab)}))}setupPanels(){var t;const e=this.querySelectorAll("nord-tab-panel"),r=null===(t=this.selectedTab)||void 0===t?void 0:t.getAttribute("aria-controls");e.forEach(((t,e)=>{t.setAttribute("id",`${this.tabGroupId}-panel-${e+1}`),t.setAttribute("aria-labelledby",`${this.tabGroupId}-tab-${e+1}`),t.setAttribute("aria-hidden",`${t.getAttribute("id")!==r}`)}))}handleTabChange(t){this.scrollTo({top:0}),t.target instanceof b&&t.target!==this.selectedTab&&this.updateSelectedTab(t.target)}previousTab(t){const e=[...this.querySelectorAll("nord-tab")],r=e.indexOf(t);return e[r-1]}handleKeydown(t){const e=t.target,r=this.querySelector("nord-tab:first-of-type"),a=this.querySelector("nord-tab:last-of-type"),s=this.querySelector(`#${e.getAttribute("id")} ~ nord-tab`)||r,o=this.previousTab(e)||a,i=(t,e)=>{e.preventDefault(),this.scrollTo({top:0}),this.updateSelectedTab(t)};switch(t.key){case"ArrowLeft":case"ArrowUp":i(this.direction.isLTR?o:s,t);break;case"ArrowRight":case"ArrowDown":i(this.direction.isLTR?s:o,t);break;case"Home":i(r,t);break;case"End":i(a,t)}}updateSelectedTab(t){const e=this.querySelector(`#${t.getAttribute("aria-controls")}`);t!==this.selectedTab&&(this.querySelectorAll("nord-tab").forEach((e=>{e.removeAttribute("selected"),e===t&&(e.setAttribute("selected",""),e.focus(),e.scrollIntoView({block:"nearest",inline:"nearest"}),this.selectedTab=e)})),this.querySelectorAll("nord-tab-panel").forEach((t=>{t.setAttribute("aria-hidden",`${t!==e}`)})))}};h.styles=[l,d,p],h.observerOptions={attributes:!0,subtree:!0,attributeFilter:["selected"],attributeOldValue:!0},t([o({reflect:!0})],h.prototype,"label",void 0),t([o({reflect:!0})],h.prototype,"padding",void 0),t([o({reflect:!0,type:Boolean})],h.prototype,"sticky",void 0),t([i()],h.prototype,"selectedTab",void 0),h=u=t([n("nord-tab-group")],h);var v=h;export{v as default};
1
+ import{_ as t}from"./tslib.es6-CmLYFWVC.js";import{css as e,LitElement as r,html as a,isServer as s}from"lit";import{property as o,state as i,customElement as n}from"lit/decorators.js";import{s as l}from"./Component-DSU3Qp0O.js";import{s as d}from"./Sticky-DqnqENYN.js";import b from"./Tab.js";import{D as c}from"./DirectionController-ChvNGESZ.js";import"./observe-D0n0zOfU.js";import"./SlotController-Z6eG7LSZ.js";import"./EventController-BBOmvfLa.js";const p=e`:host{--_n-tab-group-padding:var(--n-tab-group-padding, 0);--_n-tab-group-list-background:var(--n-color-surface);--_n-tab-group-list-border:inset 0 -1px 0 0 var(--n-color-border);--_n-tab-group-list-shadow:var(--n-box-shadow-header);--_n-sticky-size:46px;border-radius:var(--n-border-radius) var(--n-border-radius) 0 0}.n-tab-group-list{list-style:none;display:flex;overflow-x:auto;overflow-y:hidden;overscroll-behavior:none;box-shadow:var(--_n-tab-group-list-border);border-radius:var(--n-border-radius) var(--n-border-radius) 0 0;gap:var(--n-space-s);background-color:var(--_n-tab-group-list-background);background-image:radial-gradient(ellipse farthest-side at 0 50%,var(--n-color-border-strong) 0,var(--_n-tab-group-list-background)),radial-gradient(ellipse farthest-side at 100% 50%,var(--n-color-border-strong) 0,var(--_n-tab-group-list-background));background-repeat:no-repeat;background-position:0 var(--n-space-xs),100% var(--n-space-xs);background-size:var(--n-space-s) var(--n-space-xl),var(--n-space-s) var(--n-space-xl)}.n-tab-group-list::after,.n-tab-group-list::before{content:"";box-sizing:content-box;align-self:stretch;min-inline-size:var(--n-space-l);margin-block-end:1px}.n-tab-group-list::before{margin-inline-end:calc(-1 * (var(--n-space-l) + var(--n-space-s)));padding-inline-start:var(--_n-tab-group-padding)}.n-tab-group-list::after{margin-inline-start:calc(-1 * (var(--n-space-l) + var(--n-space-s)));padding-inline-end:var(--_n-tab-group-padding);flex:1}.n-tab-group-list::before,.n-tab-group.is-rtl .n-tab-group-list::after{box-shadow:inset var(--n-space-l) 0 var(--n-space-s) calc(-1 * var(--n-space-s)) var(--_n-tab-group-list-background)}.n-tab-group-list::after,.n-tab-group.is-rtl .n-tab-group-list::before{box-shadow:inset calc(-1 * var(--n-space-l)) 0 var(--n-space-s) calc(-1 * var(--n-space-s)) var(--_n-tab-group-list-background)}::slotted(nord-tab-panel){display:none;padding:var(--_n-tab-group-padding)}::slotted(nord-tab-panel[aria-hidden=false]){display:block}::slotted(nord-tab){z-index:var(--n-index-default)}:host([padding="m"]){--_n-tab-group-padding:var(--n-tab-group-padding, var(--n-space-m))}:host([padding="l"]){--_n-tab-group-padding:var(--n-tab-group-padding, var(--n-space-l))}:host([sticky]) .n-sticky{box-shadow:var(--_n-tab-group-list-border),var(--_n-tab-group-list-shadow);inset-inline:0;inset-block-end:auto}:host([sticky]),:host([sticky]) .n-tab-group-list{border-radius:0}`;var u;let h=1,v=u=class extends r{constructor(){super(...arguments),this.direction=new c(this),this.tabGroupId="nord-tab-group-"+h++,this.label="",this.padding="m",this.sticky=!1,this.selectedTab=this.initialSelectedTab,this.handleMutation=t=>{t.forEach((t=>{var e,r;if("selected"===t.attributeName&&null===t.oldValue){const a=t.target;null===(e=this.observer)||void 0===e||e.disconnect(),this.updateSelectedTab(a),null===(r=this.observer)||void 0===r||r.observe(this,u.observerOptions)}}))}}render(){return a`<div class="n-tab-group is-${this.direction.dir}"><div class="n-tab-group-list n-sticky" role="tablist" aria-label="${this.label}" @click="${this.handleTabChange}" @keydown="${this.handleKeydown}"><slot name="tab"></slot></div><slot></slot></div>`}connectedCallback(){super.connectedCallback(),this.updateSlots(),this.hasUpdated&&!this.observer&&this.setupObserver()}firstUpdated(){this.setupObserver()}updateSlots(){this.setupTabs(),this.setupPanels()}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this.observer)||void 0===t||t.disconnect(),this.observer=void 0}setupObserver(){this.observer||(this.observer=new MutationObserver(this.handleMutation),this.observer.observe(this,u.observerOptions))}get initialSelectedTab(){return s?null:this.querySelector("nord-tab[selected]")||this.querySelector("nord-tab")}setupTabs(){this.querySelectorAll("nord-tab").forEach(((t,e)=>{t.setAttribute("id",`${this.tabGroupId}-tab-${e+1}`),t.setAttribute("aria-controls",`${this.tabGroupId}-panel-${e+1}`),t.toggleAttribute("selected",t===this.selectedTab)}))}setupPanels(){var t;const e=this.querySelectorAll("nord-tab-panel"),r=null===(t=this.selectedTab)||void 0===t?void 0:t.getAttribute("aria-controls");e.forEach(((t,e)=>{t.setAttribute("id",`${this.tabGroupId}-panel-${e+1}`),t.setAttribute("aria-labelledby",`${this.tabGroupId}-tab-${e+1}`),t.setAttribute("aria-hidden",`${t.getAttribute("id")!==r}`)}))}handleTabChange(t){this.scrollTo({top:0}),t.target instanceof b&&t.target!==this.selectedTab&&this.updateSelectedTab(t.target)}previousTab(t){const e=[...this.querySelectorAll("nord-tab")],r=e.indexOf(t);return e[r-1]}handleKeydown(t){const e=t.target,r=this.querySelector("nord-tab:first-of-type"),a=this.querySelector("nord-tab:last-of-type"),s=this.querySelector(`#${e.getAttribute("id")} ~ nord-tab`)||r,o=this.previousTab(e)||a,i=(t,e)=>{e.preventDefault(),this.scrollTo({top:0}),this.updateSelectedTab(t)};switch(t.key){case"ArrowLeft":case"ArrowUp":i(this.direction.isLTR?o:s,t);break;case"ArrowRight":case"ArrowDown":i(this.direction.isLTR?s:o,t);break;case"Home":i(r,t);break;case"End":i(a,t)}}updateSelectedTab(t){const e=this.querySelector(`#${t.getAttribute("aria-controls")}`);t!==this.selectedTab&&(this.querySelectorAll("nord-tab").forEach((e=>{e.removeAttribute("selected"),e===t&&(e.setAttribute("selected",""),e.focus(),e.scrollIntoView({block:"nearest",inline:"nearest"}),this.selectedTab=e)})),this.querySelectorAll("nord-tab-panel").forEach((t=>{t.setAttribute("aria-hidden",`${t!==e}`)})))}};v.styles=[l,d,p],v.observerOptions={attributes:!0,subtree:!0,attributeFilter:["selected"],attributeOldValue:!0},t([o({reflect:!0})],v.prototype,"label",void 0),t([o({reflect:!0})],v.prototype,"padding",void 0),t([o({reflect:!0,type:Boolean})],v.prototype,"sticky",void 0),t([i()],v.prototype,"selectedTab",void 0),v=u=t([n("nord-tab-group")],v);var g=v;export{g as default};
2
2
  //# sourceMappingURL=TabGroup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TabGroup.js","sources":["../src/tab-group/TabGroup.ts"],"sourcesContent":["import { LitElement, html, isServer } from \"lit\"\nimport { customElement, property, state } from \"lit/decorators.js\"\n\nimport componentStyle from \"../common/styles/Component.css\"\nimport stickyStyle from \"../common/styles/Sticky.css\"\nimport style from \"./TabGroup.css\"\nimport Tab from \"../tab/Tab.js\"\n\nimport { DirectionController } from \"../common/controllers/DirectionController.js\"\n\nlet tabGroupCount = 1\n\n/**\n * Tab Group allows multiple panels to be contained within a single window,\n * using tabs as a navigational element.\n *\n * @status ready\n * @category navigation\n * @slot - The element which contains the content to be revealed.\n * @slot tab - The element which contains all tabs to reveal tabbed content.\n *\n * @cssprop [--n-tab-group-padding=0] - Controls the padding around the tab group (including the tab list), using our [spacing tokens](/tokens/#space).\n */\n@customElement(\"nord-tab-group\")\nexport default class TabGroup extends LitElement {\n static styles = [componentStyle, stickyStyle, style]\n\n private direction = new DirectionController(this)\n\n private observer?: MutationObserver\n\n private static observerOptions = {\n attributes: true,\n subtree: true,\n attributeFilter: [\"selected\"],\n attributeOldValue: true,\n }\n\n /**\n * Unique ID for each tab group component present.\n */\n private tabGroupId = `nord-tab-group-${tabGroupCount++}`\n\n /**\n * Adds an accessible label to the tab list container.\n */\n @property({ reflect: true }) label: string = \"\"\n\n /**\n * Controls the padding of the tab group component.\n */\n @property({ reflect: true }) padding?: \"m\" | \"l\" | \"none\" = \"m\"\n\n /**\n * Whether the tab list sticks to the top of the tab group as you scroll.\n */\n @property({ reflect: true, type: Boolean }) sticky: boolean = false\n\n /**\n * The current tab node selected in the tab group.\n */\n @state() private selectedTab = this.initialSelectedTab\n\n render() {\n return html`\n <div class=\"n-tab-group is-${this.direction.dir}\">\n <div\n class=\"n-tab-group-list n-sticky\"\n role=\"tablist\"\n aria-label=\"${this.label}\"\n @click=${this.handleTabChange}\n @keydown=${this.handleKeydown}\n >\n <slot name=\"tab\"></slot>\n </div>\n <slot></slot>\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.updateSlots()\n }\n\n private updateSlots() {\n this.setupTabs()\n this.setupPanels()\n }\n\n firstUpdated() {\n this.observer = new MutationObserver(this.handleMutation)\n this.observer?.observe(this, TabGroup.observerOptions)\n }\n\n /**\n * If the selected tab is selected programmatically update all the tabs.\n */\n private handleMutation = (mutations: MutationRecord[]) => {\n mutations.forEach(mutation => {\n if (mutation.attributeName === \"selected\" && mutation.oldValue === null) {\n const selectedTab = <Tab>mutation.target\n this.observer?.disconnect()\n this.updateSelectedTab(selectedTab)\n this.observer?.observe(this, TabGroup.observerOptions)\n }\n })\n }\n\n /**\n * Get the selected tab button, or the first tab button.\n */\n private get initialSelectedTab() {\n if (isServer) {\n return null\n }\n\n return this.querySelector(\"nord-tab[selected]\") || this.querySelector(\"nord-tab\")\n }\n\n /**\n * Apply accessible attributes and values to the tab buttons.\n */\n private setupTabs() {\n const tabs = this.querySelectorAll(\"nord-tab\")\n\n tabs.forEach((tab, index) => {\n tab.setAttribute(\"id\", `${this.tabGroupId}-tab-${index + 1}`)\n tab.setAttribute(\"aria-controls\", `${this.tabGroupId}-panel-${index + 1}`)\n tab.toggleAttribute(\"selected\", tab === this.selectedTab)\n })\n }\n\n /**\n * Apply accessible attributes and values to the tab panels.\n */\n private setupPanels() {\n const panels = this.querySelectorAll(\"nord-tab-panel\")\n const selectedPanelId = this.selectedTab?.getAttribute(\"aria-controls\")\n\n panels.forEach((panel, index) => {\n panel.setAttribute(\"id\", `${this.tabGroupId}-panel-${index + 1}`)\n panel.setAttribute(\"aria-labelledby\", `${this.tabGroupId}-tab-${index + 1}`)\n panel.setAttribute(\"aria-hidden\", `${panel.getAttribute(\"id\") !== selectedPanelId}`)\n })\n }\n\n private handleTabChange(event: Event) {\n // Always reset the scroll when a tab is selected.\n this.scrollTo({ top: 0 })\n\n /**\n * Return handler if it's not a tab or if it's already selected\n */\n if (!(event.target instanceof Tab) || event.target === this.selectedTab) return\n\n this.updateSelectedTab(event.target)\n }\n\n /**\n * Get the previous tab button in the tab group\n */\n private previousTab(tab: Tab) {\n const tabs = [...this.querySelectorAll(\"nord-tab\")]\n const selectedTabIndex = tabs.indexOf(tab)\n return tabs[selectedTabIndex - 1]\n }\n\n /**\n * Handle keyboard accessible controls.\n */\n private handleKeydown(event: KeyboardEvent) {\n const tab = <Tab>event.target\n\n const firstTab = <Tab>this.querySelector(\"nord-tab:first-of-type\")\n const lastTab = <Tab>this.querySelector(\"nord-tab:last-of-type\")\n const nextTab = <Tab>this.querySelector(`#${tab.getAttribute(\"id\")} ~ nord-tab`) || firstTab\n const previousTab = <Tab>this.previousTab(tab) || lastTab\n\n const updateTab = (selectedTab: Tab, keyEvent: Event) => {\n keyEvent.preventDefault()\n\n // Always reset the scroll when a tab is selected.\n this.scrollTo({ top: 0 })\n this.updateSelectedTab(selectedTab)\n }\n\n switch (event.key) {\n case \"ArrowLeft\":\n case \"ArrowUp\":\n updateTab(this.direction.isLTR ? previousTab : nextTab, event)\n break\n\n case \"ArrowRight\":\n case \"ArrowDown\":\n updateTab(this.direction.isLTR ? nextTab : previousTab, event)\n break\n\n case \"Home\":\n updateTab(firstTab, event)\n break\n\n case \"End\":\n updateTab(lastTab, event)\n break\n\n default:\n break\n }\n }\n\n /**\n * Update the selected tab button with attributes and values.\n * Update the tab group state.\n */\n private updateSelectedTab(selectedTab: Tab) {\n const selectedPanel = this.querySelector(`#${selectedTab.getAttribute(\"aria-controls\")}`)\n\n if (selectedTab === this.selectedTab) return\n\n /**\n * Reset all the selected state of the tabs, and select the clicked tab\n */\n this.querySelectorAll(\"nord-tab\").forEach(tab => {\n tab.removeAttribute(\"selected\")\n if (tab === selectedTab) {\n tab.setAttribute(\"selected\", \"\")\n tab.focus()\n tab.scrollIntoView({ block: \"nearest\", inline: \"nearest\" })\n this.selectedTab = tab\n }\n })\n\n /**\n * Reset all the visibility of the panels,\n * and show the panel related to the selected tab\n */\n this.querySelectorAll(\"nord-tab-panel\").forEach(panel => {\n panel.setAttribute(\"aria-hidden\", `${panel !== selectedPanel}`)\n })\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"nord-tab-group\": TabGroup\n }\n}\n"],"names":["tabGroupCount","TabGroup","TabGroup_1","LitElement","constructor","this","direction","DirectionController","tabGroupId","label","padding","sticky","selectedTab","initialSelectedTab","handleMutation","mutations","forEach","mutation","attributeName","oldValue","target","_a","observer","disconnect","updateSelectedTab","_b","observe","observerOptions","render","html","dir","handleTabChange","handleKeydown","connectedCallback","super","updateSlots","setupTabs","setupPanels","firstUpdated","MutationObserver","isServer","querySelector","querySelectorAll","tab","index","setAttribute","toggleAttribute","panels","selectedPanelId","getAttribute","panel","event","scrollTo","top","Tab","previousTab","tabs","selectedTabIndex","indexOf","firstTab","lastTab","nextTab","updateTab","keyEvent","preventDefault","key","isLTR","selectedPanel","removeAttribute","focus","scrollIntoView","block","inline","styles","componentStyle","stickyStyle","style","attributes","subtree","attributeFilter","attributeOldValue","__decorate","property","reflect","prototype","type","Boolean","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"TabGroup.js","sources":["../src/tab-group/TabGroup.ts"],"sourcesContent":["import { LitElement, html, isServer } from \"lit\"\nimport { customElement, property, state } from \"lit/decorators.js\"\n\nimport componentStyle from \"../common/styles/Component.css\"\nimport stickyStyle from \"../common/styles/Sticky.css\"\nimport style from \"./TabGroup.css\"\nimport Tab from \"../tab/Tab.js\"\n\nimport { DirectionController } from \"../common/controllers/DirectionController.js\"\n\nlet tabGroupCount = 1\n\n/**\n * Tab Group allows multiple panels to be contained within a single window,\n * using tabs as a navigational element.\n *\n * @status ready\n * @category navigation\n * @slot - The element which contains the content to be revealed.\n * @slot tab - The element which contains all tabs to reveal tabbed content.\n *\n * @cssprop [--n-tab-group-padding=0] - Controls the padding around the tab group (including the tab list), using our [spacing tokens](/tokens/#space).\n */\n@customElement(\"nord-tab-group\")\nexport default class TabGroup extends LitElement {\n static styles = [componentStyle, stickyStyle, style]\n\n private direction = new DirectionController(this)\n\n private observer?: MutationObserver\n\n private static observerOptions = {\n attributes: true,\n subtree: true,\n attributeFilter: [\"selected\"],\n attributeOldValue: true,\n }\n\n /**\n * Unique ID for each tab group component present.\n */\n private tabGroupId = `nord-tab-group-${tabGroupCount++}`\n\n /**\n * Adds an accessible label to the tab list container.\n */\n @property({ reflect: true }) label: string = \"\"\n\n /**\n * Controls the padding of the tab group component.\n */\n @property({ reflect: true }) padding?: \"m\" | \"l\" | \"none\" = \"m\"\n\n /**\n * Whether the tab list sticks to the top of the tab group as you scroll.\n */\n @property({ reflect: true, type: Boolean }) sticky: boolean = false\n\n /**\n * The current tab node selected in the tab group.\n */\n @state() private selectedTab = this.initialSelectedTab\n\n render() {\n return html`\n <div class=\"n-tab-group is-${this.direction.dir}\">\n <div\n class=\"n-tab-group-list n-sticky\"\n role=\"tablist\"\n aria-label=\"${this.label}\"\n @click=${this.handleTabChange}\n @keydown=${this.handleKeydown}\n >\n <slot name=\"tab\"></slot>\n </div>\n <slot></slot>\n </div>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.updateSlots()\n // Re-setup observer after reconnection (firstUpdated only runs once per instance)\n if (this.hasUpdated && !this.observer) {\n this.setupObserver()\n }\n }\n\n firstUpdated() {\n this.setupObserver()\n }\n\n private updateSlots() {\n this.setupTabs()\n this.setupPanels()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n // Clean up observer to prevent memory leaks\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n private setupObserver() {\n // Avoid creating multiple observers\n if (this.observer) {\n return\n }\n\n this.observer = new MutationObserver(this.handleMutation)\n this.observer.observe(this, TabGroup.observerOptions)\n }\n\n /**\n * If the selected tab is selected programmatically update all the tabs.\n */\n private handleMutation = (mutations: MutationRecord[]) => {\n mutations.forEach(mutation => {\n if (mutation.attributeName === \"selected\" && mutation.oldValue === null) {\n const selectedTab = <Tab>mutation.target\n this.observer?.disconnect()\n this.updateSelectedTab(selectedTab)\n this.observer?.observe(this, TabGroup.observerOptions)\n }\n })\n }\n\n /**\n * Get the selected tab button, or the first tab button.\n */\n private get initialSelectedTab() {\n if (isServer) {\n return null\n }\n\n return this.querySelector(\"nord-tab[selected]\") || this.querySelector(\"nord-tab\")\n }\n\n /**\n * Apply accessible attributes and values to the tab buttons.\n */\n private setupTabs() {\n const tabs = this.querySelectorAll(\"nord-tab\")\n\n tabs.forEach((tab, index) => {\n tab.setAttribute(\"id\", `${this.tabGroupId}-tab-${index + 1}`)\n tab.setAttribute(\"aria-controls\", `${this.tabGroupId}-panel-${index + 1}`)\n tab.toggleAttribute(\"selected\", tab === this.selectedTab)\n })\n }\n\n /**\n * Apply accessible attributes and values to the tab panels.\n */\n private setupPanels() {\n const panels = this.querySelectorAll(\"nord-tab-panel\")\n const selectedPanelId = this.selectedTab?.getAttribute(\"aria-controls\")\n\n panels.forEach((panel, index) => {\n panel.setAttribute(\"id\", `${this.tabGroupId}-panel-${index + 1}`)\n panel.setAttribute(\"aria-labelledby\", `${this.tabGroupId}-tab-${index + 1}`)\n panel.setAttribute(\"aria-hidden\", `${panel.getAttribute(\"id\") !== selectedPanelId}`)\n })\n }\n\n private handleTabChange(event: Event) {\n // Always reset the scroll when a tab is selected.\n this.scrollTo({ top: 0 })\n\n /**\n * Return handler if it's not a tab or if it's already selected\n */\n if (!(event.target instanceof Tab) || event.target === this.selectedTab) return\n\n this.updateSelectedTab(event.target)\n }\n\n /**\n * Get the previous tab button in the tab group\n */\n private previousTab(tab: Tab) {\n const tabs = [...this.querySelectorAll(\"nord-tab\")]\n const selectedTabIndex = tabs.indexOf(tab)\n return tabs[selectedTabIndex - 1]\n }\n\n /**\n * Handle keyboard accessible controls.\n */\n private handleKeydown(event: KeyboardEvent) {\n const tab = <Tab>event.target\n\n const firstTab = <Tab>this.querySelector(\"nord-tab:first-of-type\")\n const lastTab = <Tab>this.querySelector(\"nord-tab:last-of-type\")\n const nextTab = <Tab>this.querySelector(`#${tab.getAttribute(\"id\")} ~ nord-tab`) || firstTab\n const previousTab = <Tab>this.previousTab(tab) || lastTab\n\n const updateTab = (selectedTab: Tab, keyEvent: Event) => {\n keyEvent.preventDefault()\n\n // Always reset the scroll when a tab is selected.\n this.scrollTo({ top: 0 })\n this.updateSelectedTab(selectedTab)\n }\n\n switch (event.key) {\n case \"ArrowLeft\":\n case \"ArrowUp\":\n updateTab(this.direction.isLTR ? previousTab : nextTab, event)\n break\n\n case \"ArrowRight\":\n case \"ArrowDown\":\n updateTab(this.direction.isLTR ? nextTab : previousTab, event)\n break\n\n case \"Home\":\n updateTab(firstTab, event)\n break\n\n case \"End\":\n updateTab(lastTab, event)\n break\n\n default:\n break\n }\n }\n\n /**\n * Update the selected tab button with attributes and values.\n * Update the tab group state.\n */\n private updateSelectedTab(selectedTab: Tab) {\n const selectedPanel = this.querySelector(`#${selectedTab.getAttribute(\"aria-controls\")}`)\n\n if (selectedTab === this.selectedTab) return\n\n /**\n * Reset all the selected state of the tabs, and select the clicked tab\n */\n this.querySelectorAll(\"nord-tab\").forEach(tab => {\n tab.removeAttribute(\"selected\")\n if (tab === selectedTab) {\n tab.setAttribute(\"selected\", \"\")\n tab.focus()\n tab.scrollIntoView({ block: \"nearest\", inline: \"nearest\" })\n this.selectedTab = tab\n }\n })\n\n /**\n * Reset all the visibility of the panels,\n * and show the panel related to the selected tab\n */\n this.querySelectorAll(\"nord-tab-panel\").forEach(panel => {\n panel.setAttribute(\"aria-hidden\", `${panel !== selectedPanel}`)\n })\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"nord-tab-group\": TabGroup\n }\n}\n"],"names":["tabGroupCount","TabGroup","TabGroup_1","LitElement","constructor","this","direction","DirectionController","tabGroupId","label","padding","sticky","selectedTab","initialSelectedTab","handleMutation","mutations","forEach","mutation","attributeName","oldValue","target","_a","observer","disconnect","updateSelectedTab","_b","observe","observerOptions","render","html","dir","handleTabChange","handleKeydown","connectedCallback","super","updateSlots","hasUpdated","setupObserver","firstUpdated","setupTabs","setupPanels","disconnectedCallback","undefined","MutationObserver","isServer","querySelector","querySelectorAll","tab","index","setAttribute","toggleAttribute","panels","selectedPanelId","getAttribute","panel","event","scrollTo","top","Tab","previousTab","tabs","selectedTabIndex","indexOf","firstTab","lastTab","nextTab","updateTab","keyEvent","preventDefault","key","isLTR","selectedPanel","removeAttribute","focus","scrollIntoView","block","inline","styles","componentStyle","stickyStyle","style","attributes","subtree","attributeFilter","attributeOldValue","__decorate","property","reflect","prototype","type","Boolean","state","customElement"],"mappings":"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"}