feat(dees-appui-base): Add unified App UI API to dees-appui-base with ViewRegistry, AppRouter and StateManager
This commit is contained in:
167
ts_web/elements/00group-appui/dees-appui-base/view.registry.ts
Normal file
167
ts_web/elements/00group-appui/dees-appui-base/view.registry.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import { html, render, type TemplateResult } from '@design.estate/dees-element';
|
||||
import type { IViewDefinition } from '../../interfaces/appconfig.js';
|
||||
|
||||
/**
|
||||
* Registry for managing views and their lifecycle
|
||||
*/
|
||||
export class ViewRegistry {
|
||||
private views: Map<string, IViewDefinition> = new Map();
|
||||
private instances: Map<string, HTMLElement> = new Map();
|
||||
private currentViewId: string | null = null;
|
||||
|
||||
/**
|
||||
* Register a single view
|
||||
*/
|
||||
public register(view: IViewDefinition): void {
|
||||
if (this.views.has(view.id)) {
|
||||
console.warn(`View with id "${view.id}" already registered. Overwriting.`);
|
||||
}
|
||||
this.views.set(view.id, view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register multiple views
|
||||
*/
|
||||
public registerAll(views: IViewDefinition[]): void {
|
||||
views.forEach((view) => this.register(view));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a view definition by ID
|
||||
*/
|
||||
public get(viewId: string): IViewDefinition | undefined {
|
||||
return this.views.get(viewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all registered view IDs
|
||||
*/
|
||||
public getViewIds(): string[] {
|
||||
return Array.from(this.views.keys());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all views
|
||||
*/
|
||||
public getAll(): IViewDefinition[] {
|
||||
return Array.from(this.views.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get route for a view
|
||||
*/
|
||||
public getRoute(viewId: string): string {
|
||||
const view = this.views.get(viewId);
|
||||
return view?.route || view?.id || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Find view by route
|
||||
*/
|
||||
public findByRoute(route: string): IViewDefinition | undefined {
|
||||
for (const view of this.views.values()) {
|
||||
const viewRoute = view.route || view.id;
|
||||
if (viewRoute === route) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a view's content into a container
|
||||
*/
|
||||
public renderView(viewId: string, container: HTMLElement): HTMLElement | null {
|
||||
const view = this.views.get(viewId);
|
||||
if (!view) {
|
||||
console.error(`View "${viewId}" not found in registry`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Clear container
|
||||
container.innerHTML = '';
|
||||
|
||||
let element: HTMLElement;
|
||||
|
||||
if (typeof view.content === 'string') {
|
||||
// Tag name string
|
||||
element = document.createElement(view.content);
|
||||
} else if (typeof view.content === 'function') {
|
||||
// Check if it's a class constructor or template function
|
||||
if (view.content.prototype instanceof HTMLElement) {
|
||||
// Element class constructor
|
||||
element = new (view.content as new () => HTMLElement)();
|
||||
} else {
|
||||
// Template function - wrap in a container and use Lit's render
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'view-content-wrapper';
|
||||
wrapper.style.cssText = 'display: contents;';
|
||||
const template = (view.content as () => TemplateResult)();
|
||||
render(template, wrapper);
|
||||
element = wrapper;
|
||||
}
|
||||
} else {
|
||||
console.error(`Invalid content type for view "${viewId}"`);
|
||||
return null;
|
||||
}
|
||||
|
||||
container.appendChild(element);
|
||||
this.instances.set(viewId, element);
|
||||
this.currentViewId = viewId;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get currently active view ID
|
||||
*/
|
||||
public getCurrentViewId(): string | null {
|
||||
return this.currentViewId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached instance of a view
|
||||
*/
|
||||
public getInstance(viewId: string): HTMLElement | undefined {
|
||||
return this.instances.get(viewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all instances
|
||||
*/
|
||||
public clearInstances(): void {
|
||||
this.instances.clear();
|
||||
this.currentViewId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a view
|
||||
*/
|
||||
public unregister(viewId: string): boolean {
|
||||
this.instances.delete(viewId);
|
||||
return this.views.delete(viewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the registry
|
||||
*/
|
||||
public clear(): void {
|
||||
this.views.clear();
|
||||
this.instances.clear();
|
||||
this.currentViewId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a view is registered
|
||||
*/
|
||||
public has(viewId: string): boolean {
|
||||
return this.views.has(viewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of registered views
|
||||
*/
|
||||
public get size(): number {
|
||||
return this.views.size;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user