update
This commit is contained in:
		| @@ -65,26 +65,42 @@ Implemented an advanced editor for complex properties (Arrays and Objects) that | ||||
|  | ||||
| ### Features | ||||
| 1. **Dynamic Layout**: Frame shrinks by 300px from bottom when editor opens | ||||
| 2. **JSON Editor**:  | ||||
| 2. **Multiple Editors**: Can edit multiple properties simultaneously side by side | ||||
| 3. **JSON Editor**:  | ||||
|    - Monospace font for code editing | ||||
|    - Tab key support for indentation | ||||
|    - Syntax validation with error messages | ||||
|    - Live preview of changes | ||||
| 3. **Smooth Transitions**: Animated opening/closing with 0.3s ease | ||||
| 4. **Error Handling**: Invalid JSON shows clear error messages that disappear on typing | ||||
| 4. **Smooth Transitions**: Animated opening/closing with 0.3s ease | ||||
| 5. **Error Handling**: Invalid JSON shows clear error messages that disappear on typing | ||||
| 6. **Close All Button**: Single button to close all open editors at once | ||||
|  | ||||
| ### Technical Implementation | ||||
| - **State Management**: Added showAdvancedEditor, editingProperty, editorValue, editorError states | ||||
| ### Technical Implementation (Updated) | ||||
| - **State Management**: Changed from single editor to array of editors with unique IDs | ||||
| - **Editor Structure**: Each editor instance contains: | ||||
|   - `id`: Unique identifier (`propertyName-timestamp`) | ||||
|   - `name`: Property name | ||||
|   - `value`: Original value | ||||
|   - `element`: Reference to the element | ||||
|   - `editorValue`: Current JSON string | ||||
|   - `editorError`: Validation error message | ||||
| - **Event System**: Uses custom 'editorStateChanged' event to communicate with parent dashboard | ||||
| - **Dynamic Styling**: wcc-frame's bottom position changes from 100px to 400px when editor is open | ||||
| - **Dynamic Styling**: wcc-frame's bottom position changes from 100px to 400px when any editor is open | ||||
| - **Property Types**: Object and Array properties show "Edit Object/Array" button instead of inline controls | ||||
|  | ||||
| ### User Flow | ||||
| 1. Click "Edit Object/Array" button on complex property | ||||
| 2. Editor slides up between properties panel and frame | ||||
| 3. Edit JSON with live validation | ||||
| 4. Save applies changes and refreshes properties, Cancel discards changes | ||||
| 5. Frame automatically resizes back when editor closes | ||||
| 3. Click additional "Edit" buttons to open more properties side by side | ||||
| 4. Each editor can be saved/cancelled independently | ||||
| 5. "Close All" button dismisses all editors at once | ||||
| 6. Frame automatically resizes back when all editors are closed | ||||
|  | ||||
| ### Layout Details | ||||
| - **Container**: Flexbox with horizontal scrolling when multiple editors overflow | ||||
| - **Editor Width**: Min 300px, max 500px, flexible between | ||||
| - **Scrollbar**: Custom styled thin scrollbar for horizontal overflow | ||||
| - **Header Bar**: Fixed top bar with "Property Editors" title and "Close All" button | ||||
|  | ||||
| ## Properties Panel Element Detection Issue (Fixed) | ||||
|  | ||||
|   | ||||
| @@ -35,16 +35,14 @@ export class WccProperties extends DeesElement { | ||||
|   propertyContent: TemplateResult[] = []; | ||||
|  | ||||
|   @state() | ||||
|   showAdvancedEditor: boolean = false; | ||||
|  | ||||
|   @state() | ||||
|   editingProperty: { name: string; value: any; element: HTMLElement } = null; | ||||
|  | ||||
|   @state() | ||||
|   editorValue: string = ''; | ||||
|  | ||||
|   @state() | ||||
|   editorError: string = ''; | ||||
|   editingProperties: Array<{ | ||||
|     id: string; | ||||
|     name: string; | ||||
|     value: any; | ||||
|     element: HTMLElement; | ||||
|     editorValue: string; | ||||
|     editorError: string; | ||||
|   }> = []; | ||||
|  | ||||
|   public editorHeight: number = 300; | ||||
|  | ||||
| @@ -76,7 +74,7 @@ export class WccProperties extends DeesElement { | ||||
|           box-sizing: border-box; | ||||
|           position: absolute; | ||||
|           left: 200px; | ||||
|           height: ${this.showAdvancedEditor ? 100 + this.editorHeight : 100}px; | ||||
|           height: ${this.editingProperties.length > 0 ? 100 + this.editorHeight : 100}px; | ||||
|           bottom: 0px; | ||||
|           right: 0px; | ||||
|           overflow: hidden; | ||||
| @@ -286,99 +284,244 @@ export class WccProperties extends DeesElement { | ||||
|           backdrop-filter: blur(8px); | ||||
|         } | ||||
|  | ||||
|         .advanced-editor { | ||||
|         .advanced-editor-container { | ||||
|           position: absolute; | ||||
|           left: 0; | ||||
|           right: 0; | ||||
|           top: 0; | ||||
|           height: ${this.editorHeight}px; | ||||
|           background: var(--background); | ||||
|           border-bottom: 1px solid rgba(255, 255, 255, 0.08); | ||||
|           background: #050505; | ||||
|           border-bottom: 1px solid rgba(255, 255, 255, 0.1); | ||||
|           display: flex; | ||||
|           flex-direction: column; | ||||
|           transition: all 0.3s ease; | ||||
|           transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | ||||
|           box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2); | ||||
|         } | ||||
|  | ||||
|         .editor-header { | ||||
|           padding: 0.75rem 1rem; | ||||
|           background: rgba(59, 130, 246, 0.03); | ||||
|           border-bottom: 1px solid var(--border); | ||||
|         .editor-header-bar { | ||||
|           padding: 0.75rem 1.25rem; | ||||
|           background: linear-gradient(to bottom, rgba(59, 130, 246, 0.05), transparent); | ||||
|           border-bottom: 1px solid rgba(59, 130, 246, 0.1); | ||||
|           display: flex; | ||||
|           justify-content: space-between; | ||||
|           align-items: center; | ||||
|           height: 48px; | ||||
|           backdrop-filter: blur(8px); | ||||
|         } | ||||
|  | ||||
|         .editor-header-title { | ||||
|           font-size: 0.875rem; | ||||
|           font-weight: 600; | ||||
|           color: var(--foreground); | ||||
|           text-transform: uppercase; | ||||
|           letter-spacing: 0.1em; | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           gap: 0.5rem; | ||||
|         } | ||||
|  | ||||
|         .editor-header-title::before { | ||||
|           content: ''; | ||||
|           display: inline-block; | ||||
|           width: 3px; | ||||
|           height: 16px; | ||||
|           background: var(--primary); | ||||
|           border-radius: 1px; | ||||
|         } | ||||
|  | ||||
|         .editor-close-all { | ||||
|           padding: 0.375rem 0.75rem; | ||||
|           background: rgba(239, 68, 68, 0.05); | ||||
|           border: 1px solid rgba(239, 68, 68, 0.2); | ||||
|           border-radius: var(--radius); | ||||
|           color: #f87171; | ||||
|           font-size: 0.75rem; | ||||
|           font-weight: 500; | ||||
|           cursor: pointer; | ||||
|           transition: all 0.15s ease; | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           gap: 0.375rem; | ||||
|         } | ||||
|  | ||||
|         .editor-close-all:hover { | ||||
|           background: rgba(239, 68, 68, 0.15); | ||||
|           border-color: rgba(239, 68, 68, 0.4); | ||||
|           transform: translateY(-1px); | ||||
|           box-shadow: 0 2px 4px rgba(239, 68, 68, 0.2); | ||||
|         } | ||||
|  | ||||
|         .editor-close-all::before { | ||||
|           content: '×'; | ||||
|           font-size: 1.125rem; | ||||
|           line-height: 1; | ||||
|         } | ||||
|  | ||||
|         .editors-container { | ||||
|           flex: 1; | ||||
|           display: flex; | ||||
|           overflow-x: auto; | ||||
|           overflow-y: hidden; | ||||
|           gap: 0; | ||||
|           background: rgba(255, 255, 255, 0.02); | ||||
|           padding: 0.75rem; | ||||
|         } | ||||
|  | ||||
|         .editors-container::-webkit-scrollbar { | ||||
|           height: 8px; | ||||
|         } | ||||
|  | ||||
|         .editors-container::-webkit-scrollbar-track { | ||||
|           background: rgba(255, 255, 255, 0.02); | ||||
|           border-radius: 4px; | ||||
|         } | ||||
|  | ||||
|         .editors-container::-webkit-scrollbar-thumb { | ||||
|           background: rgba(255, 255, 255, 0.08); | ||||
|           border-radius: 4px; | ||||
|         } | ||||
|  | ||||
|         .editors-container::-webkit-scrollbar-thumb:hover { | ||||
|           background: rgba(255, 255, 255, 0.12); | ||||
|         } | ||||
|  | ||||
|         .editor-instance { | ||||
|           min-width: 320px; | ||||
|           flex: 1; | ||||
|           max-width: 480px; | ||||
|           background: rgba(10, 10, 10, 0.6); | ||||
|           display: flex; | ||||
|           flex-direction: column; | ||||
|           border-radius: var(--radius); | ||||
|           overflow: hidden; | ||||
|           margin-right: 0.75rem; | ||||
|           border: 1px solid rgba(255, 255, 255, 0.06); | ||||
|           transition: all 0.2s ease; | ||||
|         } | ||||
|  | ||||
|         .editor-instance:hover { | ||||
|           border-color: rgba(255, 255, 255, 0.1); | ||||
|         } | ||||
|  | ||||
|         .editor-instance:last-child { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|  | ||||
|         .editor-header { | ||||
|           padding: 0.5rem 0.75rem; | ||||
|           background: rgba(255, 255, 255, 0.02); | ||||
|           border-bottom: 1px solid rgba(255, 255, 255, 0.05); | ||||
|           display: flex; | ||||
|           justify-content: space-between; | ||||
|           align-items: center; | ||||
|           height: 36px; | ||||
|         } | ||||
|  | ||||
|         .editor-title { | ||||
|           font-size: 0.875rem; | ||||
|           font-size: 0.75rem; | ||||
|           font-weight: 500; | ||||
|           color: var(--foreground); | ||||
|           color: #999; | ||||
|           overflow: hidden; | ||||
|           text-overflow: ellipsis; | ||||
|           white-space: nowrap; | ||||
|           font-family: 'Consolas', 'Monaco', monospace; | ||||
|         } | ||||
|  | ||||
|         .editor-actions { | ||||
|           display: flex; | ||||
|           gap: 0.5rem; | ||||
|           gap: 0.25rem; | ||||
|         } | ||||
|  | ||||
|         .editor-button { | ||||
|           padding: 0.375rem 0.75rem; | ||||
|           width: 24px; | ||||
|           height: 24px; | ||||
|           padding: 0; | ||||
|           background: transparent; | ||||
|           border: 1px solid var(--border); | ||||
|           border-radius: var(--radius); | ||||
|           color: #999; | ||||
|           font-size: 0.75rem; | ||||
|           border: none; | ||||
|           color: #666; | ||||
|           font-size: 1rem; | ||||
|           cursor: pointer; | ||||
|           transition: all 0.15s ease; | ||||
|           border-radius: var(--radius-sm); | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: center; | ||||
|         } | ||||
|  | ||||
|         .editor-button:hover { | ||||
|           background: rgba(255, 255, 255, 0.05); | ||||
|           color: var(--foreground); | ||||
|           color: #999; | ||||
|         } | ||||
|  | ||||
|         .editor-button.primary { | ||||
|           background: var(--primary); | ||||
|           color: var(--primary-foreground); | ||||
|           border-color: var(--primary); | ||||
|           color: #4ade80; | ||||
|         } | ||||
|  | ||||
|         .editor-button.primary:hover { | ||||
|           background: rgba(59, 130, 246, 0.8); | ||||
|           background: rgba(74, 222, 128, 0.1); | ||||
|         } | ||||
|  | ||||
|         .editor-content { | ||||
|           flex: 1; | ||||
|           padding: 1rem; | ||||
|           overflow: auto; | ||||
|           display: flex; | ||||
|           flex-direction: column; | ||||
|           overflow: hidden; | ||||
|           min-height: 0; | ||||
|           position: relative; | ||||
|         } | ||||
|  | ||||
|         .editor-textarea { | ||||
|           width: 100%; | ||||
|           height: 100%; | ||||
|           background: var(--input); | ||||
|           border: 1px solid var(--border); | ||||
|           border-radius: var(--radius); | ||||
|           color: var(--foreground); | ||||
|           background: transparent; | ||||
|           border: none; | ||||
|           color: #d0d0d0; | ||||
|           font-family: 'Consolas', 'Monaco', 'Courier New', monospace; | ||||
|           font-size: 0.875rem; | ||||
|           font-size: 0.8125rem; | ||||
|           line-height: 1.6; | ||||
|           padding: 0.75rem; | ||||
|           resize: none; | ||||
|           outline: none; | ||||
|           transition: all 0.15s ease; | ||||
|           overflow: auto; | ||||
|         } | ||||
|  | ||||
|         .editor-textarea:focus { | ||||
|           border-color: var(--primary); | ||||
|           background: rgba(59, 130, 246, 0.05); | ||||
|           background: rgba(255, 255, 255, 0.01); | ||||
|         } | ||||
|  | ||||
|         .editor-textarea::selection { | ||||
|           background: rgba(59, 130, 246, 0.3); | ||||
|         } | ||||
|  | ||||
|         .editor-error { | ||||
|           margin-top: 0.5rem; | ||||
|           padding: 0.5rem; | ||||
|           background: rgba(239, 68, 68, 0.1); | ||||
|           border: 1px solid rgba(239, 68, 68, 0.3); | ||||
|           border-radius: var(--radius-sm); | ||||
|           color: #f87171; | ||||
|           font-size: 0.75rem; | ||||
|           position: absolute; | ||||
|           bottom: 0; | ||||
|           left: 0; | ||||
|           right: 0; | ||||
|           padding: 0.5rem 0.75rem; | ||||
|           background: rgba(239, 68, 68, 0.9); | ||||
|           backdrop-filter: blur(4px); | ||||
|           color: #fff; | ||||
|           font-size: 0.7rem; | ||||
|           font-weight: 500; | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           gap: 0.375rem; | ||||
|           border-top: 1px solid rgba(239, 68, 68, 0.5); | ||||
|         } | ||||
|  | ||||
|         .editor-error::before { | ||||
|           content: '!'; | ||||
|           display: inline-flex; | ||||
|           width: 16px; | ||||
|           height: 16px; | ||||
|           align-items: center; | ||||
|           justify-content: center; | ||||
|           background: rgba(255, 255, 255, 0.2); | ||||
|           border-radius: 50%; | ||||
|           font-size: 0.65rem; | ||||
|           font-weight: bold; | ||||
|         } | ||||
|  | ||||
|         .main-content { | ||||
| @@ -389,38 +532,72 @@ export class WccProperties extends DeesElement { | ||||
|           height: 100px; | ||||
|         } | ||||
|       </style> | ||||
|       ${this.showAdvancedEditor ? html` | ||||
|         <div class="advanced-editor"> | ||||
|           <div class="editor-header"> | ||||
|             <div class="editor-title">Editing: ${this.editingProperty?.name}</div> | ||||
|             <div class="editor-actions"> | ||||
|               <button class="editor-button" @click=${this.handleEditorCancel}>Cancel</button> | ||||
|               <button class="editor-button primary" @click=${this.handleEditorSave}>Save</button> | ||||
|             </div> | ||||
|       ${this.editingProperties.length > 0 ? html` | ||||
|         <div class="advanced-editor-container"> | ||||
|           <div class="editor-header-bar"> | ||||
|             <div class="editor-header-title">Property Editors</div> | ||||
|             <button class="editor-close-all" @click=${this.closeAllEditors}> | ||||
|               Close All | ||||
|             </button> | ||||
|           </div> | ||||
|           <div class="editor-content"> | ||||
|             <textarea  | ||||
|               class="editor-textarea" | ||||
|               .value=${this.editorValue} | ||||
|               @input=${(e: InputEvent) => { | ||||
|                 this.editorValue = (e.target as HTMLTextAreaElement).value; | ||||
|                 this.editorError = ''; | ||||
|               }} | ||||
|               @keydown=${(e: KeyboardEvent) => { | ||||
|                 if (e.key === 'Tab') { | ||||
|                   e.preventDefault(); | ||||
|                   const target = e.target as HTMLTextAreaElement; | ||||
|                   const start = target.selectionStart; | ||||
|                   const end = target.selectionEnd; | ||||
|                   const value = target.value; | ||||
|                   target.value = value.substring(0, start) + '  ' + value.substring(end); | ||||
|                   target.selectionStart = target.selectionEnd = start + 2; | ||||
|                 } | ||||
|               }} | ||||
|             ></textarea> | ||||
|             ${this.editorError ? html` | ||||
|               <div class="editor-error">${this.editorError}</div> | ||||
|           <div class="editors-container"> | ||||
|             ${this.editingProperties.length === 0 ? html` | ||||
|               <div style=" | ||||
|                 flex: 1; | ||||
|                 display: flex; | ||||
|                 align-items: center; | ||||
|                 justify-content: center; | ||||
|                 color: #666; | ||||
|                 font-size: 0.875rem; | ||||
|                 text-align: center; | ||||
|                 padding: 2rem; | ||||
|               "> | ||||
|                 <div> | ||||
|                   <div style="margin-bottom: 0.5rem; font-size: 1.5rem; opacity: 0.5;">{ }</div> | ||||
|                   <div>No properties being edited</div> | ||||
|                   <div style="font-size: 0.75rem; margin-top: 0.25rem; opacity: 0.7;">Click "Edit Object/Array" buttons to start editing</div> | ||||
|                 </div> | ||||
|               </div> | ||||
|             ` : null} | ||||
|             ${this.editingProperties.map(prop => html` | ||||
|               <div class="editor-instance"> | ||||
|                 <div class="editor-header"> | ||||
|                   <div class="editor-title">${prop.name}</div> | ||||
|                   <div class="editor-actions"> | ||||
|                     <button class="editor-button" @click=${() => this.handleEditorCancel(prop.id)}>✕</button> | ||||
|                     <button class="editor-button primary" @click=${() => this.handleEditorSave(prop.id)}>✓</button> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <div class="editor-content"> | ||||
|                   <textarea  | ||||
|                     class="editor-textarea" | ||||
|                     .value=${prop.editorValue} | ||||
|                     @input=${(e: InputEvent) => { | ||||
|                       const editor = this.editingProperties.find(p => p.id === prop.id); | ||||
|                       if (editor) { | ||||
|                         editor.editorValue = (e.target as HTMLTextAreaElement).value; | ||||
|                         editor.editorError = ''; | ||||
|                         this.requestUpdate(); | ||||
|                       } | ||||
|                     }} | ||||
|                     @keydown=${(e: KeyboardEvent) => { | ||||
|                       if (e.key === 'Tab') { | ||||
|                         e.preventDefault(); | ||||
|                         const target = e.target as HTMLTextAreaElement; | ||||
|                         const start = target.selectionStart; | ||||
|                         const end = target.selectionEnd; | ||||
|                         const value = target.value; | ||||
|                         target.value = value.substring(0, start) + '  ' + value.substring(end); | ||||
|                         target.selectionStart = target.selectionEnd = start + 2; | ||||
|                       } | ||||
|                     }} | ||||
|                   ></textarea> | ||||
|                   ${prop.editorError ? html` | ||||
|                     <div class="editor-error">${prop.editorError}</div> | ||||
|                   ` : null} | ||||
|                 </div> | ||||
|               </div> | ||||
|             `)} | ||||
|           </div> | ||||
|         </div> | ||||
|       ` : null} | ||||
| @@ -736,53 +913,84 @@ export class WccProperties extends DeesElement { | ||||
|   } | ||||
|  | ||||
|   private openAdvancedEditor(propertyName: string, value: any, element: HTMLElement) { | ||||
|     this.editingProperty = { | ||||
|     // Check if this property is already being edited | ||||
|     const existingEditor = this.editingProperties.find(p => p.name === propertyName && p.element === element); | ||||
|     if (existingEditor) { | ||||
|       return; // Property is already open for editing | ||||
|     } | ||||
|  | ||||
|     const newEditor = { | ||||
|       id: `${propertyName}-${Date.now()}`, | ||||
|       name: propertyName, | ||||
|       value: value, | ||||
|       element: element | ||||
|       element: element, | ||||
|       editorValue: JSON.stringify(value, null, 2), | ||||
|       editorError: '' | ||||
|     }; | ||||
|     this.editorValue = JSON.stringify(value, null, 2); | ||||
|     this.editorError = ''; | ||||
|     this.showAdvancedEditor = true; | ||||
|  | ||||
|     this.editingProperties = [...this.editingProperties, newEditor]; | ||||
|      | ||||
|     // Notify parent to resize frame | ||||
|     this.dispatchEvent( | ||||
|       new CustomEvent('editorStateChanged', { | ||||
|         detail: { isOpen: true }, | ||||
|         bubbles: true | ||||
|       }) | ||||
|     ); | ||||
|     // Notify parent to resize frame if this is the first editor | ||||
|     if (this.editingProperties.length === 1) { | ||||
|       this.dispatchEvent( | ||||
|         new CustomEvent('editorStateChanged', { | ||||
|           detail: { isOpen: true }, | ||||
|           bubbles: true | ||||
|         }) | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private handleEditorSave() { | ||||
|   private handleEditorSave(editorId: string) { | ||||
|     const editor = this.editingProperties.find(p => p.id === editorId); | ||||
|     if (!editor) return; | ||||
|  | ||||
|     try { | ||||
|       const parsedValue = JSON.parse(this.editorValue); | ||||
|       if (this.editingProperty) { | ||||
|         this.editingProperty.element[this.editingProperty.name] = parsedValue; | ||||
|         this.showAdvancedEditor = false; | ||||
|         this.editorError = ''; | ||||
|          | ||||
|         // Notify parent to resize frame back | ||||
|       const parsedValue = JSON.parse(editor.editorValue); | ||||
|       editor.element[editor.name] = parsedValue; | ||||
|        | ||||
|       // Remove this editor from the list | ||||
|       this.editingProperties = this.editingProperties.filter(p => p.id !== editorId); | ||||
|        | ||||
|       // If no more editors, notify parent to resize frame | ||||
|       if (this.editingProperties.length === 0) { | ||||
|         this.dispatchEvent( | ||||
|           new CustomEvent('editorStateChanged', { | ||||
|             detail: { isOpen: false }, | ||||
|             bubbles: true | ||||
|           }) | ||||
|         ); | ||||
|          | ||||
|         // Refresh properties display | ||||
|         this.createProperties(); | ||||
|       } | ||||
|        | ||||
|       // Refresh properties display | ||||
|       this.createProperties(); | ||||
|     } catch (error) { | ||||
|       this.editorError = `Invalid JSON: ${error.message}`; | ||||
|       // Update error for this specific editor | ||||
|       const editorIndex = this.editingProperties.findIndex(p => p.id === editorId); | ||||
|       if (editorIndex !== -1) { | ||||
|         this.editingProperties[editorIndex].editorError = `Invalid JSON: ${error.message}`; | ||||
|         this.requestUpdate(); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private handleEditorCancel() { | ||||
|     this.showAdvancedEditor = false; | ||||
|     this.editingProperty = null; | ||||
|     this.editorValue = ''; | ||||
|     this.editorError = ''; | ||||
|   private handleEditorCancel(editorId: string) { | ||||
|     // Remove this editor from the list | ||||
|     this.editingProperties = this.editingProperties.filter(p => p.id !== editorId); | ||||
|      | ||||
|     // If no more editors, notify parent to resize frame | ||||
|     if (this.editingProperties.length === 0) { | ||||
|       this.dispatchEvent( | ||||
|         new CustomEvent('editorStateChanged', { | ||||
|           detail: { isOpen: false }, | ||||
|           bubbles: true | ||||
|         }) | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private closeAllEditors() { | ||||
|     this.editingProperties = []; | ||||
|      | ||||
|     // Notify parent to resize frame back | ||||
|     this.dispatchEvent( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user