Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
f7bc113b6c | |||
05934132a7 | |||
6bdb8c78b7 | |||
fca47b87fb | |||
595620af4b | |||
8c3a116943 |
128
.gitlab-ci.yml
128
.gitlab-ci.yml
@ -1,128 +0,0 @@
|
|||||||
# gitzone ci_default
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .npmci_cache/
|
|
||||||
key: '$CI_BUILD_STAGE'
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- security
|
|
||||||
- test
|
|
||||||
- release
|
|
||||||
- metadata
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- pnpm install -g pnpm
|
|
||||||
- pnpm install -g @shipzone/npmci
|
|
||||||
- npmci npm prepare
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# security stage
|
|
||||||
# ====================
|
|
||||||
# ====================
|
|
||||||
# security stage
|
|
||||||
# ====================
|
|
||||||
auditProductionDependencies:
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
- npmci command pnpm audit --audit-level=high --prod
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
auditDevDependencies:
|
|
||||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci command npm config set registry https://registry.npmjs.org
|
|
||||||
- npmci command pnpm audit --audit-level=high --dev
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# test stage
|
|
||||||
# ====================
|
|
||||||
|
|
||||||
testStable:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
testBuild:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm build
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
release:
|
|
||||||
stage: release
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm publish
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
# ====================
|
|
||||||
# metadata stage
|
|
||||||
# ====================
|
|
||||||
codequality:
|
|
||||||
stage: metadata
|
|
||||||
allow_failure: true
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
script:
|
|
||||||
- npmci command npm install -g typescript
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci npm install
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- priv
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci trigger
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
|
|
||||||
pages:
|
|
||||||
stage: metadata
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci command npm run buildDocs
|
|
||||||
tags:
|
|
||||||
- lossless
|
|
||||||
- docker
|
|
||||||
- notpriv
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
allow_failure: true
|
|
13
package.json
13
package.json
@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@design.estate/dees-wcctools",
|
"name": "@design.estate/dees-wcctools",
|
||||||
"version": "1.0.89",
|
"version": "1.0.91",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.",
|
"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",
|
"exports": {
|
||||||
"typings": "dist_ts_web/index.d.ts",
|
".": "./dist_ts_web/index.js",
|
||||||
|
"./demoTools": "./dist_ts_demotools"
|
||||||
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "(npm run build)",
|
"test": "(npm run build)",
|
||||||
"build": "(tsbuild element --web --allowimplicitany && tsbundle element)",
|
"build": "(tsbuild tsfolders --allowimplicitany && tsbundle element)",
|
||||||
"watch": "tswatch element",
|
"watch": "tswatch element",
|
||||||
"buildDocs": "tsdoc"
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
@ -54,5 +56,6 @@
|
|||||||
"design system",
|
"design system",
|
||||||
"element testing",
|
"element testing",
|
||||||
"page development"
|
"page development"
|
||||||
]
|
],
|
||||||
|
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
|
||||||
}
|
}
|
||||||
|
8189
pnpm-lock.yaml
generated
8189
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1 +1,51 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
## Demo Tools
|
||||||
|
|
||||||
|
### DeesDemoWrapper Component
|
||||||
|
A utility component for wrapping demo elements with post-render functionality.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```typescript
|
||||||
|
import { DeesDemoWrapper } from '@design.estate/dees-wcctools/demoTools';
|
||||||
|
|
||||||
|
// In your demo function:
|
||||||
|
demo: () => html`
|
||||||
|
<dees-demowrapper .runAfterRender=${(element) => {
|
||||||
|
// Do something with the rendered element
|
||||||
|
element.setAttribute('data-demo', 'true');
|
||||||
|
console.log('Element rendered:', element);
|
||||||
|
}}>
|
||||||
|
<my-custom-element></my-custom-element>
|
||||||
|
</dees-demowrapper>
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Wraps demo elements without affecting layout (uses `display: contents`)
|
||||||
|
- Provides access to the rendered element instance after mounting
|
||||||
|
- Supports async operations in runAfterRender callback
|
||||||
|
- Automatically handles timing to ensure element is fully rendered
|
41
readme.plan.md
Normal file
41
readme.plan.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Fix Properties Panel Element Detection (COMPLETED)
|
||||||
|
|
||||||
|
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 ✅
|
||||||
|
|
||||||
|
# Demo Wrapper Implementation (COMPLETED)
|
||||||
|
|
||||||
|
## Created DeesDemoWrapper Component
|
||||||
|
- Location: ts_demotools/demotools.ts
|
||||||
|
- Allows wrapping demo elements with post-render functionality
|
||||||
|
- Provides runAfterRender callback that receives the rendered element
|
||||||
|
- Uses display: contents to not affect layout
|
||||||
|
- Handles timing automatically with 50ms delay after firstUpdated
|
||||||
|
- Supports both sync and async callbacks
|
||||||
|
- Exports available at @design.estate/dees-wcctools/demoTools
|
41
ts_demotools/demotools.ts
Normal file
41
ts_demotools/demotools.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { DeesElement, customElement, html, css, property, type TemplateResult } from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
@customElement('dees-demowrapper')
|
||||||
|
export class DeesDemoWrapper extends DeesElement {
|
||||||
|
@property({ attribute: false })
|
||||||
|
public runAfterRender: (element: HTMLElement) => void | Promise<void>;
|
||||||
|
|
||||||
|
public static styles = [
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
];
|
||||||
|
|
||||||
|
public render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<slot></slot>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async firstUpdated() {
|
||||||
|
await this.updateComplete;
|
||||||
|
|
||||||
|
// Wait a bit for slotted content to render
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 50));
|
||||||
|
|
||||||
|
// Find the first element child (excluding text nodes)
|
||||||
|
const slottedElements = this.children;
|
||||||
|
if (slottedElements.length > 0 && this.runAfterRender) {
|
||||||
|
const firstElement = slottedElements[0] as HTMLElement;
|
||||||
|
|
||||||
|
// Call the runAfterRender function with the element
|
||||||
|
try {
|
||||||
|
await this.runAfterRender(firstElement);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in runAfterRender:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
ts_demotools/index.ts
Normal file
1
ts_demotools/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './demotools.js';
|
5
ts_demotools/plugins.ts
Normal file
5
ts_demotools/plugins.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import * as deesElement from '@design.estate/dees-element';
|
||||||
|
|
||||||
|
export {
|
||||||
|
deesElement
|
||||||
|
};
|
3
ts_demotools/tspublish.json
Normal file
3
ts_demotools/tspublish.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"order": 2
|
||||||
|
}
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@design.estate/dees-wcctools',
|
name: '@design.estate/dees-wcctools',
|
||||||
version: '1.0.89',
|
version: '1.0.90',
|
||||||
description: 'A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.'
|
description: 'A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.'
|
||||||
}
|
}
|
||||||
|
@ -139,9 +139,9 @@ export class WccDashboard extends DeesElement {
|
|||||||
const storeElement = this.selectedItem;
|
const storeElement = this.selectedItem;
|
||||||
const wccFrame: WccFrame = this.shadowRoot.querySelector('wcc-frame');
|
const wccFrame: WccFrame = this.shadowRoot.querySelector('wcc-frame');
|
||||||
|
|
||||||
if (changedPropertiesArg.has('selectedItemName') {
|
if (changedPropertiesArg.has('selectedItemName')) {
|
||||||
document.title = this.selectedItemName;
|
document.title = this.selectedItemName;
|
||||||
})
|
};
|
||||||
|
|
||||||
if (this.selectedType === 'page' && this.selectedItem) {
|
if (this.selectedType === 'page' && this.selectedItem) {
|
||||||
if (typeof this.selectedItem === 'function') {
|
if (typeof this.selectedItem === 'function') {
|
||||||
|
@ -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() {
|
public async createProperties() {
|
||||||
console.log('creating properties for:');
|
console.log('creating properties for:');
|
||||||
console.log(this.selectedItem);
|
console.log(this.selectedItem);
|
||||||
@ -275,15 +300,30 @@ export class WccProperties extends DeesElement {
|
|||||||
}
|
}
|
||||||
console.log(anonItem.elementProperties);
|
console.log(anonItem.elementProperties);
|
||||||
const wccFrame = await this.dashboardRef.wccFrame;
|
const wccFrame = await this.dashboardRef.wccFrame;
|
||||||
let firstFoundInstantiatedElement: HTMLElement;
|
|
||||||
for (const element of Array.from((await wccFrame.getViewportElement()).children)) {
|
// Wait for render to complete
|
||||||
if (element instanceof (this.selectedItem as any)) {
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
firstFoundInstantiatedElement = element as HTMLElement;
|
|
||||||
break;
|
// 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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
const classProperties: Map<string, any> = anonItem.elementProperties;
|
const classProperties: Map<string, any> = anonItem.elementProperties;
|
||||||
|
3
ts_web/tspublish.json
Normal file
3
ts_web/tspublish.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"order": 1
|
||||||
|
}
|
Reference in New Issue
Block a user