fix(properties): enhance element detection in properties panel with recursive search and retry mechanism
This commit is contained in:
		| @@ -3,12 +3,14 @@ | ||||
|   "version": "1.0.90", | ||||
|   "private": false, | ||||
|   "description": "A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.", | ||||
|   "main": "dist_ts_web/index.js", | ||||
|   "typings": "dist_ts_web/index.d.ts", | ||||
|   "exports": { | ||||
|     ".": "./dist_ts_web/index.js", | ||||
|     "./demoTools": "./dist_ts_demotools" | ||||
|   }, | ||||
|   "type": "module", | ||||
|   "scripts": { | ||||
|     "test": "(npm run build)", | ||||
|     "build": "(tsbuild element --web --allowimplicitany && tsbundle element)", | ||||
|     "build": "(tsbuild tsfolders --allowimplicitany && tsbundle element)", | ||||
|     "watch": "tswatch element", | ||||
|     "buildDocs": "tsdoc" | ||||
|   }, | ||||
|   | ||||
| @@ -1 +1,24 @@ | ||||
|   | ||||
| # Project Hints and Findings | ||||
|  | ||||
| ## Properties Panel Element Detection Issue (Fixed) | ||||
|  | ||||
| ### Problem | ||||
| The properties panel had timing issues detecting rendered elements because: | ||||
| 1. Elements are rendered asynchronously via lit's `render()` function in the dashboard component | ||||
| 2. The properties panel tried to find elements immediately without waiting for render completion | ||||
| 3. Element search only looked at direct children of the viewport, missing nested elements or those inside shadow DOM | ||||
|  | ||||
| ### Solution Implemented | ||||
| 1. Added a 100ms initial delay to allow render completion | ||||
| 2. Implemented recursive element search that: | ||||
|    - Searches through nested children up to 5 levels deep | ||||
|    - Checks shadow roots of elements | ||||
|    - Handles complex DOM structures | ||||
| 3. Added retry mechanism with up to 5 attempts (200ms between retries) | ||||
| 4. Improved error messages to show retry count | ||||
|  | ||||
| ### Code Flow | ||||
| 1. Dashboard renders element demo into viewport using `render(anonItem.demo(), viewport)` | ||||
| 2. Properties panel waits, then searches recursively for the element instance | ||||
| 3. If not found, retries with delays to handle async rendering | ||||
| 4. Once found, extracts and displays element properties | ||||
							
								
								
									
										30
									
								
								readme.plan.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								readme.plan.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| # Fix Properties Panel Element Detection | ||||
|  | ||||
| To fix the element detection issue, reread CLAUDE.md first. | ||||
|  | ||||
| ## Problem Analysis | ||||
| The properties panel has timing issues detecting rendered elements because: | ||||
| 1. Elements are rendered asynchronously via lit's `render()` in the dashboard | ||||
| 2. Properties panel tries to find elements immediately without waiting for render completion | ||||
| 3. Element search only looks at direct children, missing nested/shadow DOM elements | ||||
|  | ||||
| ## Implementation Plan | ||||
|  | ||||
| ### 1. Add proper synchronization | ||||
| - Add a delay or await render completion before element detection | ||||
| - Use MutationObserver or lit's updateComplete promises | ||||
|  | ||||
| ### 2. Improve element search algorithm | ||||
| - Search recursively through all descendants, not just direct children | ||||
| - Handle shadow DOM boundaries properly | ||||
| - Support elements wrapped in containers | ||||
|  | ||||
| ### 3. Add retry mechanism | ||||
| - If element not found, retry after a delay | ||||
| - Add maximum retry attempts to prevent infinite loops | ||||
| - Clear error state when element is eventually found | ||||
|  | ||||
| ## Code Changes Required | ||||
| 1. Modify `wcc-properties.ts` createProperties() method | ||||
| 2. Add element search utility function | ||||
| 3. Improve error handling and user feedback | ||||
							
								
								
									
										0
									
								
								ts_demotools/demotools.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								ts_demotools/demotools.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								ts_demotools/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								ts_demotools/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								ts_demotools/plugins.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ts_demotools/plugins.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| import {} from '@design.estate/dees-element'; | ||||
| @@ -226,6 +226,31 @@ export class WccProperties extends DeesElement { | ||||
|     `; | ||||
|   } | ||||
|  | ||||
|   private async findElementRecursively(container: Element, elementClass: any, maxDepth: number = 5): Promise<HTMLElement | null> { | ||||
|     if (maxDepth <= 0) return null; | ||||
|      | ||||
|     // Check direct children | ||||
|     for (const child of Array.from(container.children)) { | ||||
|       if (child instanceof elementClass) { | ||||
|         return child as HTMLElement; | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     // Check shadow roots of children | ||||
|     for (const child of Array.from(container.children)) { | ||||
|       if (child.shadowRoot) { | ||||
|         const found = await this.findElementRecursively(child.shadowRoot as any, elementClass, maxDepth - 1); | ||||
|         if (found) return found; | ||||
|       } | ||||
|        | ||||
|       // Also check nested children | ||||
|       const found = await this.findElementRecursively(child, elementClass, maxDepth - 1); | ||||
|       if (found) return found; | ||||
|     } | ||||
|      | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   public async createProperties() { | ||||
|     console.log('creating properties for:'); | ||||
|     console.log(this.selectedItem); | ||||
| @@ -275,15 +300,30 @@ export class WccProperties extends DeesElement { | ||||
|       } | ||||
|       console.log(anonItem.elementProperties); | ||||
|       const wccFrame = await this.dashboardRef.wccFrame; | ||||
|       let firstFoundInstantiatedElement: HTMLElement; | ||||
|       for (const element of Array.from((await wccFrame.getViewportElement()).children)) { | ||||
|         if (element instanceof (this.selectedItem as any)) { | ||||
|           firstFoundInstantiatedElement = element as HTMLElement; | ||||
|           break; | ||||
|         } | ||||
|        | ||||
|       // Wait for render to complete | ||||
|       await new Promise(resolve => setTimeout(resolve, 100)); | ||||
|        | ||||
|       // Try to find the element with recursive search | ||||
|       const viewport = await wccFrame.getViewportElement(); | ||||
|       let firstFoundInstantiatedElement: HTMLElement = await this.findElementRecursively( | ||||
|         viewport,  | ||||
|         this.selectedItem as any | ||||
|       ); | ||||
|        | ||||
|       // Retry logic if element not found | ||||
|       let retries = 0; | ||||
|       while (!firstFoundInstantiatedElement && retries < 5) { | ||||
|         await new Promise(resolve => setTimeout(resolve, 200)); | ||||
|         firstFoundInstantiatedElement = await this.findElementRecursively( | ||||
|           viewport, | ||||
|           this.selectedItem as any | ||||
|         ); | ||||
|         retries++; | ||||
|       } | ||||
|        | ||||
|       if (!firstFoundInstantiatedElement) { | ||||
|         this.warning = `no first instantiated element found for >>${anonItem.name}<<`; | ||||
|         this.warning = `no first instantiated element found for >>${anonItem.name}<< after ${retries} retries`; | ||||
|         return; | ||||
|       } | ||||
|       const classProperties: Map<string, any> = anonItem.elementProperties; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user