import * as interfaces from './interfaces/index.js'; import { DeesElement, type TemplateResult, property, customElement, html, css, cssManager, state, } from '@design.estate/dees-element'; import './dees-appui-tabs.js'; import type { DeesAppuiTabs } from './dees-appui-tabs.js'; export interface IAppViewTab extends interfaces.ITab { content?: TemplateResult | (() => TemplateResult); } export interface IAppView { id: string; name: string; description?: string; iconName?: string; tabs: IAppViewTab[]; menuItems?: interfaces.ISelectionOption[]; } @customElement('dees-appui-view') export class DeesAppuiView extends DeesElement { public static demo = () => html` console.log('Overview tab'), content: html`
Overview Content
` }, { key: 'details', iconName: 'file-alt', action: () => console.log('Details tab'), content: html`
Details Content
` } ], menuItems: [ { key: 'General', action: () => console.log('General') }, { key: 'Advanced', action: () => console.log('Advanced') }, ] }} >
`; // INSTANCE @property({ type: Object }) public viewConfig: IAppView; @state() private selectedTab: IAppViewTab | null = null; @state() private tabs: DeesAppuiTabs; public static styles = [ cssManager.defaultStyles, css` :host { display: block; position: relative; width: 100%; height: 100%; background: #161616; } .view-container { position: relative; width: 100%; height: 100%; display: flex; flex-direction: column; } .view-header { background: #000000; border-bottom: 1px solid #333; flex-shrink: 0; } .view-content { flex: 1; position: relative; overflow: hidden; } .tab-content { position: absolute; top: 0; left: 0; right: 0; bottom: 0; overflow: auto; opacity: 0; transition: opacity 0.2s; } .tab-content.active { opacity: 1; } dees-appui-tabs { height: 60px; } `, ]; public render(): TemplateResult { if (!this.viewConfig) { return html`
No view configuration provided
`; } return html`
this.handleTabSelect(e)} >
${this.viewConfig.tabs.map((tab) => { const isActive = tab === this.selectedTab; const content = typeof tab.content === 'function' ? tab.content() : tab.content; return html`
${content || html``}
`; })}
`; } async firstUpdated() { this.tabs = this.shadowRoot.querySelector('dees-appui-tabs'); if (this.viewConfig?.tabs?.length > 0) { this.selectedTab = this.viewConfig.tabs[0]; } } private handleTabSelect(e: CustomEvent) { this.selectedTab = e.detail.tab; // Re-emit the event with view context this.dispatchEvent(new CustomEvent('view-tab-select', { detail: { view: this.viewConfig, tab: e.detail.tab }, bubbles: true, composed: true })); } // Public methods for external control public selectTab(tabKey: string) { const tab = this.viewConfig.tabs.find(t => t.key === tabKey); if (tab) { this.selectedTab = tab; if (this.tabs) { this.tabs.selectedTab = tab; } } } public getMenuItems(): interfaces.ISelectionOption[] { return this.viewConfig?.menuItems || []; } public getTabs(): IAppViewTab[] { return this.viewConfig?.tabs || []; } }