import { tab_group_styles_default } from "./chunk.EG6EOQHP.js"; import { scrollIntoView } from "./chunk.RK73WSZS.js"; import { SlIconButton } from "./chunk.Y77CZW56.js"; import { LocalizeController } from "./chunk.NH3SRVOC.js"; import { e } from "./chunk.UZVKBFXH.js"; import { watch } from "./chunk.FA5RT4K4.js"; import { ShoelaceElement, e as e2, n, r } from "./chunk.SEXBCYCU.js"; import { x } from "./chunk.CXZZ2LVK.js"; import { __decorateClass, __spreadValues } from "./chunk.KIILAQWQ.js"; // src/components/tab-group/tab-group.component.ts var SlTabGroup = class extends ShoelaceElement { constructor() { super(...arguments); this.localize = new LocalizeController(this); this.tabs = []; this.panels = []; this.hasScrollControls = false; this.placement = "top"; this.activation = "auto"; this.noScrollControls = false; } connectedCallback() { const whenAllDefined = Promise.all([ customElements.whenDefined("sl-tab"), customElements.whenDefined("sl-tab-panel") ]); super.connectedCallback(); this.resizeObserver = new ResizeObserver(() => { this.repositionIndicator(); this.updateScrollControls(); }); this.mutationObserver = new MutationObserver((mutations) => { if (mutations.some((m) => !["aria-labelledby", "aria-controls"].includes(m.attributeName))) { setTimeout(() => this.setAriaLabels()); } if (mutations.some((m) => m.attributeName === "disabled")) { this.syncTabsAndPanels(); } }); this.updateComplete.then(() => { this.syncTabsAndPanels(); this.mutationObserver.observe(this, { attributes: true, childList: true, subtree: true }); this.resizeObserver.observe(this.nav); whenAllDefined.then(() => { const intersectionObserver = new IntersectionObserver((entries, observer) => { var _a; if (entries[0].intersectionRatio > 0) { this.setAriaLabels(); this.setActiveTab((_a = this.getActiveTab()) != null ? _a : this.tabs[0], { emitEvents: false }); observer.unobserve(entries[0].target); } }); intersectionObserver.observe(this.tabGroup); }); }); } disconnectedCallback() { super.disconnectedCallback(); this.mutationObserver.disconnect(); this.resizeObserver.unobserve(this.nav); } getAllTabs(options = { includeDisabled: true }) { const slot = this.shadowRoot.querySelector('slot[name="nav"]'); return [...slot.assignedElements()].filter((el) => { return options.includeDisabled ? el.tagName.toLowerCase() === "sl-tab" : el.tagName.toLowerCase() === "sl-tab" && !el.disabled; }); } getAllPanels() { return [...this.body.assignedElements()].filter((el) => el.tagName.toLowerCase() === "sl-tab-panel"); } getActiveTab() { return this.tabs.find((el) => el.active); } handleClick(event) { const target = event.target; const tab = target.closest("sl-tab"); const tabGroup = tab == null ? void 0 : tab.closest("sl-tab-group"); if (tabGroup !== this) { return; } if (tab !== null) { this.setActiveTab(tab, { scrollBehavior: "smooth" }); } } handleKeyDown(event) { const target = event.target; const tab = target.closest("sl-tab"); const tabGroup = tab == null ? void 0 : tab.closest("sl-tab-group"); if (tabGroup !== this) { return; } if (["Enter", " "].includes(event.key)) { if (tab !== null) { this.setActiveTab(tab, { scrollBehavior: "smooth" }); event.preventDefault(); } } if (["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) { const activeEl = this.tabs.find((t) => t.matches(":focus")); const isRtl = this.localize.dir() === "rtl"; if ((activeEl == null ? void 0 : activeEl.tagName.toLowerCase()) === "sl-tab") { let index = this.tabs.indexOf(activeEl); if (event.key === "Home") { index = 0; } else if (event.key === "End") { index = this.tabs.length - 1; } else if (["top", "bottom"].includes(this.placement) && event.key === (isRtl ? "ArrowRight" : "ArrowLeft") || ["start", "end"].includes(this.placement) && event.key === "ArrowUp") { index--; } else if (["top", "bottom"].includes(this.placement) && event.key === (isRtl ? "ArrowLeft" : "ArrowRight") || ["start", "end"].includes(this.placement) && event.key === "ArrowDown") { index++; } if (index < 0) { index = this.tabs.length - 1; } if (index > this.tabs.length - 1) { index = 0; } this.tabs[index].focus({ preventScroll: true }); if (this.activation === "auto") { this.setActiveTab(this.tabs[index], { scrollBehavior: "smooth" }); } if (["top", "bottom"].includes(this.placement)) { scrollIntoView(this.tabs[index], this.nav, "horizontal"); } event.preventDefault(); } } } handleScrollToStart() { this.nav.scroll({ left: this.localize.dir() === "rtl" ? this.nav.scrollLeft + this.nav.clientWidth : this.nav.scrollLeft - this.nav.clientWidth, behavior: "smooth" }); } handleScrollToEnd() { this.nav.scroll({ left: this.localize.dir() === "rtl" ? this.nav.scrollLeft - this.nav.clientWidth : this.nav.scrollLeft + this.nav.clientWidth, behavior: "smooth" }); } setActiveTab(tab, options) { options = __spreadValues({ emitEvents: true, scrollBehavior: "auto" }, options); if (tab !== this.activeTab && !tab.disabled) { const previousTab = this.activeTab; this.activeTab = tab; this.tabs.forEach((el) => el.active = el === this.activeTab); this.panels.forEach((el) => { var _a; return el.active = el.name === ((_a = this.activeTab) == null ? void 0 : _a.panel); }); this.syncIndicator(); if (["top", "bottom"].includes(this.placement)) { scrollIntoView(this.activeTab, this.nav, "horizontal", options.scrollBehavior); } if (options.emitEvents) { if (previousTab) { this.emit("sl-tab-hide", { detail: { name: previousTab.panel } }); } this.emit("sl-tab-show", { detail: { name: this.activeTab.panel } }); } } } setAriaLabels() { this.tabs.forEach((tab) => { const panel = this.panels.find((el) => el.name === tab.panel); if (panel) { tab.setAttribute("aria-controls", panel.getAttribute("id")); panel.setAttribute("aria-labelledby", tab.getAttribute("id")); } }); } repositionIndicator() { const currentTab = this.getActiveTab(); if (!currentTab) { return; } const width = currentTab.clientWidth; const height = currentTab.clientHeight; const isRtl = this.localize.dir() === "rtl"; const allTabs = this.getAllTabs(); const precedingTabs = allTabs.slice(0, allTabs.indexOf(currentTab)); const offset = precedingTabs.reduce( (previous, current) => ({ left: previous.left + current.clientWidth, top: previous.top + current.clientHeight }), { left: 0, top: 0 } ); switch (this.placement) { case "top": case "bottom": this.indicator.style.width = `${width}px`; this.indicator.style.height = "auto"; this.indicator.style.translate = isRtl ? `${-1 * offset.left}px` : `${offset.left}px`; break; case "start": case "end": this.indicator.style.width = "auto"; this.indicator.style.height = `${height}px`; this.indicator.style.translate = `0 ${offset.top}px`; break; } } // This stores tabs and panels so we can refer to a cache instead of calling querySelectorAll() multiple times. syncTabsAndPanels() { this.tabs = this.getAllTabs({ includeDisabled: false }); this.panels = this.getAllPanels(); this.syncIndicator(); this.updateComplete.then(() => this.updateScrollControls()); } updateScrollControls() { if (this.noScrollControls) { this.hasScrollControls = false; } else { this.hasScrollControls = ["top", "bottom"].includes(this.placement) && this.nav.scrollWidth > this.nav.clientWidth; } } syncIndicator() { const tab = this.getActiveTab(); if (tab) { this.indicator.style.display = "block"; this.repositionIndicator(); } else { this.indicator.style.display = "none"; } } /** Shows the specified tab panel. */ show(panel) { const tab = this.tabs.find((el) => el.panel === panel); if (tab) { this.setActiveTab(tab, { scrollBehavior: "smooth" }); } } render() { const isRtl = this.localize.dir() === "rtl"; return x`