@design.estate/dees-wcctools 1.2.1 → 2.0.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 +1764 -218
- package/dist_bundle/bundle.js.map +4 -4
- package/dist_ts_demotools/demotools.d.ts +1 -1
- package/dist_ts_demotools/demotools.js +86 -38
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/wcc-dashboard.d.ts +11 -10
- package/dist_ts_web/elements/wcc-dashboard.js +370 -246
- package/dist_ts_web/elements/wcc-frame.d.ts +3 -3
- package/dist_ts_web/elements/wcc-frame.js +108 -57
- package/dist_ts_web/elements/wcc-properties.d.ts +14 -8
- package/dist_ts_web/elements/wcc-properties.js +442 -323
- package/dist_ts_web/elements/wcc-record-button.d.ts +12 -0
- package/dist_ts_web/elements/wcc-record-button.js +165 -0
- package/dist_ts_web/elements/wcc-recording-panel.d.ts +42 -0
- package/dist_ts_web/elements/wcc-recording-panel.js +1067 -0
- package/dist_ts_web/elements/wcc-sidebar.d.ts +7 -5
- package/dist_ts_web/elements/wcc-sidebar.js +250 -81
- package/dist_ts_web/elements/wcctools.helpers.d.ts +13 -0
- package/dist_ts_web/elements/wcctools.helpers.js +26 -1
- package/dist_ts_web/index.d.ts +3 -0
- package/dist_ts_web/index.js +5 -1
- package/dist_ts_web/services/ffmpeg.service.d.ts +42 -0
- package/dist_ts_web/services/ffmpeg.service.js +276 -0
- package/dist_ts_web/services/mp4.service.d.ts +32 -0
- package/dist_ts_web/services/mp4.service.js +139 -0
- package/dist_ts_web/services/recorder.service.d.ts +44 -0
- package/dist_ts_web/services/recorder.service.js +307 -0
- package/dist_watch/bundle.js +2126 -541
- package/dist_watch/bundle.js.map +4 -4
- package/package.json +8 -8
- package/readme.md +133 -141
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/wcc-dashboard.ts +86 -26
- package/ts_web/elements/wcc-frame.ts +3 -3
- package/ts_web/elements/wcc-properties.ts +53 -9
- package/ts_web/elements/wcc-record-button.ts +108 -0
- package/ts_web/elements/wcc-recording-panel.ts +978 -0
- package/ts_web/elements/wcc-sidebar.ts +133 -22
- package/ts_web/elements/wcctools.helpers.ts +31 -0
- package/ts_web/index.ts +5 -0
- package/ts_web/readme.md +123 -0
- package/ts_web/services/recorder.service.ts +393 -0
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import * as plugins from '../wcctools.plugins.js';
|
|
2
|
-
import { DeesElement, property, html, customElement, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
import { DeesElement, property, html, customElement, type TemplateResult, state } from '@design.estate/dees-element';
|
|
3
3
|
import { WccDashboard } from './wcc-dashboard.js';
|
|
4
4
|
import type { TTemplateFactory } from './wcctools.helpers.js';
|
|
5
|
+
import { getDemoCount, hasMultipleDemos } from './wcctools.helpers.js';
|
|
5
6
|
|
|
6
7
|
export type TElementType = 'element' | 'page';
|
|
7
8
|
|
|
8
9
|
@customElement('wcc-sidebar')
|
|
9
10
|
export class WccSidebar extends DeesElement {
|
|
10
11
|
@property({ attribute: false })
|
|
11
|
-
|
|
12
|
+
accessor selectedItem: DeesElement | TTemplateFactory;
|
|
12
13
|
|
|
13
14
|
@property({ attribute: false })
|
|
14
|
-
|
|
15
|
+
accessor selectedType: TElementType;
|
|
15
16
|
|
|
16
17
|
@property()
|
|
17
|
-
|
|
18
|
+
accessor dashboardRef: WccDashboard;
|
|
18
19
|
|
|
19
20
|
@property()
|
|
20
|
-
|
|
21
|
+
accessor isFullscreen: boolean = false;
|
|
22
|
+
|
|
23
|
+
// Track which elements are expanded (for multi-demo elements)
|
|
24
|
+
@state()
|
|
25
|
+
accessor expandedElements: Set<string> = new Set();
|
|
21
26
|
|
|
22
27
|
public render(): TemplateResult {
|
|
23
28
|
return html`
|
|
@@ -110,7 +115,21 @@ export class WccSidebar extends DeesElement {
|
|
|
110
115
|
color: #999;
|
|
111
116
|
background: transparent;
|
|
112
117
|
}
|
|
113
|
-
|
|
118
|
+
|
|
119
|
+
.selectOption.folder {
|
|
120
|
+
grid-template-columns: 16px 20px 1fr;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.selectOption .expand-icon {
|
|
124
|
+
font-size: 14px;
|
|
125
|
+
opacity: 0.5;
|
|
126
|
+
transition: transform 0.2s ease;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.selectOption.expanded .expand-icon {
|
|
130
|
+
transform: rotate(90deg);
|
|
131
|
+
}
|
|
132
|
+
|
|
114
133
|
.selectOption:hover {
|
|
115
134
|
background: rgba(59, 130, 246, 0.05);
|
|
116
135
|
color: #bbb;
|
|
@@ -143,6 +162,42 @@ export class WccSidebar extends DeesElement {
|
|
|
143
162
|
font-weight: 400;
|
|
144
163
|
}
|
|
145
164
|
|
|
165
|
+
.demo-children {
|
|
166
|
+
margin-left: 1rem;
|
|
167
|
+
overflow: hidden;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.demo-child {
|
|
171
|
+
user-select: none;
|
|
172
|
+
position: relative;
|
|
173
|
+
margin: 0.125rem 0.5rem;
|
|
174
|
+
padding: 0.35rem 0.75rem;
|
|
175
|
+
transition: all 0.15s ease;
|
|
176
|
+
display: grid;
|
|
177
|
+
grid-template-columns: 16px 1fr;
|
|
178
|
+
align-items: center;
|
|
179
|
+
gap: 0.5rem;
|
|
180
|
+
border-radius: var(--radius);
|
|
181
|
+
cursor: pointer;
|
|
182
|
+
font-size: 0.7rem;
|
|
183
|
+
color: #777;
|
|
184
|
+
background: transparent;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.demo-child:hover {
|
|
188
|
+
background: rgba(59, 130, 246, 0.05);
|
|
189
|
+
color: #bbb;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.demo-child.selected {
|
|
193
|
+
background: rgba(59, 130, 246, 0.15);
|
|
194
|
+
color: var(--primary);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.demo-child .material-symbols-outlined {
|
|
198
|
+
font-size: 14px;
|
|
199
|
+
}
|
|
200
|
+
|
|
146
201
|
::-webkit-scrollbar {
|
|
147
202
|
width: 8px;
|
|
148
203
|
}
|
|
@@ -171,7 +226,7 @@ export class WccSidebar extends DeesElement {
|
|
|
171
226
|
class="selectOption ${this.selectedItem === item ? 'selected' : null}"
|
|
172
227
|
@click=${async () => {
|
|
173
228
|
const domtools = await plugins.deesDomtools.DomTools.setupDomTools();
|
|
174
|
-
this.selectItem('page', pageName, item);
|
|
229
|
+
this.selectItem('page', pageName, item, 0);
|
|
175
230
|
}}
|
|
176
231
|
>
|
|
177
232
|
<i class="material-symbols-outlined">insert_drive_file</i>
|
|
@@ -184,31 +239,83 @@ export class WccSidebar extends DeesElement {
|
|
|
184
239
|
${(() => {
|
|
185
240
|
const elements = Object.keys(this.dashboardRef.elements);
|
|
186
241
|
return elements.map(elementName => {
|
|
187
|
-
const item = this.dashboardRef.elements[elementName];
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
<
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
+
}
|
|
200
295
|
});
|
|
201
296
|
})()}
|
|
202
297
|
</div>
|
|
203
298
|
`;
|
|
204
299
|
}
|
|
205
300
|
|
|
206
|
-
|
|
301
|
+
private toggleExpanded(elementName: string) {
|
|
302
|
+
const newSet = new Set(this.expandedElements);
|
|
303
|
+
if (newSet.has(elementName)) {
|
|
304
|
+
newSet.delete(elementName);
|
|
305
|
+
} else {
|
|
306
|
+
newSet.add(elementName);
|
|
307
|
+
}
|
|
308
|
+
this.expandedElements = newSet;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
public selectItem(typeArg: TElementType, itemNameArg: string, itemArg: TTemplateFactory | DeesElement, demoIndex: number = 0) {
|
|
207
312
|
console.log('selected item');
|
|
208
313
|
console.log(itemNameArg);
|
|
209
314
|
console.log(itemArg);
|
|
315
|
+
console.log('demo index:', demoIndex);
|
|
210
316
|
this.selectedItem = itemArg;
|
|
211
317
|
this.selectedType = typeArg;
|
|
318
|
+
this.dashboardRef.selectedDemoIndex = demoIndex;
|
|
212
319
|
this.dispatchEvent(
|
|
213
320
|
new CustomEvent('selectedType', {
|
|
214
321
|
detail: typeArg
|
|
@@ -224,7 +331,11 @@ export class WccSidebar extends DeesElement {
|
|
|
224
331
|
detail: itemArg
|
|
225
332
|
})
|
|
226
333
|
);
|
|
227
|
-
|
|
334
|
+
|
|
228
335
|
this.dashboardRef.buildUrl();
|
|
336
|
+
|
|
337
|
+
// Force re-render to update demo child selection indicator
|
|
338
|
+
// (needed when switching between demos of the same element)
|
|
339
|
+
this.requestUpdate();
|
|
229
340
|
}
|
|
230
341
|
}
|
|
@@ -2,8 +2,39 @@ import type { TemplateResult } from 'lit';
|
|
|
2
2
|
|
|
3
3
|
export type TTemplateFactory = () => TemplateResult | Promise<TemplateResult>;
|
|
4
4
|
|
|
5
|
+
// Demo can be a single function or an array of functions
|
|
6
|
+
export type TDemoDefinition = TTemplateFactory | TTemplateFactory[];
|
|
7
|
+
|
|
5
8
|
export const resolveTemplateFactory = async (
|
|
6
9
|
factoryArg: TTemplateFactory
|
|
7
10
|
): Promise<TemplateResult> => {
|
|
8
11
|
return await Promise.resolve(factoryArg());
|
|
9
12
|
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get the number of demos for an element
|
|
16
|
+
*/
|
|
17
|
+
export const getDemoCount = (demo: TDemoDefinition): number => {
|
|
18
|
+
if (Array.isArray(demo)) {
|
|
19
|
+
return demo.length;
|
|
20
|
+
}
|
|
21
|
+
return 1;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get a specific demo by index (0-based internally, displayed as 1-based)
|
|
26
|
+
*/
|
|
27
|
+
export const getDemoAtIndex = (demo: TDemoDefinition, index: number): TTemplateFactory | null => {
|
|
28
|
+
if (Array.isArray(demo)) {
|
|
29
|
+
return demo[index] ?? null;
|
|
30
|
+
}
|
|
31
|
+
// Single demo - only index 0 is valid
|
|
32
|
+
return index === 0 ? demo : null;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if an element has multiple demos
|
|
37
|
+
*/
|
|
38
|
+
export const hasMultipleDemos = (demo: TDemoDefinition): boolean => {
|
|
39
|
+
return Array.isArray(demo) && demo.length > 1;
|
|
40
|
+
};
|
package/ts_web/index.ts
CHANGED
|
@@ -2,6 +2,11 @@ import { WccDashboard } from './elements/wcc-dashboard.js';
|
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
import type { TTemplateFactory } from './elements/wcctools.helpers.js';
|
|
4
4
|
|
|
5
|
+
// Export recording components and service
|
|
6
|
+
export { RecorderService, type IRecorderEvents, type IRecordingOptions } from './services/recorder.service.js';
|
|
7
|
+
export { WccRecordButton } from './elements/wcc-record-button.js';
|
|
8
|
+
export { WccRecordingPanel } from './elements/wcc-recording-panel.js';
|
|
9
|
+
|
|
5
10
|
const setupWccTools = (
|
|
6
11
|
elementsArg?: { [key: string]: LitElement },
|
|
7
12
|
pagesArg?: Record<string, TTemplateFactory>
|
package/ts_web/readme.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# @design.estate/dees-wcctools
|
|
2
|
+
|
|
3
|
+
🛠️ **Web Component Catalogue Tools** — The core dashboard and UI components for building interactive component catalogues
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This is the main module of `@design.estate/dees-wcctools`, providing the complete dashboard experience for developing, testing, and documenting web components.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add -D @design.estate/dees-wcctools
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { setupWccTools } from '@design.estate/dees-wcctools';
|
|
19
|
+
import { MyButton } from './components/my-button.js';
|
|
20
|
+
|
|
21
|
+
setupWccTools({
|
|
22
|
+
'my-button': MyButton,
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Exports
|
|
27
|
+
|
|
28
|
+
### Main Entry Point
|
|
29
|
+
|
|
30
|
+
| Export | Description |
|
|
31
|
+
|--------|-------------|
|
|
32
|
+
| `setupWccTools` | Initialize the component catalogue dashboard |
|
|
33
|
+
|
|
34
|
+
### Recording Components
|
|
35
|
+
|
|
36
|
+
| Export | Description |
|
|
37
|
+
|--------|-------------|
|
|
38
|
+
| `RecorderService` | Service class for screen/viewport recording |
|
|
39
|
+
| `WccRecordButton` | Record button UI component |
|
|
40
|
+
| `WccRecordingPanel` | Recording options and preview panel |
|
|
41
|
+
| `IRecorderEvents` | TypeScript interface for recorder callbacks |
|
|
42
|
+
| `IRecordingOptions` | TypeScript interface for recording options |
|
|
43
|
+
|
|
44
|
+
## Internal Components
|
|
45
|
+
|
|
46
|
+
The module includes these internal web components:
|
|
47
|
+
|
|
48
|
+
| Component | Description |
|
|
49
|
+
|-----------|-------------|
|
|
50
|
+
| `wcc-dashboard` | Main dashboard container with routing |
|
|
51
|
+
| `wcc-sidebar` | Navigation sidebar with element/page listing |
|
|
52
|
+
| `wcc-frame` | Iframe viewport with responsive sizing |
|
|
53
|
+
| `wcc-properties` | Property panel with live editing |
|
|
54
|
+
| `wcc-record-button` | Recording state indicator button |
|
|
55
|
+
| `wcc-recording-panel` | Recording workflow UI |
|
|
56
|
+
|
|
57
|
+
## RecorderService API
|
|
58
|
+
|
|
59
|
+
For programmatic recording control:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { RecorderService, type IRecorderEvents } from '@design.estate/dees-wcctools';
|
|
63
|
+
|
|
64
|
+
const events: IRecorderEvents = {
|
|
65
|
+
onDurationUpdate: (duration) => console.log(`Recording: ${duration}s`),
|
|
66
|
+
onRecordingComplete: (blob) => saveBlob(blob),
|
|
67
|
+
onAudioLevelUpdate: (level) => updateMeter(level),
|
|
68
|
+
onError: (error) => console.error(error),
|
|
69
|
+
onStreamEnded: () => console.log('User stopped sharing'),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const recorder = new RecorderService(events);
|
|
73
|
+
|
|
74
|
+
// Load available microphones
|
|
75
|
+
const mics = await recorder.loadMicrophones(true); // true = request permission
|
|
76
|
+
|
|
77
|
+
// Start audio level monitoring
|
|
78
|
+
await recorder.startAudioMonitoring(mics[0].deviceId);
|
|
79
|
+
|
|
80
|
+
// Start recording
|
|
81
|
+
await recorder.startRecording({
|
|
82
|
+
mode: 'viewport', // or 'screen'
|
|
83
|
+
audioDeviceId: mics[0].deviceId,
|
|
84
|
+
viewportElement: document.querySelector('.viewport'),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Stop recording
|
|
88
|
+
recorder.stopRecording();
|
|
89
|
+
|
|
90
|
+
// Export trimmed video
|
|
91
|
+
const trimmedBlob = await recorder.exportTrimmedVideo(videoElement, startTime, endTime);
|
|
92
|
+
|
|
93
|
+
// Cleanup
|
|
94
|
+
recorder.dispose();
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Architecture
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
ts_web/
|
|
101
|
+
├── index.ts # Main exports
|
|
102
|
+
├── elements/
|
|
103
|
+
│ ├── wcc-dashboard.ts # Root dashboard component
|
|
104
|
+
│ ├── wcc-sidebar.ts # Navigation sidebar
|
|
105
|
+
│ ├── wcc-frame.ts # Responsive iframe viewport
|
|
106
|
+
│ ├── wcc-properties.ts # Property editing panel
|
|
107
|
+
│ ├── wcc-record-button.ts # Recording button
|
|
108
|
+
│ ├── wcc-recording-panel.ts # Recording options/preview
|
|
109
|
+
│ └── wcctools.helpers.ts # Shared utilities
|
|
110
|
+
├── services/
|
|
111
|
+
│ └── recorder.service.ts # MediaRecorder abstraction
|
|
112
|
+
└── pages/
|
|
113
|
+
└── index.ts # Built-in pages
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Features
|
|
117
|
+
|
|
118
|
+
- 🎨 Interactive component preview
|
|
119
|
+
- 🔧 Real-time property editing with type detection
|
|
120
|
+
- 🌓 Theme switching (light/dark)
|
|
121
|
+
- 📱 Responsive viewport testing
|
|
122
|
+
- 🎬 Screen recording with trimming
|
|
123
|
+
- 🔗 URL-based deep linking
|