diff --git a/ts_web/elements/00zindex.ts b/ts_web/elements/00zindex.ts index d357a74..b9ddcca 100644 --- a/ts_web/elements/00zindex.ts +++ b/ts_web/elements/00zindex.ts @@ -56,4 +56,106 @@ export const componentZIndex = { 'dees-mobilenavigation': zIndexLayers.fixed.mobileNav, 'dees-slash-menu': zIndexLayers.wysiwygMenus, 'dees-formatting-menu': zIndexLayers.wysiwygMenus, -} as const; \ No newline at end of file +} 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(); + private elementZIndexMap = new WeakMap(); + 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(); \ No newline at end of file diff --git a/ts_web/elements/dees-input-dropdown.ts b/ts_web/elements/dees-input-dropdown.ts index 590a379..4b326b3 100644 --- a/ts_web/elements/dees-input-dropdown.ts +++ b/ts_web/elements/dees-input-dropdown.ts @@ -280,6 +280,11 @@ export class DeesInputDropdown extends DeesInputBase { elevatedDropdown.style.top = this.getBoundingClientRect().top + 'px'; elevatedDropdown.style.left = this.getBoundingClientRect().left + 'px'; elevatedDropdown.style.width = this.clientWidth + 'px'; + + // Get z-index from registry for the elevated dropdown + const dropdownZIndex = (await import('./00zindex.js')).zIndexRegistry.getNextZIndex(); + elevatedDropdown.style.zIndex = dropdownZIndex.toString(); + (await import('./00zindex.js')).zIndexRegistry.register(elevatedDropdown, dropdownZIndex); elevatedDropdown.options = this.options; elevatedDropdown.selectedOption = this.selectedOption; elevatedDropdown.highlightedIndex = elevatedDropdown.selectedOption ? elevatedDropdown.options.indexOf( @@ -296,9 +301,13 @@ export class DeesInputDropdown extends DeesInputBase { '0'; elevatedDropdown.removeEventListener('selectedOption', handleSelection); this.windowOverlay.removeEventListener('clicked', destroyOverlay); + + // Unregister elevated dropdown from z-index registry + (await import('./00zindex.js')).zIndexRegistry.unregister(elevatedDropdown); + this.windowOverlay.destroy(); }; - const handleSelection = async (event) => { + const handleSelection = async () => { await this.updateSelection(elevatedDropdown.selectedOption); destroyOverlay(); }; @@ -323,10 +332,20 @@ export class DeesInputDropdown extends DeesInputBase { await domtoolsInstance.convenience.smartdelay.delayFor(0); const searchInput = selectionBox.querySelector('input'); searchInput?.focus(); + + // Get z-index from registry for the selection box + const selectionBoxZIndex = (await import('./00zindex.js')).zIndexRegistry.getNextZIndex(); + selectionBox.style.zIndex = selectionBoxZIndex.toString(); + (await import('./00zindex.js')).zIndexRegistry.register(selectionBox as HTMLElement, selectionBoxZIndex); + selectionBox.classList.add('show'); } else { selectedBox.style.pointerEvents = 'none'; selectionBox.classList.remove('show'); + + // Unregister selection box from z-index registry + (await import('./00zindex.js')).zIndexRegistry.unregister(selectionBox as HTMLElement); + // selectedBox.style.opacity = '0'; } } diff --git a/ts_web/elements/dees-modal.ts b/ts_web/elements/dees-modal.ts index 2b3d736..3d70c3e 100644 --- a/ts_web/elements/dees-modal.ts +++ b/ts_web/elements/dees-modal.ts @@ -1,6 +1,6 @@ import * as colors from './00colors.js'; import * as plugins from './00plugins.js'; -import { zIndexLayers } from './00zindex.js'; +import { zIndexLayers, zIndexRegistry } from './00zindex.js'; import { demoFunc } from './dees-modal.demo.js'; import { @@ -62,6 +62,11 @@ export class DeesModal extends DeesElement { }); body.append(modal.windowLayer); body.append(modal); + + // Get z-index for modal (should be above window layer) + modal.modalZIndex = zIndexRegistry.getNextZIndex(); + zIndexRegistry.register(modal, modal.modalZIndex); + return modal; } @@ -95,6 +100,9 @@ export class DeesModal extends DeesElement { @property({ attribute: false }) public onHelp: () => void | Promise; + + @state() + private modalZIndex: number = 1000; constructor() { super(); @@ -118,7 +126,6 @@ export class DeesModal extends DeesElement { box-sizing: border-box; align-items: center; justify-content: center; - z-index: ${zIndexLayers.overlay.modal}; } .modal { will-change: transform; @@ -291,7 +298,7 @@ export class DeesModal extends DeesElement { ${maxWidthStyle ? `.modal { max-width: ${maxWidthStyle}; }` : ''} ${minWidthStyle ? `.modal { min-width: ${minWidthStyle}; }` : ''} -
+