180 lines
4.2 KiB
TypeScript
180 lines
4.2 KiB
TypeScript
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/dees-appui-tabs.js';
|
|
import type { DeesAppuiTabs } from '../dees-appui-tabs/dees-appui-tabs.js';
|
|
import { demoFunc } from './dees-appui-view.demo.js';
|
|
import { themeDefaultStyles } from '../../00theme.js';
|
|
|
|
export interface IViewTab extends interfaces.IMenuItem {
|
|
content?: TemplateResult | (() => TemplateResult);
|
|
useSlotName?: boolean;
|
|
slotName?: string;
|
|
paddingPx?: number;
|
|
}
|
|
|
|
export interface IAppView {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
iconName?: string;
|
|
tabs: IViewTab[];
|
|
menuItems?: interfaces.IMenuItem[];
|
|
}
|
|
|
|
@customElement('dees-appui-view')
|
|
export class DeesAppuiView extends DeesElement {
|
|
public static demo = demoFunc;
|
|
|
|
// INSTANCE
|
|
@property({ type: Object })
|
|
accessor viewConfig: IAppView;
|
|
|
|
@state()
|
|
accessor selectedTab: IViewTab | null = null;
|
|
|
|
@state()
|
|
accessor tabs: DeesAppuiTabs;
|
|
|
|
@property({ type: Number })
|
|
accessor paddingPx: number = 16;
|
|
|
|
public static styles = [
|
|
themeDefaultStyles,
|
|
cssManager.defaultStyles,
|
|
css`
|
|
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
|
|
: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`<div>No view configuration provided</div>`;
|
|
}
|
|
|
|
return html`
|
|
<div class="view-container">
|
|
<div class="view-header">
|
|
<dees-appui-tabs
|
|
.tabs=${this.viewConfig.tabs}
|
|
.selectedTab=${this.selectedTab}
|
|
@tab-select=${(e: CustomEvent) => this.handleTabSelect(e)}
|
|
></dees-appui-tabs>
|
|
</div>
|
|
<div class="view-content">
|
|
${this.viewConfig.tabs.map((tab) => {
|
|
const isActive = tab === this.selectedTab;
|
|
const content = typeof tab.content === 'function' ? tab.content() : tab.content;
|
|
const padding = tab.paddingPx ?? this.paddingPx;
|
|
return html`
|
|
<div class="tab-content ${isActive ? 'active' : ''}" style="padding: ${padding}px;">
|
|
${content
|
|
? content
|
|
: tab.useSlotName
|
|
? html`<slot name="${tab.slotName || tab.key}"></slot>`
|
|
: ''}
|
|
</div>
|
|
`;
|
|
})}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
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.IMenuItem[] {
|
|
return this.viewConfig?.menuItems || [];
|
|
}
|
|
|
|
public getTabs(): IViewTab[] {
|
|
return this.viewConfig?.tabs || [];
|
|
}
|
|
} |