feat(dees-contextmenu,dees-appui-tabs,test): Prevent double-destruction of context menus, await window layer teardown, update destroyAll behavior, remove tabs content slot, and adjust tests
This commit is contained in:
10
changelog.md
10
changelog.md
@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-12-29 - 3.7.0 - feat(dees-contextmenu,dees-appui-tabs,test)
|
||||
Prevent double-destruction of context menus, await window layer teardown, update destroyAll behavior, remove tabs content slot, and adjust tests
|
||||
|
||||
- Add isDestroying guard in DeesContextmenu.destroy to avoid double-destruction.
|
||||
- Await windowLayer.destroy() to ensure the window layer is fully torn down before continuing.
|
||||
- Ensure submenu timeouts are cleared and submenu.destroy() is awaited during teardown.
|
||||
- Change destroyAll to locate the root/top-level menu and destroy from the root to cascade teardown reliably.
|
||||
- Remove the .content wrapper and the <slot> output from dees-appui-tabs (demo updated to render content outside the component) — this is a breaking change to the tabs API (slotted content no longer rendered).
|
||||
- Increase test timeout in test.contextmenu-nested-close.browser.ts to 600ms to account for ~300ms windowLayer destruction + ~100ms context menu delay.
|
||||
|
||||
## 2025-12-29 - 3.6.1 - fix(readme)
|
||||
document new App UI APIs to control main/secondary menu and content tabs visibility
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@ tap.test('should close all parent menus when clicking action in nested submenu',
|
||||
expect(childItem).toBeTruthy();
|
||||
childItem!.click();
|
||||
|
||||
// Wait for menus to close
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
// Wait for menus to close (windowLayer destruction takes 300ms + context menu 100ms)
|
||||
await new Promise(resolve => setTimeout(resolve, 600));
|
||||
|
||||
// Verify action was called
|
||||
expect(actionCalled).toEqual(true);
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@design.estate/dees-catalog',
|
||||
version: '3.6.1',
|
||||
version: '3.7.0',
|
||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||
}
|
||||
|
||||
@@ -67,9 +67,8 @@ export const demoFunc = () => {
|
||||
<div class="demo-container">
|
||||
<div class="section">
|
||||
<div class="section-title">Horizontal Tabs with Animated Indicator</div>
|
||||
<dees-appui-tabs .tabs=${horizontalTabs}>
|
||||
${demoContent('Select a tab to see the smooth sliding animation of the indicator. The indicator automatically adjusts its width to match the tab content with minimal padding.')}
|
||||
</dees-appui-tabs>
|
||||
<dees-appui-tabs .tabs=${horizontalTabs}></dees-appui-tabs>
|
||||
${demoContent('Select a tab to see the smooth sliding animation of the indicator. The indicator automatically adjusts its width to match the tab content with minimal padding.')}
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
@@ -82,9 +81,8 @@ export const demoFunc = () => {
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Without Indicator</div>
|
||||
<dees-appui-tabs .showTabIndicator=${false} .tabs=${noIndicatorTabs}>
|
||||
${demoContent('Tabs can also be used without the animated indicator by setting showTabIndicator to false.')}
|
||||
</dees-appui-tabs>
|
||||
<dees-appui-tabs .showTabIndicator=${false} .tabs=${noIndicatorTabs}></dees-appui-tabs>
|
||||
${demoContent('Tabs can also be used without the animated indicator by setting showTabIndicator to false.')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -198,19 +198,12 @@ export class DeesAppuiTabs extends DeesElement {
|
||||
z-index: 1;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 32px 24px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
${this.renderTabsWrapper()}
|
||||
<div class="content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ export class DeesContextmenu extends DeesElement {
|
||||
private submenu: DeesContextmenu | null = null;
|
||||
private submenuTimeout: any = null;
|
||||
private parentMenu: DeesContextmenu | null = null;
|
||||
private isDestroying: boolean = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -416,6 +417,12 @@ export class DeesContextmenu extends DeesElement {
|
||||
}
|
||||
|
||||
public async destroy() {
|
||||
// Guard against double-destruction
|
||||
if (this.isDestroying) {
|
||||
return;
|
||||
}
|
||||
this.isDestroying = true;
|
||||
|
||||
// Clear timeout
|
||||
if (this.submenuTimeout) {
|
||||
clearTimeout(this.submenuTimeout);
|
||||
@@ -430,7 +437,7 @@ export class DeesContextmenu extends DeesElement {
|
||||
|
||||
// Only destroy window layer if this is not a submenu
|
||||
if (this.windowLayer && !this.parentMenu) {
|
||||
this.windowLayer.destroy();
|
||||
await this.windowLayer.destroy();
|
||||
}
|
||||
|
||||
this.style.opacity = '0';
|
||||
@@ -446,13 +453,14 @@ export class DeesContextmenu extends DeesElement {
|
||||
* Destroys this menu and all parent menus in the chain
|
||||
*/
|
||||
public async destroyAll() {
|
||||
// First destroy parent menus if they exist
|
||||
if (this.parentMenu) {
|
||||
await this.parentMenu.destroyAll();
|
||||
} else {
|
||||
// If we're at the top level, just destroy this menu
|
||||
await this.destroy();
|
||||
// Find the root menu (top-level parent)
|
||||
let rootMenu: DeesContextmenu = this;
|
||||
while (rootMenu.parentMenu) {
|
||||
rootMenu = rootMenu.parentMenu;
|
||||
}
|
||||
|
||||
// Destroy from the root - this will cascade through all submenus
|
||||
await rootMenu.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user