|
|
|
|
@@ -8,9 +8,11 @@ import {
|
|
|
|
|
cssManager,
|
|
|
|
|
DeesElement,
|
|
|
|
|
} from '@design.estate/dees-element';
|
|
|
|
|
import * as domtools from '@design.estate/dees-domtools';
|
|
|
|
|
import { zIndexRegistry } from '../../00zindex.js';
|
|
|
|
|
import { cssGeistFontFamily } from '../../00fonts.js';
|
|
|
|
|
import { themeDefaultStyles } from '../../00theme.js';
|
|
|
|
|
import { DeesWindowLayer } from '../../00group-overlay/dees-windowlayer/dees-windowlayer.js';
|
|
|
|
|
|
|
|
|
|
declare global {
|
|
|
|
|
interface HTMLElementTagNameMap {
|
|
|
|
|
@@ -47,6 +49,12 @@ export class DeesInputDropdownPopup extends DeesElement {
|
|
|
|
|
@state()
|
|
|
|
|
accessor menuZIndex: number = 1000;
|
|
|
|
|
|
|
|
|
|
@state()
|
|
|
|
|
accessor visible: boolean = false;
|
|
|
|
|
|
|
|
|
|
private windowLayer: DeesWindowLayer | null = null;
|
|
|
|
|
private isDestroying: boolean = false;
|
|
|
|
|
|
|
|
|
|
public static styles = [
|
|
|
|
|
themeDefaultStyles,
|
|
|
|
|
cssManager.defaultStyles,
|
|
|
|
|
@@ -182,7 +190,7 @@ export class DeesInputDropdownPopup extends DeesElement {
|
|
|
|
|
|
|
|
|
|
return html`
|
|
|
|
|
<div
|
|
|
|
|
class="selectionBox show ${this.opensToTop ? 'top' : 'bottom'}"
|
|
|
|
|
class="selectionBox ${this.visible ? 'show' : ''} ${this.opensToTop ? 'top' : 'bottom'}"
|
|
|
|
|
style="${posStyle}; z-index: ${this.menuZIndex};"
|
|
|
|
|
>
|
|
|
|
|
${this.enableSearch
|
|
|
|
|
@@ -233,30 +241,43 @@ export class DeesInputDropdownPopup extends DeesElement {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public show(): void {
|
|
|
|
|
public async show(): Promise<void> {
|
|
|
|
|
this.filteredOptions = this.options;
|
|
|
|
|
this.highlightedIndex = 0;
|
|
|
|
|
this.searchValue = '';
|
|
|
|
|
|
|
|
|
|
// Create window layer (transparent, no blur)
|
|
|
|
|
this.windowLayer = await DeesWindowLayer.createAndShow();
|
|
|
|
|
this.windowLayer.addEventListener('click', () => {
|
|
|
|
|
this.dispatchEvent(new CustomEvent('close-request'));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Set z-index above the window layer
|
|
|
|
|
this.menuZIndex = zIndexRegistry.getNextZIndex();
|
|
|
|
|
zIndexRegistry.register(this, this.menuZIndex);
|
|
|
|
|
this.style.zIndex = this.menuZIndex.toString();
|
|
|
|
|
|
|
|
|
|
document.body.appendChild(this);
|
|
|
|
|
|
|
|
|
|
// Add listeners
|
|
|
|
|
// Animate in on next frame
|
|
|
|
|
await domtools.plugins.smartdelay.delayFor(0);
|
|
|
|
|
this.visible = true;
|
|
|
|
|
|
|
|
|
|
// Add scroll/resize listeners for repositioning
|
|
|
|
|
window.addEventListener('scroll', this.handleScrollOrResize, { capture: true, passive: true });
|
|
|
|
|
window.addEventListener('resize', this.handleScrollOrResize, { passive: true });
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
document.addEventListener('mousedown', this.handleOutsideClick);
|
|
|
|
|
}, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public hide(): void {
|
|
|
|
|
// Remove listeners
|
|
|
|
|
public async hide(): Promise<void> {
|
|
|
|
|
// Guard against double-destruction
|
|
|
|
|
if (this.isDestroying) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.isDestroying = true;
|
|
|
|
|
|
|
|
|
|
// Remove scroll/resize listeners
|
|
|
|
|
window.removeEventListener('scroll', this.handleScrollOrResize, { capture: true } as EventListenerOptions);
|
|
|
|
|
window.removeEventListener('resize', this.handleScrollOrResize);
|
|
|
|
|
document.removeEventListener('mousedown', this.handleOutsideClick);
|
|
|
|
|
|
|
|
|
|
zIndexRegistry.unregister(this);
|
|
|
|
|
|
|
|
|
|
@@ -264,9 +285,21 @@ export class DeesInputDropdownPopup extends DeesElement {
|
|
|
|
|
this.filteredOptions = this.options;
|
|
|
|
|
this.highlightedIndex = 0;
|
|
|
|
|
|
|
|
|
|
// Don't await - let window layer cleanup happen in background for instant visual feedback
|
|
|
|
|
if (this.windowLayer) {
|
|
|
|
|
this.windowLayer.destroy();
|
|
|
|
|
this.windowLayer = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Animate out via CSS transition
|
|
|
|
|
this.visible = false;
|
|
|
|
|
await domtools.plugins.smartdelay.delayFor(150);
|
|
|
|
|
|
|
|
|
|
if (this.parentElement) {
|
|
|
|
|
this.parentElement.removeChild(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.isDestroying = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async focusSearchInput(): Promise<void> {
|
|
|
|
|
@@ -328,13 +361,6 @@ export class DeesInputDropdownPopup extends DeesElement {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private handleOutsideClick = (event: MouseEvent): void => {
|
|
|
|
|
const path = event.composedPath();
|
|
|
|
|
if (!path.includes(this) && (!this.ownerComponent || !path.includes(this.ownerComponent))) {
|
|
|
|
|
this.dispatchEvent(new CustomEvent('close-request'));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private handleScrollOrResize = (): void => {
|
|
|
|
|
this.dispatchEvent(new CustomEvent('reposition-request'));
|
|
|
|
|
};
|
|
|
|
|
@@ -343,7 +369,6 @@ export class DeesInputDropdownPopup extends DeesElement {
|
|
|
|
|
await super.disconnectedCallback();
|
|
|
|
|
window.removeEventListener('scroll', this.handleScrollOrResize, { capture: true } as EventListenerOptions);
|
|
|
|
|
window.removeEventListener('resize', this.handleScrollOrResize);
|
|
|
|
|
document.removeEventListener('mousedown', this.handleOutsideClick);
|
|
|
|
|
zIndexRegistry.unregister(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|