@design.estate/wcctools 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.smartconfig.json +65 -0
  2. package/changelog.md +414 -0
  3. package/dist_bundle/bundle.js +92419 -0
  4. package/dist_bundle/bundle.js.map +1 -0
  5. package/dist_ts_web/00_commitinfo_data.d.ts +8 -0
  6. package/dist_ts_web/00_commitinfo_data.js +9 -0
  7. package/dist_ts_web/elements/wcc-contextmenu.d.ts +41 -0
  8. package/dist_ts_web/elements/wcc-contextmenu.js +329 -0
  9. package/dist_ts_web/elements/wcc-dashboard.d.ts +119 -0
  10. package/dist_ts_web/elements/wcc-dashboard.js +700 -0
  11. package/dist_ts_web/elements/wcc-frame.d.ts +22 -0
  12. package/dist_ts_web/elements/wcc-frame.js +256 -0
  13. package/dist_ts_web/elements/wcc-properties.d.ts +43 -0
  14. package/dist_ts_web/elements/wcc-properties.js +1147 -0
  15. package/dist_ts_web/elements/wcc-record-button.d.ts +12 -0
  16. package/dist_ts_web/elements/wcc-record-button.js +165 -0
  17. package/dist_ts_web/elements/wcc-recording-panel.d.ts +44 -0
  18. package/dist_ts_web/elements/wcc-recording-panel.js +1103 -0
  19. package/dist_ts_web/elements/wcc-sidebar.d.ts +91 -0
  20. package/dist_ts_web/elements/wcc-sidebar.js +1497 -0
  21. package/dist_ts_web/elements/wcctools.helpers.d.ts +46 -0
  22. package/dist_ts_web/elements/wcctools.helpers.js +106 -0
  23. package/dist_ts_web/index.d.ts +18 -0
  24. package/dist_ts_web/index.js +30 -0
  25. package/dist_ts_web/pages/index.d.ts +1 -0
  26. package/dist_ts_web/pages/index.js +2 -0
  27. package/dist_ts_web/services/recorder.service.d.ts +55 -0
  28. package/dist_ts_web/services/recorder.service.js +353 -0
  29. package/dist_ts_web/wcctools.interfaces.d.ts +29 -0
  30. package/dist_ts_web/wcctools.interfaces.js +2 -0
  31. package/dist_ts_web/wcctools.plugins.d.ts +2 -0
  32. package/dist_ts_web/wcctools.plugins.js +3 -0
  33. package/license.md +19 -0
  34. package/package.json +64 -0
  35. package/readme.md +568 -0
  36. package/ts_web/00_commitinfo_data.ts +8 -0
  37. package/ts_web/elements/wcc-contextmenu.ts +291 -0
  38. package/ts_web/elements/wcc-dashboard.ts +672 -0
  39. package/ts_web/elements/wcc-frame.ts +189 -0
  40. package/ts_web/elements/wcc-properties.ts +1089 -0
  41. package/ts_web/elements/wcc-record-button.ts +108 -0
  42. package/ts_web/elements/wcc-recording-panel.ts +1010 -0
  43. package/ts_web/elements/wcc-sidebar.ts +1470 -0
  44. package/ts_web/elements/wcctools.helpers.ts +153 -0
  45. package/ts_web/index.ts +38 -0
  46. package/ts_web/pages/index.ts +1 -0
  47. package/ts_web/readme.md +177 -0
  48. package/ts_web/services/recorder.service.ts +451 -0
  49. package/ts_web/tspublish.json +3 -0
  50. package/ts_web/types/dom-mediacapture-stub/index.d.ts +12 -0
  51. package/ts_web/types/dom-mediacapture-stub/package.json +6 -0
  52. package/ts_web/types/dom-webcodecs-stub/index.d.ts +2 -0
  53. package/ts_web/types/dom-webcodecs-stub/package.json +6 -0
  54. package/ts_web/wcctools.interfaces.ts +31 -0
  55. package/ts_web/wcctools.plugins.ts +5 -0
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Configuration for a section in the WCC Tools sidebar
3
+ */
4
+ export interface IWccSection {
5
+ /** Display name for the section header */
6
+ name: string;
7
+ /** How items in this section are rendered - 'elements' show demos, 'pages' render directly */
8
+ type: 'elements' | 'pages';
9
+ /** The items in this section - either element classes or page factory functions */
10
+ items: Record<string, any>;
11
+ /** Optional filter function to include/exclude items */
12
+ filter?: (name: string, item: any) => boolean;
13
+ /** Optional sort function for ordering items */
14
+ sort?: (a: [string, any], b: [string, any]) => number;
15
+ /** Optional Material icon name for the section header */
16
+ icon?: string;
17
+ /** Whether this section should start collapsed (default: false) */
18
+ collapsed?: boolean;
19
+ }
20
+ /**
21
+ * Configuration object for setupWccTools
22
+ */
23
+ export interface IWccConfig {
24
+ sections: IWccSection[];
25
+ }
26
+ /**
27
+ * Type for element selection types - now section-based
28
+ */
29
+ export type TElementType = 'element' | 'page';
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjdG9vbHMuaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3dlYi93Y2N0b29scy5pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1,2 @@
1
+ import * as deesDomtools from '@design.estate/dees-domtools';
2
+ export { deesDomtools };
@@ -0,0 +1,3 @@
1
+ import * as deesDomtools from '@design.estate/dees-domtools';
2
+ export { deesDomtools };
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjdG9vbHMucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3dlYi93Y2N0b29scy5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxZQUFZLE1BQU0sOEJBQThCLENBQUM7QUFFN0QsT0FBTyxFQUNMLFlBQVksRUFDYixDQUFDIn0=
package/license.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2020 Task Venture Capital GmbH (hello@task.vc)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@design.estate/wcctools",
3
+ "version": "5.1.0",
4
+ "private": false,
5
+ "description": "A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.",
6
+ "exports": {
7
+ ".": "./dist_ts_web/index.js"
8
+ },
9
+ "type": "module",
10
+ "author": "Lossless GmbH",
11
+ "license": "MIT",
12
+ "dependencies": {
13
+ "@design.estate/dees-domtools": "^5.0.0",
14
+ "@design.estate/dees-element": "^4.0.0",
15
+ "lit": "^3.3.2",
16
+ "mediabunny": "^1.40.1"
17
+ },
18
+ "devDependencies": {
19
+ "@api.global/typedserver": "^8.4.7",
20
+ "@git.zone/tsbuild": "^5.1.2",
21
+ "@git.zone/tsbundle": "^3.1.3",
22
+ "@git.zone/tsdoc": "^3.0.2",
23
+ "@git.zone/tsrun": "^3.0.2",
24
+ "@git.zone/tstest": "^7.1.0",
25
+ "@git.zone/tswatch": "^6.0.1",
26
+ "@push.rocks/projectinfo": "^5.1.0",
27
+ "@types/node": "^26.6.3"
28
+ },
29
+ "files": [
30
+ "ts/**/*",
31
+ "ts_web/**/*",
32
+ "dist/**/*",
33
+ "dist_*/**/*",
34
+ "dist_ts/**/*",
35
+ "dist_ts_web/**/*",
36
+ "assets/**/*",
37
+ "cli.js",
38
+ ".smartconfig.json",
39
+ "readme.md",
40
+ "changelog.md",
41
+ "license.md"
42
+ ],
43
+ "browserslist": [
44
+ "last 1 Chrome versions"
45
+ ],
46
+ "keywords": [
47
+ "web components",
48
+ "element catalogues",
49
+ "custom elements",
50
+ "documentation",
51
+ "typescript",
52
+ "lit",
53
+ "component development",
54
+ "design system",
55
+ "element testing",
56
+ "page development"
57
+ ],
58
+ "scripts": {
59
+ "test": "pnpm run build && tstest \"test/test.*.*.ts\" --verbose --logfile",
60
+ "build": "(tsbuild tsfolders --allowimplicitany && tsbundle)",
61
+ "watch": "tswatch",
62
+ "buildDocs": "tsdoc"
63
+ }
64
+ }
package/readme.md ADDED
@@ -0,0 +1,568 @@
1
+ # @design.estate/wcctools
2
+
3
+ 🛠️ **Web Component Development Tools** — A powerful framework for building, testing, documenting, and recording web components
4
+
5
+ ## Overview
6
+
7
+ `@design.estate/wcctools` provides a comprehensive development environment for web components, featuring:
8
+
9
+ - 🎨 **Interactive Component Catalogue** — Live preview with customizable sidebar sections
10
+ - 🔧 **Real-time Property Editing** — Modify component props on the fly with auto-detected editors
11
+ - 🌓 **Theme Switching** — Test light/dark modes instantly
12
+ - 📱 **Responsive Viewport Testing** — Phone, phablet, tablet, and desktop views
13
+ - 🎬 **Screen Recording** — Record component demos with audio, trimming, and MP4/WebM export
14
+ - 🧪 **Advanced Demo Tools** — Post-render hooks for interactive testing
15
+ - 📂 **Section-based Organization** — Group components into custom sections with filtering and sorting
16
+ - 🚀 **Zero-config Setup** — TypeScript and Lit support out of the box
17
+
18
+ ## Issue Reporting and Security
19
+
20
+ For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ # Using pnpm (recommended)
26
+ pnpm add -D @design.estate/wcctools
27
+
28
+ # Using npm
29
+ npm install @design.estate/wcctools --save-dev
30
+ ```
31
+
32
+ ### Migrating from `@design.estate/dees-wcctools`
33
+
34
+ `@design.estate/dees-wcctools` is now published as `@design.estate/wcctools`. Versions continue from 5.0.0 and the API is the same: swap the dependency and the import specifier.
35
+
36
+ ```bash
37
+ pnpm remove @design.estate/dees-wcctools
38
+ pnpm add -D @design.estate/wcctools
39
+ ```
40
+
41
+ ```typescript
42
+ // before: import { setupWccTools } from '@design.estate/dees-wcctools';
43
+ import { setupWccTools } from '@design.estate/wcctools';
44
+ ```
45
+
46
+ A catalogue still on a 4.x or older release also follows the 5.0.0 changes: [`setupWccTools()` takes only the config object](#migration-from-setupwcctoolselements-pages) and [`DeesDemoWrapper` moved to `@design.estate/dees-element/demotools`](#-demo-tools).
47
+
48
+ ## Quick Start
49
+
50
+ ### 1. Create Your Component
51
+
52
+ ```typescript
53
+ import { DeesElement, customElement, html, css, property } from '@design.estate/dees-element';
54
+
55
+ @customElement('my-button')
56
+ export class MyButton extends DeesElement {
57
+ // Define a demo for the catalogue
58
+ public static demo = () => html`
59
+ <my-button .label=${'Click me!'} .variant=${'primary'}></my-button>
60
+ `;
61
+
62
+ @property({ type: String })
63
+ accessor label: string = 'Button';
64
+
65
+ @property({ type: String })
66
+ accessor variant: 'primary' | 'secondary' = 'primary';
67
+
68
+ public static styles = [
69
+ css`
70
+ :host {
71
+ display: inline-block;
72
+ }
73
+ button {
74
+ padding: 8px 16px;
75
+ border-radius: 4px;
76
+ border: none;
77
+ cursor: pointer;
78
+ }
79
+ button.primary {
80
+ background: #3b82f6;
81
+ color: white;
82
+ }
83
+ button.secondary {
84
+ background: #6b7280;
85
+ color: white;
86
+ }
87
+ `
88
+ ];
89
+
90
+ public render() {
91
+ return html`
92
+ <button class="${this.variant}">${this.label}</button>
93
+ `;
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### 2. Set Up Your Catalogue
99
+
100
+ ```typescript
101
+ // catalogue.ts
102
+ import { setupWccTools } from '@design.estate/wcctools';
103
+ import { html } from 'lit';
104
+
105
+ // Import your components
106
+ import * as elements from './components/index.js';
107
+ import * as views from './views/index.js';
108
+ import * as pages from './pages/index.js';
109
+
110
+ // Initialize with sections-based configuration
111
+ setupWccTools({
112
+ sections: [
113
+ {
114
+ name: 'Pages',
115
+ type: 'pages',
116
+ items: pages,
117
+ },
118
+ {
119
+ name: 'Views',
120
+ type: 'elements',
121
+ items: views,
122
+ icon: 'web',
123
+ },
124
+ {
125
+ name: 'Elements',
126
+ type: 'elements',
127
+ items: elements,
128
+ sort: ([a], [b]) => a.localeCompare(b),
129
+ },
130
+ ],
131
+ });
132
+ ```
133
+
134
+ ### 3. Create an HTML Entry Point
135
+
136
+ ```html
137
+ <!DOCTYPE html>
138
+ <html>
139
+ <head>
140
+ <title>Component Catalogue</title>
141
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
142
+ </head>
143
+ <body style="margin: 0; padding: 0;">
144
+ <script type="module" src="./catalogue.js"></script>
145
+ </body>
146
+ </html>
147
+ ```
148
+
149
+ ## 📂 Sections Configuration
150
+
151
+ The sections-based API gives you full control over how components are organized in the sidebar.
152
+
153
+ ### Section Properties
154
+
155
+ | Property | Type | Description |
156
+ |----------|------|-------------|
157
+ | `name` | `string` | Display name for the section header |
158
+ | `type` | `'elements' \| 'pages'` | How items render (`elements` show demos, `pages` render directly) |
159
+ | `items` | `Record<string, any>` | Element classes or page factories — a whole module namespace (`import * as elements`) is fine, see [What the sidebar lists](#what-the-sidebar-lists) |
160
+ | `filter` | `(name, item) => boolean` | Optional filter function to include/exclude items |
161
+ | `sort` | `([a, itemA], [b, itemB]) => number` | Optional sort function for ordering items |
162
+ | `icon` | `string` | Optional Material Symbols icon name |
163
+ | `collapsed` | `boolean` | Start section collapsed (default: `false`) |
164
+
165
+ ### Advanced Example
166
+
167
+ ```typescript
168
+ import { setupWccTools } from '@design.estate/wcctools';
169
+ import * as allElements from './elements/index.js';
170
+ import * as pages from './pages/index.js';
171
+
172
+ setupWccTools({
173
+ sections: [
174
+ {
175
+ name: 'Pages',
176
+ type: 'pages',
177
+ items: pages,
178
+ },
179
+ {
180
+ name: 'Form Controls',
181
+ type: 'elements',
182
+ items: allElements,
183
+ icon: 'edit_note',
184
+ filter: (name) => name.startsWith('form-') || name.includes('input'),
185
+ sort: ([a], [b]) => a.localeCompare(b),
186
+ },
187
+ {
188
+ name: 'Layout',
189
+ type: 'elements',
190
+ items: allElements,
191
+ icon: 'dashboard',
192
+ filter: (name) => name.startsWith('layout-') || name.startsWith('grid-'),
193
+ },
194
+ {
195
+ name: 'Legacy',
196
+ type: 'elements',
197
+ items: allElements,
198
+ filter: (name) => name.startsWith('legacy-'),
199
+ collapsed: true, // Start collapsed
200
+ },
201
+ ],
202
+ });
203
+ ```
204
+
205
+ ### What the sidebar lists
206
+
207
+ Catalogue barrels usually export more than components: helpers, constants, styles, abstract base classes. wcctools classifies every entry of an `elements` section itself, before your `filter` and `sort` run, so no curated list is needed:
208
+
209
+ | Entry | Sidebar |
210
+ |-------|---------|
211
+ | A class extending `HTMLElement` with a static `demo` (a template factory, or a non-empty array of them) | Listed and navigable |
212
+ | A registered custom element (`customElements.getName(ctor)` is set) without a usable `demo` | Listed under **Without demo** |
213
+ | Anything else — functions, objects, strings, numbers, unregistered base classes | Not listed |
214
+
215
+ - **Without demo** is a collapsed, muted group at the bottom of each `elements` section. Its entries are not clickable (`aria-disabled`, no route); they keep demo coverage visible. A search opens the group while it has matches, and matches names, tag names and demo groups like any other entry.
216
+ - A `pages` section lists only template factories (functions).
217
+ - A route or pin that points at an entry that is not listed clears the preview and shows an explanation in the frame ("… has no demo", "… cannot be previewed", "… was not found") instead of a blank or stale preview.
218
+
219
+ ### Migration from `setupWccTools(elements, pages)`
220
+
221
+ The two-argument form is removed in 5.0.0. Pass the same maps as sections; a whole module namespace still works as `items`:
222
+
223
+ ```typescript
224
+ setupWccTools({
225
+ sections: [
226
+ { name: 'Pages', type: 'pages', items: pages },
227
+ { name: 'Elements', type: 'elements', items: elements },
228
+ ],
229
+ });
230
+ ```
231
+
232
+ ## Features
233
+
234
+ ### 🎯 Live Property Editing
235
+
236
+ The properties panel finds the nearest matching demo instance through light DOM
237
+ and open shadow roots, without imposing a nesting-depth limit. Composed examples
238
+ can place their controls inside theme providers, panels, and layout wrappers.
239
+
240
+ The properties panel automatically detects and allows editing of:
241
+
242
+ | Property Type | Editor |
243
+ |--------------|--------|
244
+ | **String** | Text input |
245
+ | **Number** | Number input |
246
+ | **Boolean** | Checkbox |
247
+ | **Enum** | Select dropdown |
248
+ | **Object/Array** | JSON editor modal |
249
+
250
+ WCC only creates editors for public reactive properties with supported runtime metadata. Bare `@property()` declarations use Lit's default string metadata; internal `@state()` fields and properties with unsupported or unavailable metadata are skipped because TypeScript types are not available at runtime. Use `@property({ type: Object, attribute: false })` or `@property({ type: Array, attribute: false })` when a complex property should be editable.
251
+
252
+ ### 📱 Viewport Testing
253
+
254
+ Test your components across different screen sizes:
255
+
256
+ - **Phone** — 400px width
257
+ - **Phablet** — 600px width
258
+ - **Tablet** — 1024px width
259
+ - **Desktop** — Available preview width
260
+
261
+ On browser viewports up to 600px wide, the catalogue sidebar moves above the preview and the property controls wrap into a compact bottom toolbar. Selecting phone, phablet, or tablet still gives the preview container its exact target width; wider targets scroll inside the frame instead of widening the document.
262
+
263
+ ### 🌓 Theme Support
264
+
265
+ Components automatically adapt to light/dark themes. Use CSS custom properties with the theme manager:
266
+
267
+ ```typescript
268
+ import { cssManager } from '@design.estate/dees-element';
269
+
270
+ public static styles = [
271
+ css`
272
+ :host {
273
+ color: ${cssManager.bdTheme('#1a1a1a', '#e5e5e5')};
274
+ background: ${cssManager.bdTheme('#ffffff', '#0a0a0a')};
275
+ }
276
+ `
277
+ ];
278
+ ```
279
+
280
+ ### 🎬 Screen Recording
281
+
282
+ Record component demos directly from the catalogue with full export control:
283
+
284
+ - **Viewport Recording** — Record just the component viewport
285
+ - **Full Screen Recording** — Capture the entire screen
286
+ - **Audio Support** — Add microphone commentary with live level monitoring
287
+ - **Video Trimming** — Trim start/end before export with a visual timeline
288
+ - **60fps Capture** — Smooth, high-bitrate recording at up to 60 frames per second
289
+ - **MP4 Export** — Universal H.264/AAC format via [mediabunny](https://mediabunny.dev) WebCodecs conversion (plays everywhere: WhatsApp, iMessage, Slack, etc.)
290
+ - **WebM Export** — Native VP9 output for maximum quality
291
+
292
+ Click the red record button in the bottom toolbar, choose your format (MP4 or WebM), and start recording.
293
+
294
+ ### 🧪 Demo Tools
295
+
296
+ `DeesDemoWrapper` lives in `@design.estate/dees-element/demotools`; import it from there. The `@design.estate/dees-wcctools/demotools` re-export is removed in 5.0.0:
297
+
298
+ ```typescript
299
+ import '@design.estate/dees-element/demotools';
300
+
301
+ @customElement('my-component')
302
+ export class MyComponent extends DeesElement {
303
+ public static demo = () => html`
304
+ <dees-demowrapper .runAfterRender=${async (wrapper) => {
305
+ // Find elements using standard DOM APIs
306
+ const myComponent = wrapper.querySelector('my-component');
307
+
308
+ // Simulate user interactions
309
+ myComponent.value = 'Test value';
310
+ await myComponent.updateComplete;
311
+
312
+ // Work with multiple elements
313
+ wrapper.querySelectorAll('.item').forEach((el, i) => {
314
+ console.log(`Item ${i}:`, el.textContent);
315
+ });
316
+ }}>
317
+ <my-component></my-component>
318
+ <div class="item">Item 1</div>
319
+ <div class="item">Item 2</div>
320
+ </dees-demowrapper>
321
+ `;
322
+ }
323
+ ```
324
+
325
+ ### 🎭 Multiple Demos
326
+
327
+ Components can expose multiple demo variations:
328
+
329
+ ```typescript
330
+ @customElement('my-button')
331
+ export class MyButton extends DeesElement {
332
+ public static demo = [
333
+ () => html`<my-button variant="primary">Primary</my-button>`,
334
+ () => html`<my-button variant="secondary">Secondary</my-button>`,
335
+ () => html`<my-button variant="danger">Danger</my-button>`,
336
+ ];
337
+ }
338
+ ```
339
+
340
+ Each demo appears as a numbered item in an expandable folder in the sidebar.
341
+
342
+ ### 🗂️ Demo Groups
343
+
344
+ Organize elements into groups within a section for better discoverability:
345
+
346
+ ```typescript
347
+ @customElement('my-input')
348
+ export class MyInput extends DeesElement {
349
+ // Single group
350
+ public static demoGroups = 'Form Controls';
351
+
352
+ // Or multiple groups — element appears in each
353
+ public static demoGroups = ['Form Controls', 'Inputs'];
354
+
355
+ public static demo = () => html`<my-input></my-input>`;
356
+ }
357
+ ```
358
+
359
+ Groups appear as collapsible headers in the sidebar, sorted alphabetically. Searching matches group names too — searching "Form Controls" shows all elements in that group.
360
+
361
+ ### ⏳ Async Demos
362
+
363
+ Return a `Promise` from `demo` for async setup:
364
+
365
+ ```typescript
366
+ public static demo = async () => {
367
+ const data = await fetchSomeData();
368
+ return html`<my-component .data=${data}></my-component>`;
369
+ };
370
+ ```
371
+
372
+ ### 🎯 Container Queries
373
+
374
+ Components can respond to their container size using the `wccToolsViewport` container:
375
+
376
+ ```typescript
377
+ public static styles = [
378
+ css`
379
+ @container wccToolsViewport (min-width: 768px) {
380
+ :host {
381
+ flex-direction: row;
382
+ }
383
+ }
384
+
385
+ @container wccToolsViewport (max-width: 767px) {
386
+ :host {
387
+ flex-direction: column;
388
+ }
389
+ }
390
+ `
391
+ ];
392
+ ```
393
+
394
+ ## Component Guidelines
395
+
396
+ ### Required for Catalogue Display
397
+
398
+ 1. Components must expose a static `demo` property returning a Lit template (or a non-empty array of template factories); registered elements without one appear under **Without demo**
399
+ 2. Use `@property()` or `@property({ type: ... })` decorators with the `accessor` keyword for editable properties
400
+ 3. Export component classes for proper detection
401
+
402
+ ### Best Practices
403
+
404
+ ```typescript
405
+ @customElement('best-practice-component')
406
+ export class BestPracticeComponent extends DeesElement {
407
+ // ✅ Static demo property (single or array)
408
+ public static demo = () => html`
409
+ <best-practice-component
410
+ .complexProp=${{ key: 'value' }}
411
+ simpleAttribute="test"
412
+ ></best-practice-component>
413
+ `;
414
+
415
+ // ✅ Typed properties with defaults (TC39 decorators)
416
+ @property({ type: String })
417
+ accessor title: string = 'Default Title';
418
+
419
+ // ✅ Complex property without attribute
420
+ @property({ type: Object, attribute: false })
421
+ accessor complexProp: { key: string } = { key: 'default' };
422
+
423
+ // ✅ String editor with a compile-time union
424
+ @property({ type: String })
425
+ accessor variant: 'small' | 'medium' | 'large' = 'medium';
426
+ }
427
+ ```
428
+
429
+ ## Keyboard Use
430
+
431
+ The sidebar is an ARIA tree with a single tab stop (the selected entry, or the last focused one):
432
+
433
+ | Key | Action |
434
+ |-----|--------|
435
+ | `Tab` / `Shift+Tab` | Move between the search field, the tree, the resize handle and the toolbar |
436
+ | `↓` in the search field | Enter the tree |
437
+ | `Esc` in the search field | Clear the search |
438
+ | `↑` / `↓` | Previous / next visible entry |
439
+ | `Home` / `End` | First / last visible entry |
440
+ | `→` | Expand a section, demo folder or **Without demo**; on an expanded one, move to its first child |
441
+ | `←` | Collapse; on a collapsed or leaf entry, move to its parent |
442
+ | `Enter` / `Space` | Open the entry (or toggle a header) |
443
+ | `ContextMenu` / `Shift+F10` | Open the entry's context menu (pin, show in group) at the entry; `↑` / `↓` / `Home` / `End` move, `Enter` / `Space` act, `Esc` / `Tab` close — focus returns to the entry |
444
+
445
+ The sidebar resize handle is a focusable separator: `←` / `→` resize by 10 px (`Shift` for 50 px), `Home` / `End` jump to the minimum / maximum width. Theme and viewport controls are toggle buttons (`aria-pressed`), and `Esc` leaves the native viewport.
446
+
447
+ Rendered demos keep their state while you search, pin, resize the sidebar, or switch theme or viewport; only selecting another entry or demo renders a new one.
448
+
449
+ ## URL Routing
450
+
451
+ The catalogue uses URL routing for deep linking:
452
+
453
+ ```
454
+ /wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme
455
+
456
+ Examples:
457
+ /wcctools-route/Elements/my-button/0/desktop/dark
458
+ /wcctools-route/Views/view-dashboard/0/tablet/bright
459
+ /wcctools-route/Pages/home/0/desktop/dark
460
+ ```
461
+
462
+ ## API Reference
463
+
464
+ ### `setupWccTools(config)`
465
+
466
+ Initialize the WCC Tools dashboard with sections configuration.
467
+
468
+ ```typescript
469
+ interface IWccSection {
470
+ name: string;
471
+ type: 'elements' | 'pages';
472
+ items: Record<string, any>;
473
+ filter?: (name: string, item: any) => boolean;
474
+ sort?: (a: [string, any], b: [string, any]) => number;
475
+ icon?: string;
476
+ collapsed?: boolean;
477
+ }
478
+
479
+ interface IWccConfig {
480
+ sections: IWccSection[];
481
+ }
482
+
483
+ setupWccTools(config: IWccConfig): void;
484
+ ```
485
+
486
+ ### `DeesDemoWrapper`
487
+
488
+ Component for wrapping demos with post-render logic, imported from `@design.estate/dees-element/demotools`.
489
+
490
+ | Property | Type | Description |
491
+ |----------|------|-------------|
492
+ | `runAfterRender` | `(wrapper) => void \| Promise<void>` | Callback after wrapped elements render |
493
+
494
+ The wrapper provides full DOM API access:
495
+ - `wrapper.querySelector()` — Find single element
496
+ - `wrapper.querySelectorAll()` — Find multiple elements
497
+ - `wrapper.children` — Access child elements directly
498
+
499
+ ### Recording Components (Advanced)
500
+
501
+ For custom recording integrations:
502
+
503
+ ```typescript
504
+ import { RecorderService, type TOutputFormat } from '@design.estate/wcctools';
505
+
506
+ const recorder = new RecorderService({
507
+ onDurationUpdate: (duration) => console.log(`${duration}s`),
508
+ onRecordingComplete: (blob) => console.log('Recording done!', blob),
509
+ onAudioLevelUpdate: (level) => console.log(`Audio: ${level}%`),
510
+ });
511
+
512
+ // Record (always captures as WebM internally)
513
+ await recorder.startRecording({ mode: 'viewport' });
514
+ // ... later
515
+ recorder.stopRecording();
516
+
517
+ // Convert to MP4 for universal playback (H.264 + AAC via WebCodecs)
518
+ const mp4Blob = await recorder.convertToMp4(recorder.recordedBlob);
519
+ ```
520
+
521
+ ## Project Structure
522
+
523
+ ```
524
+ my-component-library/
525
+ ├── src/
526
+ │ ├── elements/ # UI components
527
+ │ │ ├── my-button.ts
528
+ │ │ ├── my-card.ts
529
+ │ │ └── index.ts
530
+ │ ├── views/ # Full-page layouts
531
+ │ │ ├── view-dashboard.ts
532
+ │ │ └── index.ts
533
+ │ ├── pages/ # Documentation pages
534
+ │ │ ├── home.ts
535
+ │ │ └── index.ts
536
+ │ └── catalogue.ts # WCC Tools setup
537
+ ├── html/
538
+ │ └── index.html
539
+ └── package.json
540
+ ```
541
+
542
+ ## Browser Support
543
+
544
+ - ✅ Chrome/Edge (latest)
545
+ - ✅ Firefox (latest)
546
+ - ✅ Safari (latest)
547
+ - ✅ Mobile browsers with Web Components support
548
+
549
+ ## License and Legal Information
550
+
551
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license.md) file.
552
+
553
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
554
+
555
+ ### Trademarks
556
+
557
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
558
+
559
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
560
+
561
+ ### Company Information
562
+
563
+ Task Venture Capital GmbH
564
+ Registered at District Court Bremen HRB 35230 HB, Germany
565
+
566
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
567
+
568
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.