feat(recording-panel): Add demo wrapper utilities, improve recording trim behavior, and harden property panel element detection; update documentation
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@design.estate/dees-wcctools',
|
||||
version: '1.2.1',
|
||||
version: '1.3.0',
|
||||
description: 'A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.'
|
||||
}
|
||||
|
||||
@@ -678,16 +678,16 @@ export class WccRecordingPanel extends DeesElement {
|
||||
<div class="trim-track"></div>
|
||||
<div
|
||||
class="trim-selected"
|
||||
style="left: ${this.getHandlePosition(this.trimStart)}px; right: ${this.getHandlePositionFromEnd(this.trimEnd)}px;"
|
||||
style="left: ${this.getHandlePositionStyle(this.trimStart)}; right: ${this.getHandlePositionFromEndStyle(this.trimEnd)};"
|
||||
></div>
|
||||
<div
|
||||
class="trim-handle start-handle"
|
||||
style="left: ${this.getHandlePosition(this.trimStart)}px;"
|
||||
style="left: ${this.getHandlePositionStyle(this.trimStart)};"
|
||||
@mousedown=${(e: MouseEvent) => { e.stopPropagation(); this.isDraggingTrim = 'start'; }}
|
||||
></div>
|
||||
<div
|
||||
class="trim-handle end-handle"
|
||||
style="left: ${this.getHandlePosition(this.trimEnd)}px;"
|
||||
style="left: ${this.getHandlePositionStyle(this.trimEnd)};"
|
||||
@mousedown=${(e: MouseEvent) => { e.stopPropagation(); this.isDraggingTrim = 'end'; }}
|
||||
></div>
|
||||
</div>
|
||||
@@ -850,9 +850,12 @@ export class WccRecordingPanel extends DeesElement {
|
||||
// ==================== Trim Methods ====================
|
||||
|
||||
private handleVideoLoaded(video: HTMLVideoElement): void {
|
||||
this.videoDuration = video.duration;
|
||||
// WebM files from MediaRecorder may have Infinity/NaN duration
|
||||
// Fall back to the tracked recording duration
|
||||
const duration = Number.isFinite(video.duration) ? video.duration : this.recordingDuration;
|
||||
this.videoDuration = duration;
|
||||
this.trimStart = 0;
|
||||
this.trimEnd = video.duration;
|
||||
this.trimEnd = duration;
|
||||
}
|
||||
|
||||
private formatDuration(seconds: number): string {
|
||||
@@ -861,18 +864,23 @@ export class WccRecordingPanel extends DeesElement {
|
||||
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
private getHandlePosition(time: number): number {
|
||||
if (this.videoDuration === 0) return 12;
|
||||
private getHandlePositionStyle(time: number): string {
|
||||
if (this.videoDuration === 0) return '12px';
|
||||
const percentage = time / this.videoDuration;
|
||||
const trackWidth = 336;
|
||||
return 12 + (percentage * trackWidth);
|
||||
// Formula: 12px padding + percentage of remaining width (total - 24px padding)
|
||||
// At 0%: 12px (left edge of track)
|
||||
// At 100%: calc(100% - 12px) (right edge of track)
|
||||
return `calc(12px + ${(percentage * 100).toFixed(2)}% - ${(percentage * 24).toFixed(2)}px)`;
|
||||
}
|
||||
|
||||
private getHandlePositionFromEnd(time: number): number {
|
||||
if (this.videoDuration === 0) return 12;
|
||||
const percentage = (this.videoDuration - time) / this.videoDuration;
|
||||
const trackWidth = 336;
|
||||
return 12 + (percentage * trackWidth);
|
||||
private getHandlePositionFromEndStyle(time: number): string {
|
||||
if (this.videoDuration === 0) return '12px';
|
||||
const percentage = time / this.videoDuration;
|
||||
const remainingPercentage = 1 - percentage;
|
||||
// For CSS 'right' property: distance from right edge
|
||||
// At trimEnd = 100%: right = 12px (at right edge of track)
|
||||
// At trimEnd = 0%: right = calc(100% - 12px) (at left edge of track)
|
||||
return `calc(12px + ${(remainingPercentage * 100).toFixed(2)}% - ${(remainingPercentage * 24).toFixed(2)}px)`;
|
||||
}
|
||||
|
||||
private handleTimelineClick(e: MouseEvent): void {
|
||||
|
||||
123
ts_web/readme.md
Normal file
123
ts_web/readme.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# @design.estate/dees-wcctools
|
||||
|
||||
🛠️ **Web Component Catalogue Tools** — The core dashboard and UI components for building interactive component catalogues
|
||||
|
||||
## Overview
|
||||
|
||||
This is the main module of `@design.estate/dees-wcctools`, providing the complete dashboard experience for developing, testing, and documenting web components.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pnpm add -D @design.estate/dees-wcctools
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { setupWccTools } from '@design.estate/dees-wcctools';
|
||||
import { MyButton } from './components/my-button.js';
|
||||
|
||||
setupWccTools({
|
||||
'my-button': MyButton,
|
||||
});
|
||||
```
|
||||
|
||||
## Exports
|
||||
|
||||
### Main Entry Point
|
||||
|
||||
| Export | Description |
|
||||
|--------|-------------|
|
||||
| `setupWccTools` | Initialize the component catalogue dashboard |
|
||||
|
||||
### Recording Components
|
||||
|
||||
| Export | Description |
|
||||
|--------|-------------|
|
||||
| `RecorderService` | Service class for screen/viewport recording |
|
||||
| `WccRecordButton` | Record button UI component |
|
||||
| `WccRecordingPanel` | Recording options and preview panel |
|
||||
| `IRecorderEvents` | TypeScript interface for recorder callbacks |
|
||||
| `IRecordingOptions` | TypeScript interface for recording options |
|
||||
|
||||
## Internal Components
|
||||
|
||||
The module includes these internal web components:
|
||||
|
||||
| Component | Description |
|
||||
|-----------|-------------|
|
||||
| `wcc-dashboard` | Main dashboard container with routing |
|
||||
| `wcc-sidebar` | Navigation sidebar with element/page listing |
|
||||
| `wcc-frame` | Iframe viewport with responsive sizing |
|
||||
| `wcc-properties` | Property panel with live editing |
|
||||
| `wcc-record-button` | Recording state indicator button |
|
||||
| `wcc-recording-panel` | Recording workflow UI |
|
||||
|
||||
## RecorderService API
|
||||
|
||||
For programmatic recording control:
|
||||
|
||||
```typescript
|
||||
import { RecorderService, type IRecorderEvents } from '@design.estate/dees-wcctools';
|
||||
|
||||
const events: IRecorderEvents = {
|
||||
onDurationUpdate: (duration) => console.log(`Recording: ${duration}s`),
|
||||
onRecordingComplete: (blob) => saveBlob(blob),
|
||||
onAudioLevelUpdate: (level) => updateMeter(level),
|
||||
onError: (error) => console.error(error),
|
||||
onStreamEnded: () => console.log('User stopped sharing'),
|
||||
};
|
||||
|
||||
const recorder = new RecorderService(events);
|
||||
|
||||
// Load available microphones
|
||||
const mics = await recorder.loadMicrophones(true); // true = request permission
|
||||
|
||||
// Start audio level monitoring
|
||||
await recorder.startAudioMonitoring(mics[0].deviceId);
|
||||
|
||||
// Start recording
|
||||
await recorder.startRecording({
|
||||
mode: 'viewport', // or 'screen'
|
||||
audioDeviceId: mics[0].deviceId,
|
||||
viewportElement: document.querySelector('.viewport'),
|
||||
});
|
||||
|
||||
// Stop recording
|
||||
recorder.stopRecording();
|
||||
|
||||
// Export trimmed video
|
||||
const trimmedBlob = await recorder.exportTrimmedVideo(videoElement, startTime, endTime);
|
||||
|
||||
// Cleanup
|
||||
recorder.dispose();
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
ts_web/
|
||||
├── index.ts # Main exports
|
||||
├── elements/
|
||||
│ ├── wcc-dashboard.ts # Root dashboard component
|
||||
│ ├── wcc-sidebar.ts # Navigation sidebar
|
||||
│ ├── wcc-frame.ts # Responsive iframe viewport
|
||||
│ ├── wcc-properties.ts # Property editing panel
|
||||
│ ├── wcc-record-button.ts # Recording button
|
||||
│ ├── wcc-recording-panel.ts # Recording options/preview
|
||||
│ └── wcctools.helpers.ts # Shared utilities
|
||||
├── services/
|
||||
│ └── recorder.service.ts # MediaRecorder abstraction
|
||||
└── pages/
|
||||
└── index.ts # Built-in pages
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- 🎨 Interactive component preview
|
||||
- 🔧 Real-time property editing with type detection
|
||||
- 🌓 Theme switching (light/dark)
|
||||
- 📱 Responsive viewport testing
|
||||
- 🎬 Screen recording with trimming
|
||||
- 🔗 URL-based deep linking
|
||||
Reference in New Issue
Block a user