161 lines
4.5 KiB
TypeScript
161 lines
4.5 KiB
TypeScript
/**
|
|
* Central z-index management for consistent stacking order
|
|
* Higher numbers appear on top of lower numbers
|
|
*/
|
|
|
|
export const zIndexLayers = {
|
|
// Base layer: Regular content
|
|
base: {
|
|
content: 'auto',
|
|
inputElements: 1,
|
|
},
|
|
|
|
// Fixed UI elements
|
|
fixed: {
|
|
appBar: 10,
|
|
sideMenu: 10,
|
|
mobileNav: 250,
|
|
},
|
|
|
|
// Overlay backdrops (semi-transparent backgrounds)
|
|
backdrop: {
|
|
dropdown: 1999, // Below modals but above fixed elements
|
|
modal: 2999, // Below dropdowns on modals
|
|
contextMenu: 3999, // Below critical overlays
|
|
},
|
|
|
|
// Interactive overlays
|
|
overlay: {
|
|
dropdown: 2000, // Dropdowns and select menus
|
|
modal: 3000, // Modal dialogs
|
|
contextMenu: 4000, // Context menus and tooltips
|
|
toast: 5000, // Toast notifications (highest priority)
|
|
},
|
|
|
|
// Special cases for nested elements
|
|
modalDropdown: 3500, // Dropdowns inside modals
|
|
wysiwygMenus: 4500, // Editor formatting menus
|
|
} as const;
|
|
|
|
// Helper function to get z-index value
|
|
export function getZIndex(category: keyof typeof zIndexLayers, subcategory?: string): number | string {
|
|
const categoryObj = zIndexLayers[category];
|
|
if (typeof categoryObj === 'object' && subcategory) {
|
|
return categoryObj[subcategory as keyof typeof categoryObj] || 'auto';
|
|
}
|
|
return typeof categoryObj === 'number' ? categoryObj : 'auto';
|
|
}
|
|
|
|
// Z-index assignments for components
|
|
export const componentZIndex = {
|
|
'dees-modal': zIndexLayers.overlay.modal,
|
|
'dees-windowlayer': zIndexLayers.overlay.dropdown,
|
|
'dees-contextmenu': zIndexLayers.overlay.contextMenu,
|
|
'dees-toast': zIndexLayers.overlay.toast,
|
|
'dees-appui-mainmenu': zIndexLayers.fixed.appBar,
|
|
'dees-mobilenavigation': zIndexLayers.fixed.mobileNav,
|
|
'dees-slash-menu': zIndexLayers.wysiwygMenus,
|
|
'dees-formatting-menu': zIndexLayers.wysiwygMenus,
|
|
} as const;
|
|
|
|
/**
|
|
* Z-Index Registry for managing stacked elements
|
|
* Simple incremental z-index assignment based on creation order
|
|
*/
|
|
export class ZIndexRegistry {
|
|
private static instance: ZIndexRegistry;
|
|
private activeElements = new Set<HTMLElement>();
|
|
private elementZIndexMap = new WeakMap<HTMLElement, number>();
|
|
private currentZIndex = 1000; // Starting z-index
|
|
|
|
private constructor() {}
|
|
|
|
public static getInstance(): ZIndexRegistry {
|
|
if (!ZIndexRegistry.instance) {
|
|
ZIndexRegistry.instance = new ZIndexRegistry();
|
|
}
|
|
return ZIndexRegistry.instance;
|
|
}
|
|
|
|
/**
|
|
* Get the next available z-index
|
|
* @returns The next available z-index
|
|
*/
|
|
public getNextZIndex(): number {
|
|
this.currentZIndex += 10;
|
|
return this.currentZIndex;
|
|
}
|
|
|
|
/**
|
|
* Register an element with the z-index registry
|
|
* @param element - The HTML element to register
|
|
* @param zIndex - The z-index assigned to this element
|
|
*/
|
|
public register(element: HTMLElement, zIndex: number): void {
|
|
this.activeElements.add(element);
|
|
this.elementZIndexMap.set(element, zIndex);
|
|
}
|
|
|
|
/**
|
|
* Unregister an element from the z-index registry
|
|
* @param element - The HTML element to unregister
|
|
*/
|
|
public unregister(element: HTMLElement): void {
|
|
this.activeElements.delete(element);
|
|
this.elementZIndexMap.delete(element);
|
|
|
|
// If no more active elements, reset counter to base
|
|
if (this.activeElements.size === 0) {
|
|
this.currentZIndex = 1000;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the z-index for a specific element
|
|
* @param element - The HTML element
|
|
* @returns The z-index or undefined if not registered
|
|
*/
|
|
public getElementZIndex(element: HTMLElement): number | undefined {
|
|
return this.elementZIndexMap.get(element);
|
|
}
|
|
|
|
/**
|
|
* Get count of active elements
|
|
* @returns Number of active elements
|
|
*/
|
|
public getActiveCount(): number {
|
|
return this.activeElements.size;
|
|
}
|
|
|
|
/**
|
|
* Get the current highest z-index
|
|
* @returns The current z-index value
|
|
*/
|
|
public getCurrentZIndex(): number {
|
|
return this.currentZIndex;
|
|
}
|
|
|
|
/**
|
|
* Clear all registrations (useful for testing)
|
|
*/
|
|
public clear(): void {
|
|
this.activeElements.clear();
|
|
this.elementZIndexMap = new WeakMap();
|
|
this.currentZIndex = 1000;
|
|
}
|
|
|
|
/**
|
|
* Get all active elements in z-index order
|
|
* @returns Array of elements sorted by z-index
|
|
*/
|
|
public getActiveElementsInOrder(): HTMLElement[] {
|
|
return Array.from(this.activeElements).sort((a, b) => {
|
|
const aZ = this.elementZIndexMap.get(a) || 0;
|
|
const bZ = this.elementZIndexMap.get(b) || 0;
|
|
return aZ - bZ;
|
|
});
|
|
}
|
|
}
|
|
|
|
// Export singleton instance for convenience
|
|
export const zIndexRegistry = ZIndexRegistry.getInstance(); |