@limetech/lime-elements
Version:
175 lines (174 loc) • 6.32 kB
JavaScript
import { h, Host, } from "@stencil/core";
import { dispatchResizeEvent } from "../../util/dispatch-resize-event";
/**
* The `limel-tab-panel` component uses the `limel-tab-bar` component together
* with custom slotted components and will display the content for the currently
* active tab. Each slotted component must have an id equal to the id of the
* corresponding tab it belongs to. These components should implement the
* [TabPanelComponent](#/type/TabPanelComponent/) interface.
*
* The `limel-tab-panel` component will automatically set each tab configuration
* on the corresponding slotted component as a property named `tab` so that the
* component can take action upon that. Sometimes it might be desirable to not
* load data or render anything until the tab is active.
*
* The slotted components can also emit the `changeTab` event to update anything
* inside the actual tab, e.g. to change the icon, color or badge.
*
* @slot - Content to put inside the `limel-tab-panel`. Each slotted element
* must have the `id` attribute equal to the id of the tab it belongs to.
* @exampleComponent limel-example-tab-panel-basic
*/
export class TabPanel {
constructor() {
/**
* The tabs to display in the panel
*/
this.tabs = [];
this.slotElements = [];
this.handleChangeTabs = this.handleChangeTabs.bind(this);
this.setSlotElements = this.setSlotElements.bind(this);
this.setTabStatus = this.setTabStatus.bind(this);
}
connectedCallback() {
this.initialize();
}
componentDidLoad() {
this.initialize();
}
initialize() {
const slot = this.getSlot();
if (!slot) {
return;
}
slot.addEventListener('slotchange', this.setSlotElements);
this.setSlotElements();
// eslint-disable-next-line unicorn/no-array-for-each
this.tabs.forEach(this.setTabStatus);
}
disconnectedCallback() {
const slot = this.getSlot();
slot.removeEventListener('slotchange', this.setSlotElements);
}
tabsChanged() {
this.hidePanels();
// eslint-disable-next-line unicorn/no-array-for-each
this.tabs.forEach(this.setTabStatus);
}
render() {
return (h(Host, { key: 'ebab881a0b0efc36b64c866b58b919890c526525', onChangeTab: this.handleChangeTabs }, h("div", { key: '1417a34aea0af009e44cd91ac8fd425412a2b706', class: "tab-panel" }, h("limel-tab-bar", { key: '5b420eeec41fdd353ba0ba36bb0e475c3fd26821', tabs: this.tabs }), h("div", { key: 'aa3d6f711a824a07eed6f2b5120497dd4218ed7b', class: "tab-content" }, h("slot", { key: '7ba511fa07bd96018e4d8d288d7b1dca572cead0' })))));
}
setSlotElements() {
const slot = this.getSlot();
this.hidePanels();
this.slotElements = Array.prototype.slice.call(slot.assignedElements());
// eslint-disable-next-line unicorn/no-array-for-each
this.tabs.forEach(this.setTabStatus);
}
setTabStatus(tab) {
const element = this.slotElements.find((e) => e.id === tab.id);
if (!element) {
return;
}
if (tab.active) {
element.style.display = '';
}
else {
element.style.display = 'none';
}
element['tab'] = tab;
}
handleChangeTabs(event) {
this.tabs = this.tabs.map((tab) => {
if (tab.id === event.detail.id) {
return event.detail;
}
return tab;
});
this.setTabStatus(event.detail);
// Content inside the newly activated tab may need to redraw once
// visible, so we use the resize event trick. /Ads
setTimeout(dispatchResizeEvent);
}
getSlot() {
return this.host.shadowRoot.querySelector('slot');
}
hidePanels() {
for (const element of this.slotElements) {
element.style.display = 'none';
}
}
static get is() { return "limel-tab-panel"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() {
return {
"$": ["tab-panel.scss"]
};
}
static get styleUrls() {
return {
"$": ["tab-panel.css"]
};
}
static get properties() {
return {
"tabs": {
"type": "unknown",
"mutable": true,
"complexType": {
"original": "Tab[]",
"resolved": "Tab[]",
"references": {
"Tab": {
"location": "import",
"path": "../tab-bar/tab.types",
"id": "src/components/tab-bar/tab.types.ts::Tab",
"referenceLocation": "Tab"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "The tabs to display in the panel"
},
"getter": false,
"setter": false,
"defaultValue": "[]"
}
};
}
static get events() {
return [{
"method": "changeTab",
"name": "changeTab",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Emitted when a tab has been changed"
},
"complexType": {
"original": "Tab",
"resolved": "Tab",
"references": {
"Tab": {
"location": "import",
"path": "../tab-bar/tab.types",
"id": "src/components/tab-bar/tab.types.ts::Tab",
"referenceLocation": "Tab"
}
}
}
}];
}
static get elementRef() { return "host"; }
static get watchers() {
return [{
"propName": "tabs",
"methodName": "tabsChanged"
}];
}
}