feat(theme,interfaces): Introduce a global theming system and unify menu/tab interfaces; migrate components to use themeDefaultStyles and update APIs accordingly

This commit is contained in:
2025-12-29 01:20:24 +00:00
parent 9175799ec6
commit e38d3cd42a
78 changed files with 1413 additions and 616 deletions

View File

@@ -16,6 +16,7 @@ import type { DeesAppuiSecondarymenu } from '../dees-appui-secondarymenu/dees-ap
import type { DeesAppuiMaincontent } from '../dees-appui-maincontent/dees-appui-maincontent.js';
import type { DeesAppuiActivitylog } from '../dees-appui-activitylog/dees-appui-activitylog.js';
import { demoFunc } from './dees-appui-base.demo.js';
import { themeDefaultStyles } from '../../00theme.js';
// View registry for managing views
import { ViewRegistry } from './view.registry.js';
@@ -84,23 +85,23 @@ export class DeesAppuiBase extends DeesElement {
accessor mainmenuGroups: interfaces.IMenuGroup[] = [];
@property({ type: Array })
accessor mainmenuBottomTabs: interfaces.ITab[] = [];
accessor mainmenuBottomTabs: interfaces.IMenuItem[] = [];
@property({ type: Array })
accessor mainmenuTabs: interfaces.ITab[] = [];
accessor mainmenuTabs: interfaces.IMenuItem[] = [];
@property({ type: Object })
accessor mainmenuSelectedTab: interfaces.ITab | undefined = undefined;
accessor mainmenuSelectedTab: interfaces.IMenuItem | undefined = undefined;
// Properties for secondarymenu
@property({ type: String })
accessor secondarymenuHeading: string = '';
@property({ type: Array })
accessor secondarymenuGroups: interfaces.ISecondaryMenuGroup[] = [];
accessor secondarymenuGroups: interfaces.IMenuGroup[] = [];
@property({ type: Object })
accessor secondarymenuSelectedItem: interfaces.ISecondaryMenuItem | undefined = undefined;
accessor secondarymenuSelectedItem: interfaces.IMenuItem | undefined = undefined;
// Collapse states
@property({ type: Boolean })
@@ -111,10 +112,10 @@ export class DeesAppuiBase extends DeesElement {
// Properties for maincontent
@property({ type: Array })
accessor maincontentTabs: interfaces.ITab[] = [];
accessor maincontentTabs: interfaces.IMenuItem[] = [];
@property({ type: Object })
accessor maincontentSelectedTab: interfaces.ITab | undefined = undefined;
accessor maincontentSelectedTab: interfaces.IMenuItem | undefined = undefined;
// References to child components
@state()
@@ -142,8 +143,10 @@ export class DeesAppuiBase extends DeesElement {
private searchCallback: ((query: string) => void) | null = null;
public static styles = [
themeDefaultStyles,
cssManager.defaultStyles,
css`
/* TODO: Migrate hardcoded values to --dees-* CSS variables */
:host {
position: absolute;
height: 100%;
@@ -370,12 +373,12 @@ export class DeesAppuiBase extends DeesElement {
/**
* Add a menu item to a specific group
*/
public addMainMenuItem(groupName: string, tab: interfaces.ITab): void {
public addMainMenuItem(groupName: string, tab: interfaces.IMenuItem): void {
this.mainmenuGroups = this.mainmenuGroups.map(group => {
if (group.name === groupName) {
return {
...group,
tabs: [...(group.tabs || []), tab],
items: [...(group.items || []), tab],
};
}
return group;
@@ -390,7 +393,7 @@ export class DeesAppuiBase extends DeesElement {
if (group.name === groupName) {
return {
...group,
tabs: (group.tabs || []).filter(t => t.key !== tabKey),
items: (group.items || []).filter(t => t.key !== tabKey),
};
}
return group;
@@ -402,7 +405,7 @@ export class DeesAppuiBase extends DeesElement {
*/
public setMainMenuSelection(tabKey: string): void {
for (const group of this.mainmenuGroups) {
const tab = group.tabs?.find(t => t.key === tabKey);
const tab = group.items?.find(t => t.key === tabKey);
if (tab) {
this.mainmenuSelectedTab = tab;
return;
@@ -428,7 +431,7 @@ export class DeesAppuiBase extends DeesElement {
public setMainMenuBadge(tabKey: string, badge: string | number): void {
this.mainmenuGroups = this.mainmenuGroups.map(group => ({
...group,
tabs: (group.tabs || []).map(tab =>
items: (group.items || []).map(tab =>
tab.key === tabKey ? { ...tab, badge } : tab
),
}));
@@ -444,7 +447,7 @@ export class DeesAppuiBase extends DeesElement {
public clearMainMenuBadge(tabKey: string): void {
this.mainmenuGroups = this.mainmenuGroups.map(group => ({
...group,
tabs: (group.tabs || []).map(tab => {
items: (group.items || []).map(tab => {
if (tab.key === tabKey) {
const { badge, ...rest } = tab;
return rest;
@@ -469,7 +472,7 @@ export class DeesAppuiBase extends DeesElement {
/**
* Set the secondary menu configuration
*/
public setSecondaryMenu(config: { heading?: string; groups: interfaces.ISecondaryMenuGroup[] }): void {
public setSecondaryMenu(config: { heading?: string; groups: interfaces.IMenuGroup[] }): void {
if (config.heading !== undefined) {
this.secondarymenuHeading = config.heading;
}
@@ -479,7 +482,7 @@ export class DeesAppuiBase extends DeesElement {
/**
* Update a specific secondary menu group
*/
public updateSecondaryMenuGroup(groupName: string, update: Partial<interfaces.ISecondaryMenuGroup>): void {
public updateSecondaryMenuGroup(groupName: string, update: Partial<interfaces.IMenuGroup>): void {
this.secondarymenuGroups = this.secondarymenuGroups.map(group =>
group.name === groupName ? { ...group, ...update } : group
);
@@ -490,7 +493,7 @@ export class DeesAppuiBase extends DeesElement {
*/
public addSecondaryMenuItem(
groupName: string,
item: interfaces.ISecondaryMenuGroup['items'][0]
item: interfaces.IMenuGroup['items'][0]
): void {
this.secondarymenuGroups = this.secondarymenuGroups.map(group => {
if (group.name === groupName) {
@@ -532,7 +535,7 @@ export class DeesAppuiBase extends DeesElement {
/**
* Set the content tabs
*/
public setContentTabs(tabs: interfaces.ITab[]): void {
public setContentTabs(tabs: interfaces.IMenuItem[]): void {
this.maincontentTabs = [...tabs];
if (tabs.length > 0 && !this.maincontentSelectedTab) {
this.maincontentSelectedTab = tabs[0];
@@ -542,7 +545,7 @@ export class DeesAppuiBase extends DeesElement {
/**
* Add a content tab
*/
public addContentTab(tab: interfaces.ITab): void {
public addContentTab(tab: interfaces.IMenuItem): void {
this.maincontentTabs = [...this.maincontentTabs, tab];
}
@@ -569,7 +572,7 @@ export class DeesAppuiBase extends DeesElement {
/**
* Get the currently selected content tab
*/
public getSelectedContentTab(): interfaces.ITab | undefined {
public getSelectedContentTab(): interfaces.IMenuItem | undefined {
return this.maincontentSelectedTab;
}
@@ -779,7 +782,7 @@ export class DeesAppuiBase extends DeesElement {
return config.mainMenu.sections.map((section) => ({
name: section.name,
tabs: section.views
items: section.views
.map((viewId) => {
const view = this.viewRegistry.get(viewId);
if (!view) {
@@ -791,13 +794,13 @@ export class DeesAppuiBase extends DeesElement {
iconName: view.iconName,
action: () => this.navigateToView(viewId),
badge: view.badge,
} as interfaces.ITab;
} as interfaces.IMenuItem;
})
.filter(Boolean) as interfaces.ITab[],
.filter(Boolean) as interfaces.IMenuItem[],
}));
}
private buildBottomTabsFromItems(items: string[]): interfaces.ITab[] {
private buildBottomTabsFromItems(items: string[]): interfaces.IMenuItem[] {
return items
.map((viewId) => {
const view = this.viewRegistry.get(viewId);
@@ -809,9 +812,9 @@ export class DeesAppuiBase extends DeesElement {
key: view.id,
iconName: view.iconName,
action: () => this.navigateToView(viewId),
} as interfaces.ITab;
} as interfaces.IMenuItem;
})
.filter(Boolean) as interfaces.ITab[];
.filter(Boolean) as interfaces.IMenuItem[];
}
private async loadView(