Compare commits

...

3 Commits

Author SHA1 Message Date
4c23739d9a 1.2.0
Some checks failed
Default (tags) / security (push) Failing after 23s
Default (tags) / test (push) Failing after 14s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
2025-09-19 13:24:46 +00:00
dd048d42a8 feat(wcc-properties): Add advanced property editors, recursive element detection, demo wrapper, UI refresh and test fixtures 2025-09-19 13:24:46 +00:00
ca28dbd9db feat: add async demo support and enhance template resolution
- Introduced async demo functionality in the README, allowing for asynchronous data preparation before rendering components.
- Updated WccDashboard, WccProperties, and WccSidebar to support Promise-based template factories.
- Implemented resolveTemplateFactory to handle both synchronous and asynchronous template results.
- Added tests for resolveTemplateFactory to ensure correct behavior for both sync and async templates.
- Updated pnpm workspace configuration.
2025-09-19 13:02:16 +00:00
13 changed files with 3944 additions and 1803 deletions

View File

@@ -1,5 +1,16 @@
# Changelog # Changelog
## 2025-09-19 - 1.2.0 - feat(wcc-properties)
Add advanced property editors, recursive element detection, demo wrapper, UI refresh and test fixtures
- Advanced JSON property editor: multiple side-by-side editors with save/cancel, syntax validation and inline error display; editors affect frame layout (frame bottom increases when editors open).
- Improved properties panel element detection: recursive search through nested children and shadow DOM, initial delay and retry mechanism to handle async Lit rendering.
- Add dees-demowrapper component in ts_demotools to run post-render callbacks and support async demo setup and DOM access for demos.
- UI refresh with shadcn-like styles: CSS variables for theming, redesigned properties panel and sidebar, improved form controls, theme and viewport selectors.
- Viewport and frame improvements: responsive padding based on viewport type, theme-aware background rendering, and scroll position tracking with URL/state restoration for frame and sidebar.
- Add test fixtures and demo elements/pages under test/ to exercise properties, complex types, nested elements and scroll restoration; include node test for resolveTemplateFactory.
- Expose setupWccTools entry point and plugin wiring (wcctools.plugins exports for dees-domtools and smartdelay) for easier integration.
## 2025-06-27 - 1.1.0 - feat(wcctools) ## 2025-06-27 - 1.1.0 - feat(wcctools)
Enhance component tools with an advanced property editor, improved element detection and modernized UI styling for a more responsive dashboard experience. Enhance component tools with an advanced property editor, improved element detection and modernized UI styling for a more responsive dashboard experience.

View File

@@ -1,6 +1,6 @@
{ {
"name": "@design.estate/dees-wcctools", "name": "@design.estate/dees-wcctools",
"version": "1.1.1", "version": "1.2.0",
"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.",
"exports": { "exports": {
@@ -17,18 +17,20 @@
"author": "Lossless GmbH", "author": "Lossless GmbH",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@design.estate/dees-domtools": "^2.0.57", "@design.estate/dees-domtools": "^2.3.3",
"@design.estate/dees-element": "^2.0.34", "@design.estate/dees-element": "^2.1.2",
"@push.rocks/smartdelay": "^3.0.5", "@push.rocks/smartdelay": "^3.0.5",
"lit": "^3.1.3" "lit": "^3.3.1"
}, },
"devDependencies": { "devDependencies": {
"@api.global/typedserver": "^3.0.29", "@api.global/typedserver": "^3.0.79",
"@git.zone/tsbuild": "^2.1.72", "@git.zone/tsbuild": "^2.6.8",
"@git.zone/tsbundle": "^2.0.15", "@git.zone/tsbundle": "^2.5.1",
"@git.zone/tsrun": "^1.2.44", "@git.zone/tsrun": "^1.2.44",
"@git.zone/tswatch": "^2.0.23", "@git.zone/tstest": "^2.3.8",
"@push.rocks/projectinfo": "^5.0.2" "@git.zone/tswatch": "^2.2.1",
"@push.rocks/projectinfo": "^5.0.2",
"@types/node": "^22.18.6"
}, },
"files": [ "files": [
"ts/**/*", "ts/**/*",

5624
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

4
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,4 @@
onlyBuiltDependencies:
- esbuild
- mongodb-memory-server
- puppeteer

View File

@@ -211,6 +211,19 @@ export class MyComponent extends DeesElement {
} }
``` ```
### ⏳ Async Demos
If your catalogue needs additional setup before rendering, return a `Promise` from the `demo` function. The dashboard waits for the result before inserting it into the viewport:
```typescript
public static demo = async () => {
await Promise.resolve(); // e.g. fetch data, load fixtures, or await wrappers
return html`<my-component .value=${'Loaded asynchronously'}></my-component>`;
};
```
The same pattern works for page factories you pass into `setupWccTools`, enabling asynchronous data preparation across the entire demo surface.
### 🎭 Container Queries Support ### 🎭 Container Queries Support
Components can respond to their container size: Components can respond to their container size:

View File

@@ -98,3 +98,10 @@ Properties panel was overwriting values set by demo functions
3. Added proper number parsing for number inputs 3. Added proper number parsing for number inputs
4. Increased initial wait to 200ms for demo wrappers to complete 4. Increased initial wait to 200ms for demo wrappers to complete
5. Simplified select element handling to use property binding 5. Simplified select element handling to use property binding
# Async Demo Support (IN PROGRESS)
## Tasks
- [ ] Allow dashboard-selected items to return Promise-based TemplateResults
- [ ] Await async demos/pages before rendering them into the viewport
- [ ] Add regression test covering async demo usage
- [ ] Document async demo pattern in README and verify with pnpm scripts

View File

@@ -0,0 +1,22 @@
import { tap, expect } from '@git.zone/tstest/tapbundle';
import { resolveTemplateFactory } from '../ts_web/elements/wcctools.helpers.js';
import { html } from 'lit';
const waitFor = (durationMs: number) => new Promise(resolve => setTimeout(resolve, durationMs));
tap.test('resolveTemplateFactory returns sync TemplateResult', async () => {
const template = html`<p>sync demo</p>`;
const resolvedTemplate = await resolveTemplateFactory(() => template);
expect(resolvedTemplate).toEqual(template);
});
tap.test('resolveTemplateFactory awaits async TemplateResult', async () => {
const template = html`<p>async demo</p>`;
const resolvedTemplate = await resolveTemplateFactory(async () => {
await waitFor(5);
return template;
});
expect(resolvedTemplate).toEqual(template);
});
export default tap.start();

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@design.estate/dees-wcctools', name: '@design.estate/dees-wcctools',
version: '1.1.0', version: '1.2.0',
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.'
} }

View File

@@ -1,4 +1,6 @@
import { DeesElement, property, html, customElement, type TemplateResult, queryAsync, render, domtools } from '@design.estate/dees-element'; import { DeesElement, property, html, customElement, type TemplateResult, queryAsync, render, domtools } from '@design.estate/dees-element';
import { resolveTemplateFactory } from './wcctools.helpers.js';
import type { TTemplateFactory } from './wcctools.helpers.js';
import * as plugins from '../wcctools.plugins.js'; import * as plugins from '../wcctools.plugins.js';
@@ -21,7 +23,7 @@ export class WccDashboard extends DeesElement {
public selectedItemName: string; public selectedItemName: string;
@property() @property()
public selectedItem: (() => TemplateResult) | DeesElement; public selectedItem: TTemplateFactory | DeesElement;
@property() @property()
public selectedViewport: plugins.deesDomtools.breakpoints.TViewport = 'desktop'; public selectedViewport: plugins.deesDomtools.breakpoints.TViewport = 'desktop';
@@ -33,7 +35,7 @@ export class WccDashboard extends DeesElement {
public isFullscreen: boolean = false; public isFullscreen: boolean = false;
@property() @property()
public pages: { [key: string]: () => TemplateResult } = {}; public pages: Record<string, TTemplateFactory> = {};
@property() @property()
public elements: { [key: string]: DeesElement } = {}; public elements: { [key: string]: DeesElement } = {};
@@ -50,7 +52,7 @@ export class WccDashboard extends DeesElement {
constructor( constructor(
elementsArg?: { [key: string]: DeesElement }, elementsArg?: { [key: string]: DeesElement },
pagesArg?: { [key: string]: () => TemplateResult } pagesArg?: Record<string, TTemplateFactory>
) { ) {
super(); super();
if (elementsArg) { if (elementsArg) {
@@ -201,7 +203,9 @@ export class WccDashboard extends DeesElement {
if (typeof this.selectedItem === 'function') { if (typeof this.selectedItem === 'function') {
console.log('slotting page.'); console.log('slotting page.');
const viewport = await wccFrame.getViewportElement(); const viewport = await wccFrame.getViewportElement();
render(this.selectedItem(), viewport); const pageFactory = this.selectedItem as TTemplateFactory;
const pageTemplate = await resolveTemplateFactory(pageFactory);
render(pageTemplate, viewport);
console.log('rendered page.'); console.log('rendered page.');
} else { } else {
console.error('The selected item looks strange:'); console.error('The selected item looks strange:');
@@ -222,7 +226,8 @@ export class WccDashboard extends DeesElement {
} }
this.setWarning(null); this.setWarning(null);
const viewport = await wccFrame.getViewportElement(); const viewport = await wccFrame.getViewportElement();
render(anonItem.demo(), viewport);; const demoTemplate = await resolveTemplateFactory(() => anonItem.demo());
render(demoTemplate, viewport);
} }
} }

View File

@@ -1,5 +1,6 @@
import { DeesElement, property, html, customElement, type TemplateResult, state } from '@design.estate/dees-element'; import { DeesElement, property, html, customElement, type TemplateResult, state } from '@design.estate/dees-element';
import { WccDashboard } from './wcc-dashboard.js'; import { WccDashboard } from './wcc-dashboard.js';
import type { TTemplateFactory } from './wcctools.helpers.js';
export type TPropertyType = 'String' | 'Number' | 'Boolean' | 'Object' | 'Enum' | 'Array'; export type TPropertyType = 'String' | 'Number' | 'Boolean' | 'Object' | 'Enum' | 'Array';
@@ -20,7 +21,7 @@ export class WccProperties extends DeesElement {
public dashboardRef: WccDashboard; public dashboardRef: WccDashboard;
@property() @property()
public selectedItem: (() => TemplateResult) | DeesElement; public selectedItem: TTemplateFactory | DeesElement;
@property() @property()
public selectedViewport: TEnvironment = 'native'; public selectedViewport: TEnvironment = 'native';

View File

@@ -1,13 +1,14 @@
import * as plugins from '../wcctools.plugins.js'; import * as plugins from '../wcctools.plugins.js';
import { DeesElement, property, html, customElement, type TemplateResult } from '@design.estate/dees-element'; import { DeesElement, property, html, customElement, type TemplateResult } from '@design.estate/dees-element';
import { WccDashboard } from './wcc-dashboard.js'; import { WccDashboard } from './wcc-dashboard.js';
import type { TTemplateFactory } from './wcctools.helpers.js';
export type TElementType = 'element' | 'page'; export type TElementType = 'element' | 'page';
@customElement('wcc-sidebar') @customElement('wcc-sidebar')
export class WccSidebar extends DeesElement { export class WccSidebar extends DeesElement {
@property({ attribute: false }) @property({ attribute: false })
public selectedItem: DeesElement | (() => TemplateResult); public selectedItem: DeesElement | TTemplateFactory;
@property({ attribute: false }) @property({ attribute: false })
public selectedType: TElementType; public selectedType: TElementType;
@@ -202,7 +203,7 @@ export class WccSidebar extends DeesElement {
`; `;
} }
public selectItem(typeArg: TElementType, itemNameArg: string, itemArg: (() => TemplateResult) | DeesElement) { public selectItem(typeArg: TElementType, itemNameArg: string, itemArg: TTemplateFactory | DeesElement) {
console.log('selected item'); console.log('selected item');
console.log(itemNameArg); console.log(itemNameArg);
console.log(itemArg); console.log(itemArg);

View File

@@ -0,0 +1,9 @@
import type { TemplateResult } from 'lit';
export type TTemplateFactory = () => TemplateResult | Promise<TemplateResult>;
export const resolveTemplateFactory = async (
factoryArg: TTemplateFactory
): Promise<TemplateResult> => {
return await Promise.resolve(factoryArg());
};

View File

@@ -1,7 +1,11 @@
import { WccDashboard } from './elements/wcc-dashboard.js'; import { WccDashboard } from './elements/wcc-dashboard.js';
import { LitElement, type TemplateResult } from 'lit'; import { LitElement } from 'lit';
import type { TTemplateFactory } from './elements/wcctools.helpers.js';
const setupWccTools = (elementsArg?: { [key: string]: LitElement }, pagesArg?: { [key: string]: () => TemplateResult }) => { const setupWccTools = (
elementsArg?: { [key: string]: LitElement },
pagesArg?: Record<string, TTemplateFactory>
) => {
let hasRun = false; let hasRun = false;
const runWccToolsSetup = async () => { const runWccToolsSetup = async () => {
if (document.readyState === 'complete' && !hasRun) { if (document.readyState === 'complete' && !hasRun) {