@freshworks/crayons
Version:
Crayons Web Components library
206 lines (201 loc) • 7.67 kB
JavaScript
import { attachShadow, createEvent, h, proxyCustomElement } from '@stencil/core/internal/client';
import { d as defineCustomElement$2 } from './tab-panel.js';
const tabsCss = ":host{font-family:var(--fw-font-family, -apple-system, blinkmacsystemfont, \"Segoe UI\", roboto, oxygen, ubuntu, cantarell, \"Open Sans\", \"Helvetica Neue\", sans-serif);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-box-sizing:border-box;box-sizing:border-box}.tabs{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:var(--fw-tabs-width, \"inherit\");height:var(--fw-tabs-height, \"inherit\")}.tabs__items__nav{padding:0;padding-left:var(--fw-tabs-padding-left, 12px);padding-right:var(--fw-tabs-padding-right, 12px);margin-left:var(--fw-tabs-margin-l, 0);margin-right:var(--fw-tabs-margin-r, 0);display:-ms-flexbox;display:flex;border-bottom:1px solid #ebeff3;overflow-x:auto;overflow-y:hidden}.tabs__items__nav__box{background-color:#f5f7f9;border:1px solid #ebeff3;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.tabs__items__tabs{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;position:relative}";
let Tabs = class extends HTMLElement {
constructor() {
super();
this.__registerHost();
attachShadow(this);
this.fwChange = createEvent(this, "fwChange", 7);
/**
* Describes the purpose of set of tabs.
*/
this.label = '';
/**
* The index of the activated Tab(Starts from 0)
*/
this.activeTabIndex = 0;
/**
* The style of tab headers that needs to be displayed, box will display headers in a container.
*/
this.variant = 'normal';
}
syncTabsAndPanels() {
this.tabs = Array.from(this.el.querySelectorAll('fw-tab')).filter((tab) => !tab.disabled);
this.panels = Array.from(this.el.querySelectorAll('fw-tab-panel'));
}
init() {
this.syncTabsAndPanels();
// Assign aria attributes
this.assignAriaLabels();
// set active tab
this.setActiveTab(this.getActiveTab() || this.tabs[0], false);
}
createPanelIfRequired() {
let counter = 0;
this.tabs = Array.from(this.el.querySelectorAll('fw-tab'));
this.tabs.map((tab) => {
if (tab.tabHeader) {
tab.setAttribute('panel', `panel-${counter++}`);
tab.setAttribute('slot', 'tab');
const panel = document.createElement('fw-tab-panel');
panel.innerHTML = tab.innerHTML;
panel.setAttribute('id', `fw-tab-panel-${counter++}`);
panel.setAttribute('name', tab.getAttribute('panel') || tab.panel);
this.el.appendChild(panel);
}
});
}
assignAriaLabels() {
Array.from(this.el.querySelectorAll('fw-tab')).map((tab) => {
const panel = this.panels.find((p) => p.name === tab.getAttribute('panel') || tab.panel);
if (panel) {
tab.setAttribute('aria-controls', panel.getAttribute('id'));
panel.setAttribute('aria-labelledby', tab.getAttribute('id'));
}
});
}
/**
* Activates the tab based based on tabindex or name.
*/
async activateTab(index, name) {
(index || index === 0) && (this.activeTabIndex = index);
name && (this.activeTabName = name);
this.setActiveTab(this.getActiveTab(), false);
}
setActiveTab(tab, shouldEmit = true) {
if (tab && tab !== this.activeTab && !tab.disabled) {
this.activeTab = tab;
this.activeTabIndex = this.tabs.indexOf(tab);
// Sync active tab and panel
this.tabs.map((el) => (el.active = el === this.activeTab));
const activePanel = this.activeTab.getAttribute('panel') || this.activeTab.panel;
this.panels.map((el) => (el.active = el.name === activePanel));
// Emit events
if (shouldEmit) {
this.fwChange.emit({
tabIndex: this.activeTabIndex,
tabName: this.activeTab.id,
});
}
}
}
componentWillLoad() {
this.init();
}
connectedCallback() {
// Create fw-tab-panel component explictly if tab-header attribute is present.
this.createPanelIfRequired();
this.tabsMutation = new MutationObserver(() => {
this.init();
});
this.tabMutation = new MutationObserver((mutations) => {
if (mutations.some((m) => m.attributeName === 'disabled')) {
this.syncTabsAndPanels();
}
});
this.tabsMutation.observe(this.el, {
childList: true,
attributes: true,
});
Array.from(this.el.querySelectorAll('fw-tab')).forEach((tab) => {
this.tabMutation.observe(tab, {
attributes: true,
});
});
}
disconnectedCallback() {
var _a, _b;
(_a = this.tabsMutation) === null || _a === void 0 ? void 0 : _a.disconnect();
(_b = this.tabMutation) === null || _b === void 0 ? void 0 : _b.disconnect();
this.tabsMutation = undefined;
this.tabMutation = undefined;
}
getActiveTab() {
return (((this.activeTabIndex || this.activeTabIndex === 0) &&
this.tabs[this.activeTabIndex]) ||
this.tabs.find((tab) => tab.id === this.activeTabName || tab.active));
}
handleClick(event) {
const target = event.target;
const tab = target.closest('fw-tab');
const tabs = tab === null || tab === void 0 ? void 0 : tab.closest('fw-tabs');
if (tabs !== this.el) {
return;
}
if (tab) {
this.setActiveTab(tab);
}
}
handleKeyDown(event) {
const target = event.target;
const tab = target.closest('fw-tab');
const tabs = tab === null || tab === void 0 ? void 0 : tab.closest('fw-tabs');
if (tabs !== this.el) {
return;
}
switch (event.code) {
case 'ArrowDown':
case 'ArrowUp':
case 'ArrowLeft':
case 'ArrowRight':
event.preventDefault();
break;
}
}
handleKeyUp(e) {
const target = e.target;
const tab = target.closest('fw-tab');
const tabs = tab === null || tab === void 0 ? void 0 : tab.closest('fw-tabs');
if (tabs !== this.el) {
return;
}
if (this.activeTabIndex !== undefined) {
let index = this.activeTabIndex;
switch (e.code) {
case 'ArrowLeft':
case 'ArrowUp':
index = (index - 1 + this.tabs.length) % this.tabs.length;
break;
case 'ArrowRight':
case 'ArrowDown':
index = (index + 1) % this.tabs.length;
break;
default:
return;
}
this.tabs[index].focus();
this.setActiveTab(this.tabs[index]);
}
}
render() {
return (h("div", { class: 'tabs' }, h("div", { class: 'tabs__items__nav' + (this.variant === 'box' ? '__box' : '') }, h("div", { class: 'tabs__items__tabs', role: 'tablist', "aria-label": this.label }, h("slot", { name: 'tab' }))), h("slot", null)));
}
get el() { return this; }
static get style() { return tabsCss; }
};
Tabs = /*@__PURE__*/ proxyCustomElement(Tabs, [1, "fw-tabs", {
"label": [1],
"activeTabIndex": [1538, "active-tab-index"],
"activeTabName": [513, "active-tab-name"],
"variant": [1],
"activateTab": [64]
}, [[0, "click", "handleClick"], [0, "keydown", "handleKeyDown"], [0, "keyup", "handleKeyUp"]]]);
function defineCustomElement$1() {
const components = ["fw-tabs", "fw-tab-panel"];
components.forEach(tagName => { switch (tagName) {
case "fw-tabs":
if (!customElements.get(tagName)) {
customElements.define(tagName, Tabs);
}
break;
case "fw-tab-panel":
if (!customElements.get(tagName)) {
defineCustomElement$2();
}
break;
} });
}
const FwTabs = Tabs;
const defineCustomElement = defineCustomElement$1;
export { FwTabs, defineCustomElement };