@design.estate/dees-wcctools 3.2.0 → 3.3.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.
- package/dist_bundle/bundle.js +285 -111
- package/dist_bundle/bundle.js.map +3 -3
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/wcc-dashboard.d.ts +19 -8
- package/dist_ts_web/elements/wcc-dashboard.js +110 -43
- package/dist_ts_web/elements/wcc-sidebar.d.ts +17 -2
- package/dist_ts_web/elements/wcc-sidebar.js +179 -77
- package/dist_ts_web/index.d.ts +21 -1
- package/dist_ts_web/index.js +55 -3
- package/dist_ts_web/wcctools.interfaces.d.ts +29 -0
- package/dist_ts_web/wcctools.interfaces.js +2 -0
- package/dist_watch/bundle.js +1368 -162
- package/dist_watch/bundle.js.map +4 -4
- package/package.json +1 -1
- package/readme.hints.md +62 -0
- package/readme.md +158 -73
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/wcc-dashboard.ts +107 -35
- package/ts_web/elements/wcc-sidebar.ts +208 -95
- package/ts_web/index.ts +67 -2
- package/ts_web/readme.md +55 -5
- package/ts_web/wcctools.interfaces.ts +31 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as plugins from '../wcctools.plugins.js';
|
|
2
2
|
import { DeesElement, property, html, customElement, type TemplateResult, state } from '@design.estate/dees-element';
|
|
3
|
-
import { WccDashboard } from './wcc-dashboard.js';
|
|
3
|
+
import { WccDashboard, getSectionItems } from './wcc-dashboard.js';
|
|
4
4
|
import type { TTemplateFactory } from './wcctools.helpers.js';
|
|
5
5
|
import { getDemoCount, hasMultipleDemos } from './wcctools.helpers.js';
|
|
6
|
-
|
|
7
|
-
export type TElementType = 'element' | 'page';
|
|
6
|
+
import type { IWccSection, TElementType } from '../wcctools.interfaces.js';
|
|
8
7
|
|
|
9
8
|
@customElement('wcc-sidebar')
|
|
10
9
|
export class WccSidebar extends DeesElement {
|
|
@@ -24,6 +23,12 @@ export class WccSidebar extends DeesElement {
|
|
|
24
23
|
@state()
|
|
25
24
|
accessor expandedElements: Set<string> = new Set();
|
|
26
25
|
|
|
26
|
+
// Track which sections are collapsed
|
|
27
|
+
@state()
|
|
28
|
+
accessor collapsedSections: Set<string> = new Set();
|
|
29
|
+
|
|
30
|
+
private sectionsInitialized = false;
|
|
31
|
+
|
|
27
32
|
public render(): TemplateResult {
|
|
28
33
|
return html`
|
|
29
34
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet" />
|
|
@@ -65,7 +70,7 @@ export class WccSidebar extends DeesElement {
|
|
|
65
70
|
padding: 0.5rem 0;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
|
|
73
|
+
.section-header {
|
|
69
74
|
padding: 0.3rem 0.75rem;
|
|
70
75
|
font-size: 0.65rem;
|
|
71
76
|
font-weight: 500;
|
|
@@ -77,12 +82,45 @@ export class WccSidebar extends DeesElement {
|
|
|
77
82
|
background: rgba(59, 130, 246, 0.03);
|
|
78
83
|
border-bottom: 1px solid var(--border);
|
|
79
84
|
border-top: 1px solid var(--border);
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 0.5rem;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
user-select: none;
|
|
90
|
+
transition: all 0.15s ease;
|
|
80
91
|
}
|
|
81
92
|
|
|
82
|
-
|
|
93
|
+
.section-header:first-child {
|
|
83
94
|
margin-top: 0;
|
|
84
95
|
}
|
|
85
96
|
|
|
97
|
+
.section-header:hover {
|
|
98
|
+
background: rgba(59, 130, 246, 0.08);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.section-header .expand-icon {
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
opacity: 0.5;
|
|
104
|
+
transition: transform 0.2s ease;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.section-header.collapsed .expand-icon {
|
|
108
|
+
transform: rotate(-90deg);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.section-header .section-icon {
|
|
112
|
+
font-size: 14px;
|
|
113
|
+
opacity: 0.6;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.section-content {
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.section-content.collapsed {
|
|
121
|
+
display: none;
|
|
122
|
+
}
|
|
123
|
+
|
|
86
124
|
.material-symbols-outlined {
|
|
87
125
|
font-family: 'Material Symbols Outlined';
|
|
88
126
|
font-weight: normal;
|
|
@@ -216,88 +254,144 @@ export class WccSidebar extends DeesElement {
|
|
|
216
254
|
}
|
|
217
255
|
</style>
|
|
218
256
|
<div class="menu">
|
|
219
|
-
|
|
220
|
-
${(() => {
|
|
221
|
-
const pages = Object.keys(this.dashboardRef.pages);
|
|
222
|
-
return pages.map(pageName => {
|
|
223
|
-
const item = this.dashboardRef.pages[pageName];
|
|
224
|
-
return html`
|
|
225
|
-
<div
|
|
226
|
-
class="selectOption ${this.selectedItem === item ? 'selected' : null}"
|
|
227
|
-
@click=${async () => {
|
|
228
|
-
const domtools = await plugins.deesDomtools.DomTools.setupDomTools();
|
|
229
|
-
this.selectItem('page', pageName, item, 0);
|
|
230
|
-
}}
|
|
231
|
-
>
|
|
232
|
-
<i class="material-symbols-outlined">insert_drive_file</i>
|
|
233
|
-
<div class="text">${pageName}</div>
|
|
234
|
-
</div>
|
|
235
|
-
`;
|
|
236
|
-
});
|
|
237
|
-
})()}
|
|
238
|
-
<h3>Elements</h3>
|
|
239
|
-
${(() => {
|
|
240
|
-
const elements = Object.keys(this.dashboardRef.elements);
|
|
241
|
-
return elements.map(elementName => {
|
|
242
|
-
const item = this.dashboardRef.elements[elementName] as any;
|
|
243
|
-
const demoCount = item.demo ? getDemoCount(item.demo) : 0;
|
|
244
|
-
const isMultiDemo = item.demo && hasMultipleDemos(item.demo);
|
|
245
|
-
const isExpanded = this.expandedElements.has(elementName);
|
|
246
|
-
const isSelected = this.selectedItem === item;
|
|
247
|
-
|
|
248
|
-
if (isMultiDemo) {
|
|
249
|
-
// Multi-demo element - render as expandable folder
|
|
250
|
-
return html`
|
|
251
|
-
<div
|
|
252
|
-
class="selectOption folder ${isExpanded ? 'expanded' : ''} ${isSelected ? 'selected' : ''}"
|
|
253
|
-
@click=${() => this.toggleExpanded(elementName)}
|
|
254
|
-
>
|
|
255
|
-
<i class="material-symbols-outlined expand-icon">chevron_right</i>
|
|
256
|
-
<i class="material-symbols-outlined">folder</i>
|
|
257
|
-
<div class="text">${elementName}</div>
|
|
258
|
-
</div>
|
|
259
|
-
${isExpanded ? html`
|
|
260
|
-
<div class="demo-children">
|
|
261
|
-
${Array.from({ length: demoCount }, (_, i) => {
|
|
262
|
-
const demoIndex = i;
|
|
263
|
-
const isThisDemoSelected = isSelected && this.dashboardRef.selectedDemoIndex === demoIndex;
|
|
264
|
-
return html`
|
|
265
|
-
<div
|
|
266
|
-
class="demo-child ${isThisDemoSelected ? 'selected' : ''}"
|
|
267
|
-
@click=${async () => {
|
|
268
|
-
await plugins.deesDomtools.DomTools.setupDomTools();
|
|
269
|
-
this.selectItem('element', elementName, item, demoIndex);
|
|
270
|
-
}}
|
|
271
|
-
>
|
|
272
|
-
<i class="material-symbols-outlined">play_circle</i>
|
|
273
|
-
<div class="text">demo${demoIndex + 1}</div>
|
|
274
|
-
</div>
|
|
275
|
-
`;
|
|
276
|
-
})}
|
|
277
|
-
</div>
|
|
278
|
-
` : null}
|
|
279
|
-
`;
|
|
280
|
-
} else {
|
|
281
|
-
// Single demo element - render as normal
|
|
282
|
-
return html`
|
|
283
|
-
<div
|
|
284
|
-
class="selectOption ${isSelected ? 'selected' : null}"
|
|
285
|
-
@click=${async () => {
|
|
286
|
-
await plugins.deesDomtools.DomTools.setupDomTools();
|
|
287
|
-
this.selectItem('element', elementName, item, 0);
|
|
288
|
-
}}
|
|
289
|
-
>
|
|
290
|
-
<i class="material-symbols-outlined">featured_video</i>
|
|
291
|
-
<div class="text">${elementName}</div>
|
|
292
|
-
</div>
|
|
293
|
-
`;
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
})()}
|
|
257
|
+
${this.renderSections()}
|
|
297
258
|
</div>
|
|
298
259
|
`;
|
|
299
260
|
}
|
|
300
261
|
|
|
262
|
+
/**
|
|
263
|
+
* Initialize collapsed sections from section config
|
|
264
|
+
*/
|
|
265
|
+
private initCollapsedSections() {
|
|
266
|
+
if (this.sectionsInitialized) return;
|
|
267
|
+
|
|
268
|
+
const collapsed = new Set<string>();
|
|
269
|
+
for (const section of this.dashboardRef.sections) {
|
|
270
|
+
if (section.collapsed) {
|
|
271
|
+
collapsed.add(section.name);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
this.collapsedSections = collapsed;
|
|
275
|
+
this.sectionsInitialized = true;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Render all sections
|
|
280
|
+
*/
|
|
281
|
+
private renderSections() {
|
|
282
|
+
this.initCollapsedSections();
|
|
283
|
+
|
|
284
|
+
return this.dashboardRef.sections.map((section, index) => {
|
|
285
|
+
const isCollapsed = this.collapsedSections.has(section.name);
|
|
286
|
+
const sectionIcon = section.icon || (section.type === 'pages' ? 'insert_drive_file' : 'widgets');
|
|
287
|
+
|
|
288
|
+
return html`
|
|
289
|
+
<div
|
|
290
|
+
class="section-header ${isCollapsed ? 'collapsed' : ''}"
|
|
291
|
+
@click=${() => this.toggleSectionCollapsed(section.name)}
|
|
292
|
+
>
|
|
293
|
+
<i class="material-symbols-outlined expand-icon">expand_more</i>
|
|
294
|
+
${section.icon ? html`<i class="material-symbols-outlined section-icon">${section.icon}</i>` : null}
|
|
295
|
+
<span>${section.name}</span>
|
|
296
|
+
</div>
|
|
297
|
+
<div class="section-content ${isCollapsed ? 'collapsed' : ''}">
|
|
298
|
+
${this.renderSectionItems(section)}
|
|
299
|
+
</div>
|
|
300
|
+
`;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Render items for a section
|
|
306
|
+
*/
|
|
307
|
+
private renderSectionItems(section: IWccSection) {
|
|
308
|
+
const entries = getSectionItems(section);
|
|
309
|
+
|
|
310
|
+
if (section.type === 'pages') {
|
|
311
|
+
return entries.map(([pageName, item]) => {
|
|
312
|
+
return html`
|
|
313
|
+
<div
|
|
314
|
+
class="selectOption ${this.selectedItem === item ? 'selected' : ''}"
|
|
315
|
+
@click=${async () => {
|
|
316
|
+
await plugins.deesDomtools.DomTools.setupDomTools();
|
|
317
|
+
this.selectItem('page', pageName, item, 0, section);
|
|
318
|
+
}}
|
|
319
|
+
>
|
|
320
|
+
<i class="material-symbols-outlined">insert_drive_file</i>
|
|
321
|
+
<div class="text">${pageName}</div>
|
|
322
|
+
</div>
|
|
323
|
+
`;
|
|
324
|
+
});
|
|
325
|
+
} else {
|
|
326
|
+
// type === 'elements'
|
|
327
|
+
return entries.map(([elementName, item]) => {
|
|
328
|
+
const anonItem = item as any;
|
|
329
|
+
const demoCount = anonItem.demo ? getDemoCount(anonItem.demo) : 0;
|
|
330
|
+
const isMultiDemo = anonItem.demo && hasMultipleDemos(anonItem.demo);
|
|
331
|
+
const isExpanded = this.expandedElements.has(elementName);
|
|
332
|
+
const isSelected = this.selectedItem === item;
|
|
333
|
+
|
|
334
|
+
if (isMultiDemo) {
|
|
335
|
+
// Multi-demo element - render as expandable folder
|
|
336
|
+
return html`
|
|
337
|
+
<div
|
|
338
|
+
class="selectOption folder ${isExpanded ? 'expanded' : ''} ${isSelected ? 'selected' : ''}"
|
|
339
|
+
@click=${() => this.toggleExpanded(elementName)}
|
|
340
|
+
>
|
|
341
|
+
<i class="material-symbols-outlined expand-icon">chevron_right</i>
|
|
342
|
+
<i class="material-symbols-outlined">folder</i>
|
|
343
|
+
<div class="text">${elementName}</div>
|
|
344
|
+
</div>
|
|
345
|
+
${isExpanded ? html`
|
|
346
|
+
<div class="demo-children">
|
|
347
|
+
${Array.from({ length: demoCount }, (_, i) => {
|
|
348
|
+
const demoIndex = i;
|
|
349
|
+
const isThisDemoSelected = isSelected && this.dashboardRef.selectedDemoIndex === demoIndex;
|
|
350
|
+
return html`
|
|
351
|
+
<div
|
|
352
|
+
class="demo-child ${isThisDemoSelected ? 'selected' : ''}"
|
|
353
|
+
@click=${async () => {
|
|
354
|
+
await plugins.deesDomtools.DomTools.setupDomTools();
|
|
355
|
+
this.selectItem('element', elementName, item, demoIndex, section);
|
|
356
|
+
}}
|
|
357
|
+
>
|
|
358
|
+
<i class="material-symbols-outlined">play_circle</i>
|
|
359
|
+
<div class="text">demo${demoIndex + 1}</div>
|
|
360
|
+
</div>
|
|
361
|
+
`;
|
|
362
|
+
})}
|
|
363
|
+
</div>
|
|
364
|
+
` : null}
|
|
365
|
+
`;
|
|
366
|
+
} else {
|
|
367
|
+
// Single demo element
|
|
368
|
+
return html`
|
|
369
|
+
<div
|
|
370
|
+
class="selectOption ${isSelected ? 'selected' : ''}"
|
|
371
|
+
@click=${async () => {
|
|
372
|
+
await plugins.deesDomtools.DomTools.setupDomTools();
|
|
373
|
+
this.selectItem('element', elementName, item, 0, section);
|
|
374
|
+
}}
|
|
375
|
+
>
|
|
376
|
+
<i class="material-symbols-outlined">featured_video</i>
|
|
377
|
+
<div class="text">${elementName}</div>
|
|
378
|
+
</div>
|
|
379
|
+
`;
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private toggleSectionCollapsed(sectionName: string) {
|
|
386
|
+
const newSet = new Set(this.collapsedSections);
|
|
387
|
+
if (newSet.has(sectionName)) {
|
|
388
|
+
newSet.delete(sectionName);
|
|
389
|
+
} else {
|
|
390
|
+
newSet.add(sectionName);
|
|
391
|
+
}
|
|
392
|
+
this.collapsedSections = newSet;
|
|
393
|
+
}
|
|
394
|
+
|
|
301
395
|
private toggleExpanded(elementName: string) {
|
|
302
396
|
const newSet = new Set(this.expandedElements);
|
|
303
397
|
if (newSet.has(elementName)) {
|
|
@@ -313,30 +407,50 @@ export class WccSidebar extends DeesElement {
|
|
|
313
407
|
|
|
314
408
|
// Auto-expand folder when a multi-demo element is selected
|
|
315
409
|
if (changedProperties.has('selectedItem') && this.selectedItem) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
410
|
+
// Find the element in any section
|
|
411
|
+
for (const section of this.dashboardRef.sections) {
|
|
412
|
+
if (section.type !== 'elements') continue;
|
|
413
|
+
|
|
414
|
+
const entries = getSectionItems(section);
|
|
415
|
+
const found = entries.find(([_, item]) => item === this.selectedItem);
|
|
416
|
+
if (found) {
|
|
417
|
+
const [elementName, item] = found;
|
|
418
|
+
const anonItem = item as any;
|
|
419
|
+
if (anonItem.demo && hasMultipleDemos(anonItem.demo)) {
|
|
420
|
+
if (!this.expandedElements.has(elementName)) {
|
|
421
|
+
const newSet = new Set(this.expandedElements);
|
|
422
|
+
newSet.add(elementName);
|
|
423
|
+
this.expandedElements = newSet;
|
|
424
|
+
}
|
|
326
425
|
}
|
|
426
|
+
break;
|
|
327
427
|
}
|
|
328
428
|
}
|
|
329
429
|
}
|
|
330
430
|
}
|
|
331
431
|
|
|
332
|
-
public selectItem(
|
|
432
|
+
public selectItem(
|
|
433
|
+
typeArg: TElementType,
|
|
434
|
+
itemNameArg: string,
|
|
435
|
+
itemArg: TTemplateFactory | DeesElement,
|
|
436
|
+
demoIndex: number = 0,
|
|
437
|
+
section?: IWccSection
|
|
438
|
+
) {
|
|
333
439
|
console.log('selected item');
|
|
334
440
|
console.log(itemNameArg);
|
|
335
441
|
console.log(itemArg);
|
|
336
442
|
console.log('demo index:', demoIndex);
|
|
443
|
+
console.log('section:', section?.name);
|
|
444
|
+
|
|
337
445
|
this.selectedItem = itemArg;
|
|
338
446
|
this.selectedType = typeArg;
|
|
339
447
|
this.dashboardRef.selectedDemoIndex = demoIndex;
|
|
448
|
+
|
|
449
|
+
// Set the selected section on dashboard
|
|
450
|
+
if (section) {
|
|
451
|
+
this.dashboardRef.selectedSection = section;
|
|
452
|
+
}
|
|
453
|
+
|
|
340
454
|
this.dispatchEvent(
|
|
341
455
|
new CustomEvent('selectedType', {
|
|
342
456
|
detail: typeArg
|
|
@@ -356,7 +470,6 @@ export class WccSidebar extends DeesElement {
|
|
|
356
470
|
this.dashboardRef.buildUrl();
|
|
357
471
|
|
|
358
472
|
// Force re-render to update demo child selection indicator
|
|
359
|
-
// (needed when switching between demos of the same element)
|
|
360
473
|
this.requestUpdate();
|
|
361
474
|
}
|
|
362
475
|
}
|
package/ts_web/index.ts
CHANGED
|
@@ -1,21 +1,86 @@
|
|
|
1
1
|
import { WccDashboard } from './elements/wcc-dashboard.js';
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
import type { TTemplateFactory } from './elements/wcctools.helpers.js';
|
|
4
|
+
import type { IWccConfig, IWccSection } from './wcctools.interfaces.js';
|
|
4
5
|
|
|
5
6
|
// Export recording components and service
|
|
6
7
|
export { RecorderService, type IRecorderEvents, type IRecordingOptions } from './services/recorder.service.js';
|
|
7
8
|
export { WccRecordButton } from './elements/wcc-record-button.js';
|
|
8
9
|
export { WccRecordingPanel } from './elements/wcc-recording-panel.js';
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
// Export types for external use
|
|
12
|
+
export type { IWccConfig, IWccSection } from './wcctools.interfaces.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Converts legacy (elements, pages) format to new sections config
|
|
16
|
+
*/
|
|
17
|
+
const convertLegacyToConfig = (
|
|
11
18
|
elementsArg?: { [key: string]: LitElement },
|
|
12
19
|
pagesArg?: Record<string, TTemplateFactory>
|
|
20
|
+
): IWccConfig => {
|
|
21
|
+
const sections: IWccSection[] = [];
|
|
22
|
+
|
|
23
|
+
if (pagesArg && Object.keys(pagesArg).length > 0) {
|
|
24
|
+
sections.push({
|
|
25
|
+
name: 'Pages',
|
|
26
|
+
type: 'pages',
|
|
27
|
+
items: pagesArg,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (elementsArg && Object.keys(elementsArg).length > 0) {
|
|
32
|
+
sections.push({
|
|
33
|
+
name: 'Elements',
|
|
34
|
+
type: 'elements',
|
|
35
|
+
items: elementsArg,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return { sections };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if the argument is the new config format
|
|
44
|
+
*/
|
|
45
|
+
const isWccConfig = (arg: any): arg is IWccConfig => {
|
|
46
|
+
return arg && typeof arg === 'object' && 'sections' in arg && Array.isArray(arg.sections);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Setup WCC Tools dashboard
|
|
51
|
+
*
|
|
52
|
+
* New format (recommended):
|
|
53
|
+
* ```typescript
|
|
54
|
+
* setupWccTools({
|
|
55
|
+
* sections: [
|
|
56
|
+
* { name: 'Elements', type: 'elements', items: elements },
|
|
57
|
+
* { name: 'Pages', type: 'pages', items: pages },
|
|
58
|
+
* ]
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* Legacy format (still supported):
|
|
63
|
+
* ```typescript
|
|
64
|
+
* setupWccTools(elements, pages);
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
const setupWccTools = (
|
|
68
|
+
configOrElements?: IWccConfig | { [key: string]: LitElement },
|
|
69
|
+
pagesArg?: Record<string, TTemplateFactory>
|
|
13
70
|
) => {
|
|
71
|
+
let config: IWccConfig;
|
|
72
|
+
|
|
73
|
+
if (isWccConfig(configOrElements)) {
|
|
74
|
+
config = configOrElements;
|
|
75
|
+
} else {
|
|
76
|
+
config = convertLegacyToConfig(configOrElements, pagesArg);
|
|
77
|
+
}
|
|
78
|
+
|
|
14
79
|
let hasRun = false;
|
|
15
80
|
const runWccToolsSetup = async () => {
|
|
16
81
|
if (document.readyState === 'complete' && !hasRun) {
|
|
17
82
|
hasRun = true;
|
|
18
|
-
const wccTools = new WccDashboard(
|
|
83
|
+
const wccTools = new WccDashboard(config);
|
|
19
84
|
document.querySelector('body').append(wccTools);
|
|
20
85
|
}
|
|
21
86
|
};
|
package/ts_web/readme.md
CHANGED
|
@@ -14,6 +14,40 @@ pnpm add -D @design.estate/dees-wcctools
|
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
|
+
### Sections-based Configuration (Recommended)
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { setupWccTools } from '@design.estate/dees-wcctools';
|
|
21
|
+
import * as elements from './elements/index.js';
|
|
22
|
+
import * as views from './views/index.js';
|
|
23
|
+
import * as pages from './pages/index.js';
|
|
24
|
+
|
|
25
|
+
setupWccTools({
|
|
26
|
+
sections: [
|
|
27
|
+
{
|
|
28
|
+
name: 'Pages',
|
|
29
|
+
type: 'pages',
|
|
30
|
+
items: pages,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'Views',
|
|
34
|
+
type: 'elements',
|
|
35
|
+
items: views,
|
|
36
|
+
icon: 'web',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Elements',
|
|
40
|
+
type: 'elements',
|
|
41
|
+
items: elements,
|
|
42
|
+
filter: (name) => !name.startsWith('internal-'),
|
|
43
|
+
sort: ([a], [b]) => a.localeCompare(b),
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Legacy Format (Still Supported)
|
|
50
|
+
|
|
17
51
|
```typescript
|
|
18
52
|
import { setupWccTools } from '@design.estate/dees-wcctools';
|
|
19
53
|
import { MyButton } from './components/my-button.js';
|
|
@@ -30,6 +64,8 @@ setupWccTools({
|
|
|
30
64
|
| Export | Description |
|
|
31
65
|
|--------|-------------|
|
|
32
66
|
| `setupWccTools` | Initialize the component catalogue dashboard |
|
|
67
|
+
| `IWccConfig` | TypeScript interface for sections configuration |
|
|
68
|
+
| `IWccSection` | TypeScript interface for individual section |
|
|
33
69
|
|
|
34
70
|
### Recording Components
|
|
35
71
|
|
|
@@ -41,6 +77,18 @@ setupWccTools({
|
|
|
41
77
|
| `IRecorderEvents` | TypeScript interface for recorder callbacks |
|
|
42
78
|
| `IRecordingOptions` | TypeScript interface for recording options |
|
|
43
79
|
|
|
80
|
+
## Section Configuration
|
|
81
|
+
|
|
82
|
+
| Property | Type | Description |
|
|
83
|
+
|----------|------|-------------|
|
|
84
|
+
| `name` | `string` | Display name for the section header |
|
|
85
|
+
| `type` | `'elements' \| 'pages'` | Rendering behavior |
|
|
86
|
+
| `items` | `Record<string, any>` | Element classes or page factories |
|
|
87
|
+
| `filter` | `(name, item) => boolean` | Optional filter function |
|
|
88
|
+
| `sort` | `([a, itemA], [b, itemB]) => number` | Optional sort function |
|
|
89
|
+
| `icon` | `string` | Material Symbols icon name |
|
|
90
|
+
| `collapsed` | `boolean` | Start section collapsed (default: false) |
|
|
91
|
+
|
|
44
92
|
## Internal Components
|
|
45
93
|
|
|
46
94
|
The module includes these internal web components:
|
|
@@ -48,8 +96,8 @@ The module includes these internal web components:
|
|
|
48
96
|
| Component | Description |
|
|
49
97
|
|-----------|-------------|
|
|
50
98
|
| `wcc-dashboard` | Main dashboard container with routing |
|
|
51
|
-
| `wcc-sidebar` | Navigation sidebar with
|
|
52
|
-
| `wcc-frame` |
|
|
99
|
+
| `wcc-sidebar` | Navigation sidebar with collapsible sections |
|
|
100
|
+
| `wcc-frame` | Responsive viewport with size controls |
|
|
53
101
|
| `wcc-properties` | Property panel with live editing |
|
|
54
102
|
| `wcc-record-button` | Recording state indicator button |
|
|
55
103
|
| `wcc-recording-panel` | Recording workflow UI |
|
|
@@ -72,14 +120,14 @@ const events: IRecorderEvents = {
|
|
|
72
120
|
const recorder = new RecorderService(events);
|
|
73
121
|
|
|
74
122
|
// Load available microphones
|
|
75
|
-
const mics = await recorder.loadMicrophones(true);
|
|
123
|
+
const mics = await recorder.loadMicrophones(true);
|
|
76
124
|
|
|
77
125
|
// Start audio level monitoring
|
|
78
126
|
await recorder.startAudioMonitoring(mics[0].deviceId);
|
|
79
127
|
|
|
80
128
|
// Start recording
|
|
81
129
|
await recorder.startRecording({
|
|
82
|
-
mode: 'viewport',
|
|
130
|
+
mode: 'viewport',
|
|
83
131
|
audioDeviceId: mics[0].deviceId,
|
|
84
132
|
viewportElement: document.querySelector('.viewport'),
|
|
85
133
|
});
|
|
@@ -99,10 +147,11 @@ recorder.dispose();
|
|
|
99
147
|
```
|
|
100
148
|
ts_web/
|
|
101
149
|
├── index.ts # Main exports
|
|
150
|
+
├── wcctools.interfaces.ts # Type definitions
|
|
102
151
|
├── elements/
|
|
103
152
|
│ ├── wcc-dashboard.ts # Root dashboard component
|
|
104
153
|
│ ├── wcc-sidebar.ts # Navigation sidebar
|
|
105
|
-
│ ├── wcc-frame.ts # Responsive
|
|
154
|
+
│ ├── wcc-frame.ts # Responsive viewport
|
|
106
155
|
│ ├── wcc-properties.ts # Property editing panel
|
|
107
156
|
│ ├── wcc-record-button.ts # Recording button
|
|
108
157
|
│ ├── wcc-recording-panel.ts # Recording options/preview
|
|
@@ -116,6 +165,7 @@ ts_web/
|
|
|
116
165
|
## Features
|
|
117
166
|
|
|
118
167
|
- 🎨 Interactive component preview
|
|
168
|
+
- 📂 Section-based sidebar with filtering & sorting
|
|
119
169
|
- 🔧 Real-time property editing with type detection
|
|
120
170
|
- 🌓 Theme switching (light/dark)
|
|
121
171
|
- 📱 Responsive viewport testing
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
/**
|
|
22
|
+
* Configuration object for setupWccTools
|
|
23
|
+
*/
|
|
24
|
+
export interface IWccConfig {
|
|
25
|
+
sections: IWccSection[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Type for element selection types - now section-based
|
|
30
|
+
*/
|
|
31
|
+
export type TElementType = 'element' | 'page';
|