@design.estate/dees-wcctools 1.2.0 → 1.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.
Files changed (35) hide show
  1. package/dist_bundle/bundle.js +1700 -264
  2. package/dist_bundle/bundle.js.map +4 -4
  3. package/dist_ts_demotools/demotools.d.ts +1 -1
  4. package/dist_ts_demotools/demotools.js +86 -38
  5. package/dist_ts_web/00_commitinfo_data.js +1 -1
  6. package/dist_ts_web/elements/wcc-dashboard.d.ts +10 -10
  7. package/dist_ts_web/elements/wcc-dashboard.js +317 -245
  8. package/dist_ts_web/elements/wcc-frame.d.ts +3 -3
  9. package/dist_ts_web/elements/wcc-frame.js +108 -57
  10. package/dist_ts_web/elements/wcc-properties.d.ts +14 -8
  11. package/dist_ts_web/elements/wcc-properties.js +442 -323
  12. package/dist_ts_web/elements/wcc-record-button.d.ts +12 -0
  13. package/dist_ts_web/elements/wcc-record-button.js +165 -0
  14. package/dist_ts_web/elements/wcc-recording-panel.d.ts +42 -0
  15. package/dist_ts_web/elements/wcc-recording-panel.js +1063 -0
  16. package/dist_ts_web/elements/wcc-sidebar.d.ts +4 -4
  17. package/dist_ts_web/elements/wcc-sidebar.js +125 -71
  18. package/dist_ts_web/index.d.ts +3 -0
  19. package/dist_ts_web/index.js +5 -1
  20. package/dist_ts_web/services/recorder.service.d.ts +44 -0
  21. package/dist_ts_web/services/recorder.service.js +306 -0
  22. package/dist_watch/bundle.js +1939 -521
  23. package/dist_watch/bundle.js.map +4 -4
  24. package/package.json +10 -10
  25. package/readme.md +133 -141
  26. package/ts_web/00_commitinfo_data.ts +1 -1
  27. package/ts_web/elements/wcc-dashboard.ts +10 -10
  28. package/ts_web/elements/wcc-frame.ts +3 -3
  29. package/ts_web/elements/wcc-properties.ts +53 -9
  30. package/ts_web/elements/wcc-record-button.ts +108 -0
  31. package/ts_web/elements/wcc-recording-panel.ts +974 -0
  32. package/ts_web/elements/wcc-sidebar.ts +4 -4
  33. package/ts_web/index.ts +5 -0
  34. package/ts_web/readme.md +123 -0
  35. package/ts_web/services/recorder.service.ts +391 -0
@@ -0,0 +1,1063 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { DeesElement, customElement, html, css, property, state } from '@design.estate/dees-element';
36
+ import { RecorderService } from '../services/recorder.service.js';
37
+ let WccRecordingPanel = (() => {
38
+ let _classDecorators = [customElement('wcc-recording-panel')];
39
+ let _classDescriptor;
40
+ let _classExtraInitializers = [];
41
+ let _classThis;
42
+ let _classSuper = DeesElement;
43
+ let _dashboardRef_decorators;
44
+ let _dashboardRef_initializers = [];
45
+ let _dashboardRef_extraInitializers = [];
46
+ let _panelState_decorators;
47
+ let _panelState_initializers = [];
48
+ let _panelState_extraInitializers = [];
49
+ let _recordingMode_decorators;
50
+ let _recordingMode_initializers = [];
51
+ let _recordingMode_extraInitializers = [];
52
+ let _audioEnabled_decorators;
53
+ let _audioEnabled_initializers = [];
54
+ let _audioEnabled_extraInitializers = [];
55
+ let _selectedMicrophoneId_decorators;
56
+ let _selectedMicrophoneId_initializers = [];
57
+ let _selectedMicrophoneId_extraInitializers = [];
58
+ let _availableMicrophones_decorators;
59
+ let _availableMicrophones_initializers = [];
60
+ let _availableMicrophones_extraInitializers = [];
61
+ let _audioLevel_decorators;
62
+ let _audioLevel_initializers = [];
63
+ let _audioLevel_extraInitializers = [];
64
+ let _recordingDuration_decorators;
65
+ let _recordingDuration_initializers = [];
66
+ let _recordingDuration_extraInitializers = [];
67
+ let _previewVideoUrl_decorators;
68
+ let _previewVideoUrl_initializers = [];
69
+ let _previewVideoUrl_extraInitializers = [];
70
+ let _trimStart_decorators;
71
+ let _trimStart_initializers = [];
72
+ let _trimStart_extraInitializers = [];
73
+ let _trimEnd_decorators;
74
+ let _trimEnd_initializers = [];
75
+ let _trimEnd_extraInitializers = [];
76
+ let _videoDuration_decorators;
77
+ let _videoDuration_initializers = [];
78
+ let _videoDuration_extraInitializers = [];
79
+ let _isDraggingTrim_decorators;
80
+ let _isDraggingTrim_initializers = [];
81
+ let _isDraggingTrim_extraInitializers = [];
82
+ let _isExporting_decorators;
83
+ let _isExporting_initializers = [];
84
+ let _isExporting_extraInitializers = [];
85
+ var WccRecordingPanel = class extends _classSuper {
86
+ static { _classThis = this; }
87
+ static {
88
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
89
+ _dashboardRef_decorators = [property({ attribute: false })];
90
+ _panelState_decorators = [state()];
91
+ _recordingMode_decorators = [state()];
92
+ _audioEnabled_decorators = [state()];
93
+ _selectedMicrophoneId_decorators = [state()];
94
+ _availableMicrophones_decorators = [state()];
95
+ _audioLevel_decorators = [state()];
96
+ _recordingDuration_decorators = [state()];
97
+ _previewVideoUrl_decorators = [state()];
98
+ _trimStart_decorators = [state()];
99
+ _trimEnd_decorators = [state()];
100
+ _videoDuration_decorators = [state()];
101
+ _isDraggingTrim_decorators = [state()];
102
+ _isExporting_decorators = [state()];
103
+ __esDecorate(this, null, _dashboardRef_decorators, { kind: "accessor", name: "dashboardRef", static: false, private: false, access: { has: obj => "dashboardRef" in obj, get: obj => obj.dashboardRef, set: (obj, value) => { obj.dashboardRef = value; } }, metadata: _metadata }, _dashboardRef_initializers, _dashboardRef_extraInitializers);
104
+ __esDecorate(this, null, _panelState_decorators, { kind: "accessor", name: "panelState", static: false, private: false, access: { has: obj => "panelState" in obj, get: obj => obj.panelState, set: (obj, value) => { obj.panelState = value; } }, metadata: _metadata }, _panelState_initializers, _panelState_extraInitializers);
105
+ __esDecorate(this, null, _recordingMode_decorators, { kind: "accessor", name: "recordingMode", static: false, private: false, access: { has: obj => "recordingMode" in obj, get: obj => obj.recordingMode, set: (obj, value) => { obj.recordingMode = value; } }, metadata: _metadata }, _recordingMode_initializers, _recordingMode_extraInitializers);
106
+ __esDecorate(this, null, _audioEnabled_decorators, { kind: "accessor", name: "audioEnabled", static: false, private: false, access: { has: obj => "audioEnabled" in obj, get: obj => obj.audioEnabled, set: (obj, value) => { obj.audioEnabled = value; } }, metadata: _metadata }, _audioEnabled_initializers, _audioEnabled_extraInitializers);
107
+ __esDecorate(this, null, _selectedMicrophoneId_decorators, { kind: "accessor", name: "selectedMicrophoneId", static: false, private: false, access: { has: obj => "selectedMicrophoneId" in obj, get: obj => obj.selectedMicrophoneId, set: (obj, value) => { obj.selectedMicrophoneId = value; } }, metadata: _metadata }, _selectedMicrophoneId_initializers, _selectedMicrophoneId_extraInitializers);
108
+ __esDecorate(this, null, _availableMicrophones_decorators, { kind: "accessor", name: "availableMicrophones", static: false, private: false, access: { has: obj => "availableMicrophones" in obj, get: obj => obj.availableMicrophones, set: (obj, value) => { obj.availableMicrophones = value; } }, metadata: _metadata }, _availableMicrophones_initializers, _availableMicrophones_extraInitializers);
109
+ __esDecorate(this, null, _audioLevel_decorators, { kind: "accessor", name: "audioLevel", static: false, private: false, access: { has: obj => "audioLevel" in obj, get: obj => obj.audioLevel, set: (obj, value) => { obj.audioLevel = value; } }, metadata: _metadata }, _audioLevel_initializers, _audioLevel_extraInitializers);
110
+ __esDecorate(this, null, _recordingDuration_decorators, { kind: "accessor", name: "recordingDuration", static: false, private: false, access: { has: obj => "recordingDuration" in obj, get: obj => obj.recordingDuration, set: (obj, value) => { obj.recordingDuration = value; } }, metadata: _metadata }, _recordingDuration_initializers, _recordingDuration_extraInitializers);
111
+ __esDecorate(this, null, _previewVideoUrl_decorators, { kind: "accessor", name: "previewVideoUrl", static: false, private: false, access: { has: obj => "previewVideoUrl" in obj, get: obj => obj.previewVideoUrl, set: (obj, value) => { obj.previewVideoUrl = value; } }, metadata: _metadata }, _previewVideoUrl_initializers, _previewVideoUrl_extraInitializers);
112
+ __esDecorate(this, null, _trimStart_decorators, { kind: "accessor", name: "trimStart", static: false, private: false, access: { has: obj => "trimStart" in obj, get: obj => obj.trimStart, set: (obj, value) => { obj.trimStart = value; } }, metadata: _metadata }, _trimStart_initializers, _trimStart_extraInitializers);
113
+ __esDecorate(this, null, _trimEnd_decorators, { kind: "accessor", name: "trimEnd", static: false, private: false, access: { has: obj => "trimEnd" in obj, get: obj => obj.trimEnd, set: (obj, value) => { obj.trimEnd = value; } }, metadata: _metadata }, _trimEnd_initializers, _trimEnd_extraInitializers);
114
+ __esDecorate(this, null, _videoDuration_decorators, { kind: "accessor", name: "videoDuration", static: false, private: false, access: { has: obj => "videoDuration" in obj, get: obj => obj.videoDuration, set: (obj, value) => { obj.videoDuration = value; } }, metadata: _metadata }, _videoDuration_initializers, _videoDuration_extraInitializers);
115
+ __esDecorate(this, null, _isDraggingTrim_decorators, { kind: "accessor", name: "isDraggingTrim", static: false, private: false, access: { has: obj => "isDraggingTrim" in obj, get: obj => obj.isDraggingTrim, set: (obj, value) => { obj.isDraggingTrim = value; } }, metadata: _metadata }, _isDraggingTrim_initializers, _isDraggingTrim_extraInitializers);
116
+ __esDecorate(this, null, _isExporting_decorators, { kind: "accessor", name: "isExporting", static: false, private: false, access: { has: obj => "isExporting" in obj, get: obj => obj.isExporting, set: (obj, value) => { obj.isExporting = value; } }, metadata: _metadata }, _isExporting_initializers, _isExporting_extraInitializers);
117
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
118
+ WccRecordingPanel = _classThis = _classDescriptor.value;
119
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
120
+ }
121
+ #dashboardRef_accessor_storage = __runInitializers(this, _dashboardRef_initializers, void 0);
122
+ // External configuration
123
+ get dashboardRef() { return this.#dashboardRef_accessor_storage; }
124
+ set dashboardRef(value) { this.#dashboardRef_accessor_storage = value; }
125
+ #panelState_accessor_storage = (__runInitializers(this, _dashboardRef_extraInitializers), __runInitializers(this, _panelState_initializers, 'options'));
126
+ // Panel state
127
+ get panelState() { return this.#panelState_accessor_storage; }
128
+ set panelState(value) { this.#panelState_accessor_storage = value; }
129
+ #recordingMode_accessor_storage = (__runInitializers(this, _panelState_extraInitializers), __runInitializers(this, _recordingMode_initializers, 'viewport'));
130
+ // Recording options
131
+ get recordingMode() { return this.#recordingMode_accessor_storage; }
132
+ set recordingMode(value) { this.#recordingMode_accessor_storage = value; }
133
+ #audioEnabled_accessor_storage = (__runInitializers(this, _recordingMode_extraInitializers), __runInitializers(this, _audioEnabled_initializers, false));
134
+ get audioEnabled() { return this.#audioEnabled_accessor_storage; }
135
+ set audioEnabled(value) { this.#audioEnabled_accessor_storage = value; }
136
+ #selectedMicrophoneId_accessor_storage = (__runInitializers(this, _audioEnabled_extraInitializers), __runInitializers(this, _selectedMicrophoneId_initializers, ''));
137
+ get selectedMicrophoneId() { return this.#selectedMicrophoneId_accessor_storage; }
138
+ set selectedMicrophoneId(value) { this.#selectedMicrophoneId_accessor_storage = value; }
139
+ #availableMicrophones_accessor_storage = (__runInitializers(this, _selectedMicrophoneId_extraInitializers), __runInitializers(this, _availableMicrophones_initializers, []));
140
+ get availableMicrophones() { return this.#availableMicrophones_accessor_storage; }
141
+ set availableMicrophones(value) { this.#availableMicrophones_accessor_storage = value; }
142
+ #audioLevel_accessor_storage = (__runInitializers(this, _availableMicrophones_extraInitializers), __runInitializers(this, _audioLevel_initializers, 0));
143
+ get audioLevel() { return this.#audioLevel_accessor_storage; }
144
+ set audioLevel(value) { this.#audioLevel_accessor_storage = value; }
145
+ #recordingDuration_accessor_storage = (__runInitializers(this, _audioLevel_extraInitializers), __runInitializers(this, _recordingDuration_initializers, 0));
146
+ // Recording state
147
+ get recordingDuration() { return this.#recordingDuration_accessor_storage; }
148
+ set recordingDuration(value) { this.#recordingDuration_accessor_storage = value; }
149
+ #previewVideoUrl_accessor_storage = (__runInitializers(this, _recordingDuration_extraInitializers), __runInitializers(this, _previewVideoUrl_initializers, ''));
150
+ // Preview/trim state
151
+ get previewVideoUrl() { return this.#previewVideoUrl_accessor_storage; }
152
+ set previewVideoUrl(value) { this.#previewVideoUrl_accessor_storage = value; }
153
+ #trimStart_accessor_storage = (__runInitializers(this, _previewVideoUrl_extraInitializers), __runInitializers(this, _trimStart_initializers, 0));
154
+ get trimStart() { return this.#trimStart_accessor_storage; }
155
+ set trimStart(value) { this.#trimStart_accessor_storage = value; }
156
+ #trimEnd_accessor_storage = (__runInitializers(this, _trimStart_extraInitializers), __runInitializers(this, _trimEnd_initializers, 0));
157
+ get trimEnd() { return this.#trimEnd_accessor_storage; }
158
+ set trimEnd(value) { this.#trimEnd_accessor_storage = value; }
159
+ #videoDuration_accessor_storage = (__runInitializers(this, _trimEnd_extraInitializers), __runInitializers(this, _videoDuration_initializers, 0));
160
+ get videoDuration() { return this.#videoDuration_accessor_storage; }
161
+ set videoDuration(value) { this.#videoDuration_accessor_storage = value; }
162
+ #isDraggingTrim_accessor_storage = (__runInitializers(this, _videoDuration_extraInitializers), __runInitializers(this, _isDraggingTrim_initializers, null));
163
+ get isDraggingTrim() { return this.#isDraggingTrim_accessor_storage; }
164
+ set isDraggingTrim(value) { this.#isDraggingTrim_accessor_storage = value; }
165
+ #isExporting_accessor_storage = (__runInitializers(this, _isDraggingTrim_extraInitializers), __runInitializers(this, _isExporting_initializers, false));
166
+ get isExporting() { return this.#isExporting_accessor_storage; }
167
+ set isExporting(value) { this.#isExporting_accessor_storage = value; }
168
+ // Service instance
169
+ recorderService = __runInitializers(this, _isExporting_extraInitializers);
170
+ constructor() {
171
+ super();
172
+ this.recorderService = new RecorderService({
173
+ onDurationUpdate: (duration) => {
174
+ this.recordingDuration = duration;
175
+ this.dispatchEvent(new CustomEvent('duration-update', {
176
+ detail: { duration },
177
+ bubbles: true,
178
+ composed: true
179
+ }));
180
+ },
181
+ onRecordingComplete: (blob) => {
182
+ this.handleRecordingComplete(blob);
183
+ },
184
+ onAudioLevelUpdate: (level) => {
185
+ this.audioLevel = level;
186
+ },
187
+ onStreamEnded: () => {
188
+ this.stopRecording();
189
+ }
190
+ });
191
+ }
192
+ static styles = [
193
+ css `
194
+ :host {
195
+ /* CSS Variables */
196
+ --background: #0a0a0a;
197
+ --foreground: #e5e5e5;
198
+ --input: #141414;
199
+ --primary: #3b82f6;
200
+ --border: rgba(255, 255, 255, 0.06);
201
+ --radius-sm: 2px;
202
+ --radius-md: 4px;
203
+ --radius-lg: 6px;
204
+ }
205
+
206
+ /* Recording Options Panel */
207
+ .recording-options-panel {
208
+ position: fixed;
209
+ right: 16px;
210
+ bottom: 116px;
211
+ width: 360px;
212
+ background: #0c0c0c;
213
+ border: 1px solid rgba(255, 255, 255, 0.1);
214
+ border-radius: var(--radius-md);
215
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
216
+ z-index: 1000;
217
+ overflow: hidden;
218
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
219
+ }
220
+
221
+ .recording-options-header {
222
+ padding: 0.75rem 1rem;
223
+ background: rgba(255, 255, 255, 0.02);
224
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
225
+ display: flex;
226
+ justify-content: space-between;
227
+ align-items: center;
228
+ }
229
+
230
+ .recording-options-title {
231
+ font-size: 0.8rem;
232
+ font-weight: 500;
233
+ color: #ccc;
234
+ }
235
+
236
+ .recording-options-close {
237
+ width: 24px;
238
+ height: 24px;
239
+ background: transparent;
240
+ border: none;
241
+ color: #666;
242
+ cursor: pointer;
243
+ display: flex;
244
+ align-items: center;
245
+ justify-content: center;
246
+ border-radius: var(--radius-sm);
247
+ transition: all 0.15s ease;
248
+ }
249
+
250
+ .recording-options-close:hover {
251
+ background: rgba(255, 255, 255, 0.05);
252
+ color: #999;
253
+ }
254
+
255
+ .recording-options-content {
256
+ padding: 1rem;
257
+ }
258
+
259
+ .recording-option-group {
260
+ margin-bottom: 1rem;
261
+ }
262
+
263
+ .recording-option-group:last-child {
264
+ margin-bottom: 0;
265
+ }
266
+
267
+ .recording-option-label {
268
+ font-size: 0.7rem;
269
+ font-weight: 500;
270
+ color: #888;
271
+ text-transform: uppercase;
272
+ letter-spacing: 0.05em;
273
+ margin-bottom: 0.5rem;
274
+ }
275
+
276
+ .recording-mode-buttons {
277
+ display: flex;
278
+ gap: 0.5rem;
279
+ }
280
+
281
+ .recording-mode-btn {
282
+ flex: 1;
283
+ padding: 0.6rem 0.75rem;
284
+ background: var(--input);
285
+ border: 1px solid transparent;
286
+ border-radius: var(--radius-sm);
287
+ color: #999;
288
+ font-size: 0.75rem;
289
+ cursor: pointer;
290
+ transition: all 0.15s ease;
291
+ text-align: center;
292
+ }
293
+
294
+ .recording-mode-btn:hover {
295
+ border-color: var(--primary);
296
+ color: #ccc;
297
+ }
298
+
299
+ .recording-mode-btn.selected {
300
+ background: rgba(59, 130, 246, 0.15);
301
+ border-color: var(--primary);
302
+ color: var(--primary);
303
+ }
304
+
305
+ .audio-toggle {
306
+ display: flex;
307
+ align-items: center;
308
+ gap: 0.5rem;
309
+ margin-bottom: 0.75rem;
310
+ }
311
+
312
+ .audio-toggle input[type="checkbox"] {
313
+ width: 1rem;
314
+ height: 1rem;
315
+ accent-color: var(--primary);
316
+ }
317
+
318
+ .audio-toggle label {
319
+ font-size: 0.75rem;
320
+ color: #999;
321
+ cursor: pointer;
322
+ }
323
+
324
+ .microphone-select {
325
+ width: 100%;
326
+ padding: 0.5rem 0.75rem;
327
+ background: var(--input);
328
+ border: 1px solid transparent;
329
+ border-radius: var(--radius-sm);
330
+ color: var(--foreground);
331
+ font-size: 0.75rem;
332
+ outline: none;
333
+ cursor: pointer;
334
+ transition: all 0.15s ease;
335
+ }
336
+
337
+ .microphone-select:focus {
338
+ border-color: var(--primary);
339
+ }
340
+
341
+ .microphone-select:disabled {
342
+ opacity: 0.5;
343
+ cursor: not-allowed;
344
+ }
345
+
346
+ .audio-level-container {
347
+ margin-top: 0.75rem;
348
+ padding: 0.5rem;
349
+ background: rgba(255, 255, 255, 0.02);
350
+ border-radius: var(--radius-sm);
351
+ }
352
+
353
+ .audio-level-label {
354
+ font-size: 0.65rem;
355
+ color: #666;
356
+ margin-bottom: 0.25rem;
357
+ }
358
+
359
+ .audio-level-bar {
360
+ height: 8px;
361
+ background: var(--input);
362
+ border-radius: 4px;
363
+ overflow: hidden;
364
+ }
365
+
366
+ .audio-level-fill {
367
+ height: 100%;
368
+ background: linear-gradient(90deg, #22c55e, #84cc16, #eab308);
369
+ border-radius: 4px;
370
+ transition: width 0.1s ease;
371
+ }
372
+
373
+ .start-recording-btn {
374
+ width: 100%;
375
+ padding: 0.75rem;
376
+ background: #dc2626;
377
+ border: none;
378
+ border-radius: var(--radius-sm);
379
+ color: white;
380
+ font-size: 0.8rem;
381
+ font-weight: 500;
382
+ cursor: pointer;
383
+ transition: all 0.15s ease;
384
+ margin-top: 1rem;
385
+ display: flex;
386
+ align-items: center;
387
+ justify-content: center;
388
+ gap: 0.5rem;
389
+ }
390
+
391
+ .start-recording-btn:hover {
392
+ background: #b91c1c;
393
+ }
394
+
395
+ .start-recording-btn .rec-dot {
396
+ width: 10px;
397
+ height: 10px;
398
+ background: white;
399
+ border-radius: 50%;
400
+ }
401
+
402
+ /* Preview Modal */
403
+ .preview-modal-overlay {
404
+ position: fixed;
405
+ top: 0;
406
+ left: 0;
407
+ right: 0;
408
+ bottom: 0;
409
+ background: rgba(0, 0, 0, 0.8);
410
+ display: flex;
411
+ align-items: center;
412
+ justify-content: center;
413
+ z-index: 1000;
414
+ backdrop-filter: blur(4px);
415
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
416
+ }
417
+
418
+ .preview-modal {
419
+ width: 90%;
420
+ max-width: 800px;
421
+ background: #0c0c0c;
422
+ border: 1px solid rgba(255, 255, 255, 0.1);
423
+ border-radius: var(--radius-lg);
424
+ overflow: hidden;
425
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
426
+ }
427
+
428
+ .preview-modal-header {
429
+ padding: 1rem 1.25rem;
430
+ background: rgba(255, 255, 255, 0.02);
431
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
432
+ display: flex;
433
+ justify-content: space-between;
434
+ align-items: center;
435
+ }
436
+
437
+ .preview-modal-title {
438
+ font-size: 0.9rem;
439
+ font-weight: 500;
440
+ color: #ccc;
441
+ }
442
+
443
+ .preview-modal-close {
444
+ width: 28px;
445
+ height: 28px;
446
+ background: transparent;
447
+ border: none;
448
+ color: #666;
449
+ cursor: pointer;
450
+ display: flex;
451
+ align-items: center;
452
+ justify-content: center;
453
+ border-radius: var(--radius-sm);
454
+ font-size: 1.2rem;
455
+ transition: all 0.15s ease;
456
+ }
457
+
458
+ .preview-modal-close:hover {
459
+ background: rgba(255, 255, 255, 0.05);
460
+ color: #999;
461
+ }
462
+
463
+ .preview-modal-content {
464
+ padding: 1.25rem;
465
+ }
466
+
467
+ .preview-video-container {
468
+ background: #000;
469
+ border-radius: var(--radius-sm);
470
+ overflow: hidden;
471
+ aspect-ratio: 16 / 9;
472
+ }
473
+
474
+ .preview-video {
475
+ width: 100%;
476
+ height: 100%;
477
+ object-fit: contain;
478
+ }
479
+
480
+ .preview-modal-actions {
481
+ padding: 1rem 1.25rem;
482
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
483
+ display: flex;
484
+ justify-content: flex-end;
485
+ gap: 0.75rem;
486
+ }
487
+
488
+ .preview-btn {
489
+ padding: 0.6rem 1.25rem;
490
+ border-radius: var(--radius-sm);
491
+ font-size: 0.8rem;
492
+ font-weight: 500;
493
+ cursor: pointer;
494
+ transition: all 0.15s ease;
495
+ }
496
+
497
+ .preview-btn.secondary {
498
+ background: transparent;
499
+ border: 1px solid rgba(255, 255, 255, 0.1);
500
+ color: #999;
501
+ }
502
+
503
+ .preview-btn.secondary:hover {
504
+ border-color: rgba(255, 255, 255, 0.2);
505
+ color: #ccc;
506
+ }
507
+
508
+ .preview-btn.primary {
509
+ background: var(--primary);
510
+ border: none;
511
+ color: white;
512
+ }
513
+
514
+ .preview-btn.primary:hover {
515
+ background: #2563eb;
516
+ }
517
+
518
+ .preview-btn.primary:disabled {
519
+ background: #1e3a5f;
520
+ cursor: not-allowed;
521
+ opacity: 0.7;
522
+ }
523
+
524
+ /* Trim Timeline Styles */
525
+ .trim-section {
526
+ margin-top: 1.25rem;
527
+ padding-top: 1.25rem;
528
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
529
+ }
530
+
531
+ .trim-section-header {
532
+ display: flex;
533
+ justify-content: space-between;
534
+ align-items: center;
535
+ margin-bottom: 0.75rem;
536
+ }
537
+
538
+ .trim-section-title {
539
+ font-size: 0.75rem;
540
+ font-weight: 500;
541
+ color: #888;
542
+ text-transform: uppercase;
543
+ letter-spacing: 0.05em;
544
+ }
545
+
546
+ .trim-duration-info {
547
+ font-size: 0.7rem;
548
+ color: #666;
549
+ font-family: 'Consolas', 'Monaco', monospace;
550
+ }
551
+
552
+ .trim-timeline {
553
+ position: relative;
554
+ height: 48px;
555
+ background: var(--input);
556
+ border-radius: var(--radius-sm);
557
+ margin-bottom: 0.75rem;
558
+ user-select: none;
559
+ }
560
+
561
+ .trim-track {
562
+ position: absolute;
563
+ top: 50%;
564
+ left: 12px;
565
+ right: 12px;
566
+ height: 6px;
567
+ background: #333;
568
+ transform: translateY(-50%);
569
+ border-radius: 3px;
570
+ }
571
+
572
+ .trim-selected {
573
+ position: absolute;
574
+ top: 50%;
575
+ height: 6px;
576
+ background: var(--primary);
577
+ transform: translateY(-50%);
578
+ border-radius: 3px;
579
+ pointer-events: none;
580
+ }
581
+
582
+ .trim-handle {
583
+ position: absolute;
584
+ top: 50%;
585
+ width: 16px;
586
+ height: 36px;
587
+ background: white;
588
+ border: 2px solid var(--primary);
589
+ border-radius: 4px;
590
+ transform: translate(-50%, -50%);
591
+ cursor: ew-resize;
592
+ z-index: 2;
593
+ display: flex;
594
+ align-items: center;
595
+ justify-content: center;
596
+ transition: background 0.15s ease, transform 0.1s ease;
597
+ }
598
+
599
+ .trim-handle:hover {
600
+ background: #e0e0e0;
601
+ }
602
+
603
+ .trim-handle:active {
604
+ background: var(--primary);
605
+ transform: translate(-50%, -50%) scale(1.05);
606
+ }
607
+
608
+ .trim-handle::before {
609
+ content: '';
610
+ width: 2px;
611
+ height: 16px;
612
+ background: #666;
613
+ border-radius: 1px;
614
+ }
615
+
616
+ .trim-handle:active::before {
617
+ background: white;
618
+ }
619
+
620
+ .trim-time-labels {
621
+ display: flex;
622
+ justify-content: space-between;
623
+ font-size: 0.65rem;
624
+ color: #666;
625
+ font-family: 'Consolas', 'Monaco', monospace;
626
+ padding: 0 12px;
627
+ }
628
+
629
+ .trim-actions {
630
+ display: flex;
631
+ gap: 0.5rem;
632
+ margin-top: 0.75rem;
633
+ }
634
+
635
+ .trim-action-btn {
636
+ flex: 1;
637
+ padding: 0.5rem 0.75rem;
638
+ background: var(--input);
639
+ border: 1px solid transparent;
640
+ border-radius: var(--radius-sm);
641
+ color: #999;
642
+ font-size: 0.75rem;
643
+ cursor: pointer;
644
+ transition: all 0.15s ease;
645
+ text-align: center;
646
+ }
647
+
648
+ .trim-action-btn:hover {
649
+ border-color: var(--primary);
650
+ color: #ccc;
651
+ }
652
+
653
+ .export-spinner {
654
+ display: inline-block;
655
+ width: 14px;
656
+ height: 14px;
657
+ border: 2px solid rgba(255, 255, 255, 0.3);
658
+ border-radius: 50%;
659
+ border-top-color: white;
660
+ animation: spin 0.8s linear infinite;
661
+ margin-right: 0.5rem;
662
+ }
663
+
664
+ @keyframes spin {
665
+ to { transform: rotate(360deg); }
666
+ }
667
+ `
668
+ ];
669
+ render() {
670
+ if (this.panelState === 'options') {
671
+ return this.renderOptionsPanel();
672
+ }
673
+ else if (this.panelState === 'preview') {
674
+ return this.renderPreviewModal();
675
+ }
676
+ return html ``;
677
+ }
678
+ renderOptionsPanel() {
679
+ return html `
680
+ <div class="recording-options-panel">
681
+ <div class="recording-options-header">
682
+ <span class="recording-options-title">Recording Settings</span>
683
+ <button class="recording-options-close" @click=${() => this.close()}>✕</button>
684
+ </div>
685
+ <div class="recording-options-content">
686
+ <div class="recording-option-group">
687
+ <div class="recording-option-label">Record Area</div>
688
+ <div class="recording-mode-buttons">
689
+ <button
690
+ class="recording-mode-btn ${this.recordingMode === 'viewport' ? 'selected' : ''}"
691
+ @click=${() => this.recordingMode = 'viewport'}
692
+ >
693
+ Viewport Only
694
+ </button>
695
+ <button
696
+ class="recording-mode-btn ${this.recordingMode === 'screen' ? 'selected' : ''}"
697
+ @click=${() => this.recordingMode = 'screen'}
698
+ >
699
+ Entire Screen
700
+ </button>
701
+ </div>
702
+ </div>
703
+
704
+ <div class="recording-option-group">
705
+ <div class="recording-option-label">Audio</div>
706
+ <div class="audio-toggle">
707
+ <input
708
+ type="checkbox"
709
+ id="audioToggle"
710
+ ?checked=${this.audioEnabled}
711
+ @change=${(e) => this.handleAudioToggle(e.target.checked)}
712
+ />
713
+ <label for="audioToggle">Enable Microphone</label>
714
+ </div>
715
+
716
+ ${this.audioEnabled ? html `
717
+ <select
718
+ class="microphone-select"
719
+ .value=${this.selectedMicrophoneId}
720
+ @change=${(e) => this.handleMicrophoneChange(e.target.value)}
721
+ >
722
+ <option value="">Select Microphone...</option>
723
+ ${this.availableMicrophones.map(mic => html `
724
+ <option value=${mic.deviceId}>${mic.label || `Microphone ${mic.deviceId.slice(0, 8)}`}</option>
725
+ `)}
726
+ </select>
727
+
728
+ ${this.selectedMicrophoneId ? html `
729
+ <div class="audio-level-container">
730
+ <div class="audio-level-label">Input Level</div>
731
+ <div class="audio-level-bar">
732
+ <div class="audio-level-fill" style="width: ${this.audioLevel}%"></div>
733
+ </div>
734
+ </div>
735
+ ` : null}
736
+ ` : null}
737
+ </div>
738
+
739
+ <button class="start-recording-btn" @click=${() => this.startRecording()}>
740
+ <div class="rec-dot"></div>
741
+ Start Recording
742
+ </button>
743
+ </div>
744
+ </div>
745
+ `;
746
+ }
747
+ renderPreviewModal() {
748
+ return html `
749
+ <div class="preview-modal-overlay" @click=${(e) => {
750
+ if (e.target.classList.contains('preview-modal-overlay')) {
751
+ this.discardRecording();
752
+ }
753
+ }}>
754
+ <div class="preview-modal">
755
+ <div class="preview-modal-header">
756
+ <span class="preview-modal-title">Recording Preview</span>
757
+ <button class="preview-modal-close" @click=${() => this.discardRecording()}>✕</button>
758
+ </div>
759
+ <div class="preview-modal-content">
760
+ <div class="preview-video-container">
761
+ <video
762
+ class="preview-video"
763
+ src=${this.previewVideoUrl}
764
+ controls
765
+ @loadedmetadata=${(e) => this.handleVideoLoaded(e.target)}
766
+ ></video>
767
+ </div>
768
+
769
+ <!-- Trim Section -->
770
+ <div class="trim-section">
771
+ <div class="trim-section-header">
772
+ <span class="trim-section-title">Trim Video</span>
773
+ <span class="trim-duration-info">
774
+ ${this.formatDuration(Math.floor(this.trimEnd - this.trimStart))}
775
+ ${this.trimStart > 0 || this.trimEnd < this.videoDuration
776
+ ? `(trimmed from ${this.formatDuration(Math.floor(this.videoDuration))})`
777
+ : ''}
778
+ </span>
779
+ </div>
780
+
781
+ <div
782
+ class="trim-timeline"
783
+ @mousedown=${(e) => this.handleTimelineClick(e)}
784
+ @mousemove=${(e) => this.handleTimelineDrag(e)}
785
+ @mouseup=${() => this.handleTimelineDragEnd()}
786
+ @mouseleave=${() => this.handleTimelineDragEnd()}
787
+ >
788
+ <div class="trim-track"></div>
789
+ <div
790
+ class="trim-selected"
791
+ style="left: ${this.getHandlePositionStyle(this.trimStart)}; right: ${this.getHandlePositionFromEndStyle(this.trimEnd)};"
792
+ ></div>
793
+ <div
794
+ class="trim-handle start-handle"
795
+ style="left: ${this.getHandlePositionStyle(this.trimStart)};"
796
+ @mousedown=${(e) => { e.stopPropagation(); this.isDraggingTrim = 'start'; }}
797
+ ></div>
798
+ <div
799
+ class="trim-handle end-handle"
800
+ style="left: ${this.getHandlePositionStyle(this.trimEnd)};"
801
+ @mousedown=${(e) => { e.stopPropagation(); this.isDraggingTrim = 'end'; }}
802
+ ></div>
803
+ </div>
804
+
805
+ <div class="trim-time-labels">
806
+ <span>${this.formatDuration(Math.floor(this.trimStart))}</span>
807
+ <span>${this.formatDuration(Math.floor(this.trimEnd))}</span>
808
+ </div>
809
+
810
+ <div class="trim-actions">
811
+ <button class="trim-action-btn" @click=${() => this.resetTrim()}>
812
+ Reset Trim
813
+ </button>
814
+ <button class="trim-action-btn" @click=${() => this.previewTrimmedSection()}>
815
+ Preview Selection
816
+ </button>
817
+ </div>
818
+ </div>
819
+ </div>
820
+ <div class="preview-modal-actions">
821
+ <button class="preview-btn secondary" @click=${() => this.discardRecording()}>Discard</button>
822
+ <button
823
+ class="preview-btn primary"
824
+ ?disabled=${this.isExporting}
825
+ @click=${() => this.downloadRecording()}
826
+ >
827
+ ${this.isExporting ? html `<span class="export-spinner"></span>Exporting...` : 'Download'}
828
+ </button>
829
+ </div>
830
+ </div>
831
+ </div>
832
+ `;
833
+ }
834
+ // ==================== Audio Methods ====================
835
+ async handleAudioToggle(enabled) {
836
+ this.audioEnabled = enabled;
837
+ if (enabled) {
838
+ this.availableMicrophones = await this.recorderService.loadMicrophones(true);
839
+ if (this.availableMicrophones.length > 0 && !this.selectedMicrophoneId) {
840
+ this.selectedMicrophoneId = this.availableMicrophones[0].deviceId;
841
+ await this.recorderService.startAudioMonitoring(this.selectedMicrophoneId);
842
+ }
843
+ }
844
+ else {
845
+ this.recorderService.stopAudioMonitoring();
846
+ this.selectedMicrophoneId = '';
847
+ this.audioLevel = 0;
848
+ }
849
+ }
850
+ async handleMicrophoneChange(deviceId) {
851
+ this.selectedMicrophoneId = deviceId;
852
+ if (deviceId) {
853
+ await this.recorderService.startAudioMonitoring(deviceId);
854
+ }
855
+ else {
856
+ this.recorderService.stopAudioMonitoring();
857
+ this.audioLevel = 0;
858
+ }
859
+ }
860
+ // ==================== Recording Methods ====================
861
+ async startRecording() {
862
+ try {
863
+ let viewportElement;
864
+ if (this.recordingMode === 'viewport' && this.dashboardRef) {
865
+ const wccFrame = await this.dashboardRef.wccFrame;
866
+ viewportElement = await wccFrame.getViewportElement();
867
+ }
868
+ await this.recorderService.startRecording({
869
+ mode: this.recordingMode,
870
+ audioDeviceId: this.audioEnabled ? this.selectedMicrophoneId : undefined,
871
+ viewportElement
872
+ });
873
+ this.panelState = 'recording';
874
+ this.dispatchEvent(new CustomEvent('recording-start', {
875
+ bubbles: true,
876
+ composed: true
877
+ }));
878
+ }
879
+ catch (error) {
880
+ console.error('Failed to start recording:', error);
881
+ this.panelState = 'options';
882
+ }
883
+ }
884
+ stopRecording() {
885
+ this.recorderService.stopRecording();
886
+ }
887
+ handleRecordingComplete(blob) {
888
+ if (this.previewVideoUrl) {
889
+ URL.revokeObjectURL(this.previewVideoUrl);
890
+ }
891
+ this.previewVideoUrl = URL.createObjectURL(blob);
892
+ this.panelState = 'preview';
893
+ this.dispatchEvent(new CustomEvent('recording-stop', {
894
+ bubbles: true,
895
+ composed: true
896
+ }));
897
+ }
898
+ discardRecording() {
899
+ if (this.previewVideoUrl) {
900
+ URL.revokeObjectURL(this.previewVideoUrl);
901
+ this.previewVideoUrl = '';
902
+ }
903
+ this.recorderService.reset();
904
+ this.trimStart = 0;
905
+ this.trimEnd = 0;
906
+ this.videoDuration = 0;
907
+ this.isExporting = false;
908
+ this.recordingDuration = 0;
909
+ this.close();
910
+ }
911
+ async downloadRecording() {
912
+ const recordedBlob = this.recorderService.recordedBlob;
913
+ if (!recordedBlob)
914
+ return;
915
+ this.isExporting = true;
916
+ try {
917
+ let blobToDownload;
918
+ const needsTrim = this.trimStart > 0.1 || this.trimEnd < this.videoDuration - 0.1;
919
+ if (needsTrim) {
920
+ const video = this.shadowRoot?.querySelector('.preview-video');
921
+ if (video) {
922
+ blobToDownload = await this.recorderService.exportTrimmedVideo(video, this.trimStart, this.trimEnd);
923
+ }
924
+ else {
925
+ blobToDownload = recordedBlob;
926
+ }
927
+ }
928
+ else {
929
+ blobToDownload = recordedBlob;
930
+ }
931
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
932
+ const filename = `wcctools-recording-${timestamp}.webm`;
933
+ const url = URL.createObjectURL(blobToDownload);
934
+ const a = document.createElement('a');
935
+ a.href = url;
936
+ a.download = filename;
937
+ document.body.appendChild(a);
938
+ a.click();
939
+ document.body.removeChild(a);
940
+ URL.revokeObjectURL(url);
941
+ this.discardRecording();
942
+ }
943
+ catch (error) {
944
+ console.error('Error exporting video:', error);
945
+ this.isExporting = false;
946
+ }
947
+ }
948
+ // ==================== Trim Methods ====================
949
+ handleVideoLoaded(video) {
950
+ // WebM files from MediaRecorder may have Infinity/NaN duration
951
+ // Fall back to the tracked recording duration
952
+ const duration = Number.isFinite(video.duration) ? video.duration : this.recordingDuration;
953
+ this.videoDuration = duration;
954
+ this.trimStart = 0;
955
+ this.trimEnd = duration;
956
+ }
957
+ formatDuration(seconds) {
958
+ const mins = Math.floor(seconds / 60);
959
+ const secs = seconds % 60;
960
+ return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
961
+ }
962
+ getHandlePositionStyle(time) {
963
+ if (this.videoDuration === 0)
964
+ return '12px';
965
+ const percentage = time / this.videoDuration;
966
+ // Formula: 12px padding + percentage of remaining width (total - 24px padding)
967
+ // At 0%: 12px (left edge of track)
968
+ // At 100%: calc(100% - 12px) (right edge of track)
969
+ return `calc(12px + ${(percentage * 100).toFixed(2)}% - ${(percentage * 24).toFixed(2)}px)`;
970
+ }
971
+ getHandlePositionFromEndStyle(time) {
972
+ if (this.videoDuration === 0)
973
+ return '12px';
974
+ const percentage = time / this.videoDuration;
975
+ const remainingPercentage = 1 - percentage;
976
+ // For CSS 'right' property: distance from right edge
977
+ // At trimEnd = 100%: right = 12px (at right edge of track)
978
+ // At trimEnd = 0%: right = calc(100% - 12px) (at left edge of track)
979
+ return `calc(12px + ${(remainingPercentage * 100).toFixed(2)}% - ${(remainingPercentage * 24).toFixed(2)}px)`;
980
+ }
981
+ handleTimelineClick(e) {
982
+ if (this.isDraggingTrim)
983
+ return;
984
+ const timeline = e.currentTarget;
985
+ const rect = timeline.getBoundingClientRect();
986
+ const x = e.clientX - rect.left;
987
+ const percentage = Math.max(0, Math.min(1, (x - 12) / (rect.width - 24)));
988
+ const time = percentage * this.videoDuration;
989
+ const video = this.shadowRoot?.querySelector('.preview-video');
990
+ if (video) {
991
+ video.currentTime = time;
992
+ }
993
+ }
994
+ handleTimelineDrag(e) {
995
+ if (!this.isDraggingTrim)
996
+ return;
997
+ const timeline = e.currentTarget;
998
+ const rect = timeline.getBoundingClientRect();
999
+ const x = e.clientX - rect.left;
1000
+ const percentage = Math.max(0, Math.min(1, (x - 12) / (rect.width - 24)));
1001
+ const time = percentage * this.videoDuration;
1002
+ const minDuration = 1;
1003
+ if (this.isDraggingTrim === 'start') {
1004
+ this.trimStart = Math.min(time, this.trimEnd - minDuration);
1005
+ this.trimStart = Math.max(0, this.trimStart);
1006
+ }
1007
+ else if (this.isDraggingTrim === 'end') {
1008
+ this.trimEnd = Math.max(time, this.trimStart + minDuration);
1009
+ this.trimEnd = Math.min(this.videoDuration, this.trimEnd);
1010
+ }
1011
+ const video = this.shadowRoot?.querySelector('.preview-video');
1012
+ if (video) {
1013
+ video.currentTime = this.isDraggingTrim === 'start' ? this.trimStart : this.trimEnd;
1014
+ }
1015
+ }
1016
+ handleTimelineDragEnd() {
1017
+ this.isDraggingTrim = null;
1018
+ }
1019
+ resetTrim() {
1020
+ this.trimStart = 0;
1021
+ this.trimEnd = this.videoDuration;
1022
+ const video = this.shadowRoot?.querySelector('.preview-video');
1023
+ if (video) {
1024
+ video.currentTime = 0;
1025
+ }
1026
+ }
1027
+ previewTrimmedSection() {
1028
+ const video = this.shadowRoot?.querySelector('.preview-video');
1029
+ if (!video)
1030
+ return;
1031
+ video.currentTime = this.trimStart;
1032
+ video.play();
1033
+ const checkTime = () => {
1034
+ if (video.currentTime >= this.trimEnd) {
1035
+ video.pause();
1036
+ video.removeEventListener('timeupdate', checkTime);
1037
+ }
1038
+ };
1039
+ video.addEventListener('timeupdate', checkTime);
1040
+ }
1041
+ // ==================== Lifecycle ====================
1042
+ close() {
1043
+ this.recorderService.stopAudioMonitoring();
1044
+ this.dispatchEvent(new CustomEvent('close', {
1045
+ bubbles: true,
1046
+ composed: true
1047
+ }));
1048
+ }
1049
+ async disconnectedCallback() {
1050
+ await super.disconnectedCallback();
1051
+ this.recorderService.dispose();
1052
+ if (this.previewVideoUrl) {
1053
+ URL.revokeObjectURL(this.previewVideoUrl);
1054
+ }
1055
+ }
1056
+ static {
1057
+ __runInitializers(_classThis, _classExtraInitializers);
1058
+ }
1059
+ };
1060
+ return WccRecordingPanel = _classThis;
1061
+ })();
1062
+ export { WccRecordingPanel };
1063
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjLXJlY29yZGluZy1wYW5lbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3dlYi9lbGVtZW50cy93Y2MtcmVjb3JkaW5nLXBhbmVsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQXVCLE1BQU0sNkJBQTZCLENBQUM7QUFDMUgsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0lBSXJELGlCQUFpQjs0QkFEN0IsYUFBYSxDQUFDLHFCQUFxQixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7aUNBQW5CLFNBQVEsV0FBVzs7Ozt3Q0FFL0MsUUFBUSxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDO3NDQUk5QixLQUFLLEVBQUU7eUNBSVAsS0FBSyxFQUFFO3dDQUdQLEtBQUssRUFBRTtnREFHUCxLQUFLLEVBQUU7Z0RBR1AsS0FBSyxFQUFFO3NDQUdQLEtBQUssRUFBRTs2Q0FJUCxLQUFLLEVBQUU7MkNBSVAsS0FBSyxFQUFFO3FDQUdQLEtBQUssRUFBRTttQ0FHUCxLQUFLLEVBQUU7eUNBR1AsS0FBSyxFQUFFOzBDQUdQLEtBQUssRUFBRTt1Q0FHUCxLQUFLLEVBQUU7WUExQ1IseUxBQVMsWUFBWSw2QkFBWixZQUFZLG1HQUFlO1lBSXBDLG1MQUFTLFVBQVUsNkJBQVYsVUFBVSwrRkFBa0Q7WUFJckUsNExBQVMsYUFBYSw2QkFBYixhQUFhLHFHQUFxQztZQUczRCx5TEFBUyxZQUFZLDZCQUFaLFlBQVksbUdBQWtCO1lBR3ZDLGlOQUFTLG9CQUFvQiw2QkFBcEIsb0JBQW9CLG1IQUFjO1lBRzNDLGlOQUFTLG9CQUFvQiw2QkFBcEIsb0JBQW9CLG1I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