@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.
Files changed (42) hide show
  1. package/dist_bundle/bundle.js +1764 -218
  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 +11 -10
  7. package/dist_ts_web/elements/wcc-dashboard.js +370 -246
  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 +1067 -0
  16. package/dist_ts_web/elements/wcc-sidebar.d.ts +7 -5
  17. package/dist_ts_web/elements/wcc-sidebar.js +250 -81
  18. package/dist_ts_web/elements/wcctools.helpers.d.ts +13 -0
  19. package/dist_ts_web/elements/wcctools.helpers.js +26 -1
  20. package/dist_ts_web/index.d.ts +3 -0
  21. package/dist_ts_web/index.js +5 -1
  22. package/dist_ts_web/services/ffmpeg.service.d.ts +42 -0
  23. package/dist_ts_web/services/ffmpeg.service.js +276 -0
  24. package/dist_ts_web/services/mp4.service.d.ts +32 -0
  25. package/dist_ts_web/services/mp4.service.js +139 -0
  26. package/dist_ts_web/services/recorder.service.d.ts +44 -0
  27. package/dist_ts_web/services/recorder.service.js +307 -0
  28. package/dist_watch/bundle.js +2126 -541
  29. package/dist_watch/bundle.js.map +4 -4
  30. package/package.json +8 -8
  31. package/readme.md +133 -141
  32. package/ts_web/00_commitinfo_data.ts +1 -1
  33. package/ts_web/elements/wcc-dashboard.ts +86 -26
  34. package/ts_web/elements/wcc-frame.ts +3 -3
  35. package/ts_web/elements/wcc-properties.ts +53 -9
  36. package/ts_web/elements/wcc-record-button.ts +108 -0
  37. package/ts_web/elements/wcc-recording-panel.ts +978 -0
  38. package/ts_web/elements/wcc-sidebar.ts +133 -22
  39. package/ts_web/elements/wcctools.helpers.ts +31 -0
  40. package/ts_web/index.ts +5 -0
  41. package/ts_web/readme.md +123 -0
  42. package/ts_web/services/recorder.service.ts +393 -0
@@ -0,0 +1,1067 @@
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
+ ];
670
+ render() {
671
+ if (this.panelState === 'options') {
672
+ return this.renderOptionsPanel();
673
+ }
674
+ else if (this.panelState === 'preview') {
675
+ return this.renderPreviewModal();
676
+ }
677
+ return html ``;
678
+ }
679
+ renderOptionsPanel() {
680
+ return html `
681
+ <div class="recording-options-panel">
682
+ <div class="recording-options-header">
683
+ <span class="recording-options-title">Recording Settings</span>
684
+ <button class="recording-options-close" @click=${() => this.close()}>✕</button>
685
+ </div>
686
+ <div class="recording-options-content">
687
+ <div class="recording-option-group">
688
+ <div class="recording-option-label">Record Area</div>
689
+ <div class="recording-mode-buttons">
690
+ <button
691
+ class="recording-mode-btn ${this.recordingMode === 'viewport' ? 'selected' : ''}"
692
+ @click=${() => this.recordingMode = 'viewport'}
693
+ >
694
+ Viewport Only
695
+ </button>
696
+ <button
697
+ class="recording-mode-btn ${this.recordingMode === 'screen' ? 'selected' : ''}"
698
+ @click=${() => this.recordingMode = 'screen'}
699
+ >
700
+ Entire Screen
701
+ </button>
702
+ </div>
703
+ </div>
704
+
705
+ <div class="recording-option-group">
706
+ <div class="recording-option-label">Audio</div>
707
+ <div class="audio-toggle">
708
+ <input
709
+ type="checkbox"
710
+ id="audioToggle"
711
+ ?checked=${this.audioEnabled}
712
+ @change=${(e) => this.handleAudioToggle(e.target.checked)}
713
+ />
714
+ <label for="audioToggle">Enable Microphone</label>
715
+ </div>
716
+
717
+ ${this.audioEnabled ? html `
718
+ <select
719
+ class="microphone-select"
720
+ .value=${this.selectedMicrophoneId}
721
+ @change=${(e) => this.handleMicrophoneChange(e.target.value)}
722
+ >
723
+ <option value="">Select Microphone...</option>
724
+ ${this.availableMicrophones.map(mic => html `
725
+ <option value=${mic.deviceId}>${mic.label || `Microphone ${mic.deviceId.slice(0, 8)}`}</option>
726
+ `)}
727
+ </select>
728
+
729
+ ${this.selectedMicrophoneId ? html `
730
+ <div class="audio-level-container">
731
+ <div class="audio-level-label">Input Level</div>
732
+ <div class="audio-level-bar">
733
+ <div class="audio-level-fill" style="width: ${this.audioLevel}%"></div>
734
+ </div>
735
+ </div>
736
+ ` : null}
737
+ ` : null}
738
+ </div>
739
+
740
+ <button class="start-recording-btn" @click=${() => this.startRecording()}>
741
+ <div class="rec-dot"></div>
742
+ Start Recording
743
+ </button>
744
+ </div>
745
+ </div>
746
+ `;
747
+ }
748
+ renderPreviewModal() {
749
+ return html `
750
+ <div class="preview-modal-overlay" @click=${(e) => {
751
+ if (e.target.classList.contains('preview-modal-overlay')) {
752
+ this.discardRecording();
753
+ }
754
+ }}>
755
+ <div class="preview-modal">
756
+ <div class="preview-modal-header">
757
+ <span class="preview-modal-title">Recording Preview</span>
758
+ <button class="preview-modal-close" @click=${() => this.discardRecording()}>✕</button>
759
+ </div>
760
+ <div class="preview-modal-content">
761
+ <div class="preview-video-container">
762
+ <video
763
+ class="preview-video"
764
+ src=${this.previewVideoUrl}
765
+ controls
766
+ @loadedmetadata=${(e) => this.handleVideoLoaded(e.target)}
767
+ ></video>
768
+ </div>
769
+
770
+ <!-- Trim Section -->
771
+ <div class="trim-section">
772
+ <div class="trim-section-header">
773
+ <span class="trim-section-title">Trim Video</span>
774
+ <span class="trim-duration-info">
775
+ ${this.formatDuration(Math.floor(this.trimEnd - this.trimStart))}
776
+ ${this.trimStart > 0 || this.trimEnd < this.videoDuration
777
+ ? `(trimmed from ${this.formatDuration(Math.floor(this.videoDuration))})`
778
+ : ''}
779
+ </span>
780
+ </div>
781
+
782
+ <div
783
+ class="trim-timeline"
784
+ @mousedown=${(e) => this.handleTimelineClick(e)}
785
+ @mousemove=${(e) => this.handleTimelineDrag(e)}
786
+ @mouseup=${() => this.handleTimelineDragEnd()}
787
+ @mouseleave=${() => this.handleTimelineDragEnd()}
788
+ >
789
+ <div class="trim-track"></div>
790
+ <div
791
+ class="trim-selected"
792
+ style="left: ${this.getHandlePositionStyle(this.trimStart)}; right: ${this.getHandlePositionFromEndStyle(this.trimEnd)};"
793
+ ></div>
794
+ <div
795
+ class="trim-handle start-handle"
796
+ style="left: ${this.getHandlePositionStyle(this.trimStart)};"
797
+ @mousedown=${(e) => { e.stopPropagation(); this.isDraggingTrim = 'start'; }}
798
+ ></div>
799
+ <div
800
+ class="trim-handle end-handle"
801
+ style="left: ${this.getHandlePositionStyle(this.trimEnd)};"
802
+ @mousedown=${(e) => { e.stopPropagation(); this.isDraggingTrim = 'end'; }}
803
+ ></div>
804
+ </div>
805
+
806
+ <div class="trim-time-labels">
807
+ <span>${this.formatDuration(Math.floor(this.trimStart))}</span>
808
+ <span>${this.formatDuration(Math.floor(this.trimEnd))}</span>
809
+ </div>
810
+
811
+ <div class="trim-actions">
812
+ <button class="trim-action-btn" @click=${() => this.resetTrim()}>
813
+ Reset Trim
814
+ </button>
815
+ <button class="trim-action-btn" @click=${() => this.previewTrimmedSection()}>
816
+ Preview Selection
817
+ </button>
818
+ </div>
819
+ </div>
820
+
821
+ </div>
822
+ <div class="preview-modal-actions">
823
+ <button class="preview-btn secondary" @click=${() => this.discardRecording()}>Discard</button>
824
+ <button
825
+ class="preview-btn primary"
826
+ ?disabled=${this.isExporting}
827
+ @click=${() => this.downloadRecording()}
828
+ >
829
+ ${this.isExporting ? html `<span class="export-spinner"></span>Exporting...` : 'Download WebM'}
830
+ </button>
831
+ </div>
832
+ </div>
833
+ </div>
834
+ `;
835
+ }
836
+ // ==================== Audio Methods ====================
837
+ async handleAudioToggle(enabled) {
838
+ this.audioEnabled = enabled;
839
+ if (enabled) {
840
+ this.availableMicrophones = await this.recorderService.loadMicrophones(true);
841
+ if (this.availableMicrophones.length > 0 && !this.selectedMicrophoneId) {
842
+ this.selectedMicrophoneId = this.availableMicrophones[0].deviceId;
843
+ await this.recorderService.startAudioMonitoring(this.selectedMicrophoneId);
844
+ }
845
+ }
846
+ else {
847
+ this.recorderService.stopAudioMonitoring();
848
+ this.selectedMicrophoneId = '';
849
+ this.audioLevel = 0;
850
+ }
851
+ }
852
+ async handleMicrophoneChange(deviceId) {
853
+ this.selectedMicrophoneId = deviceId;
854
+ if (deviceId) {
855
+ await this.recorderService.startAudioMonitoring(deviceId);
856
+ }
857
+ else {
858
+ this.recorderService.stopAudioMonitoring();
859
+ this.audioLevel = 0;
860
+ }
861
+ }
862
+ // ==================== Recording Methods ====================
863
+ async startRecording() {
864
+ try {
865
+ let viewportElement;
866
+ if (this.recordingMode === 'viewport' && this.dashboardRef) {
867
+ const wccFrame = await this.dashboardRef.wccFrame;
868
+ viewportElement = await wccFrame.getViewportElement();
869
+ }
870
+ await this.recorderService.startRecording({
871
+ mode: this.recordingMode,
872
+ audioDeviceId: this.audioEnabled ? this.selectedMicrophoneId : undefined,
873
+ viewportElement
874
+ });
875
+ this.panelState = 'recording';
876
+ this.dispatchEvent(new CustomEvent('recording-start', {
877
+ bubbles: true,
878
+ composed: true
879
+ }));
880
+ }
881
+ catch (error) {
882
+ console.error('Failed to start recording:', error);
883
+ this.panelState = 'options';
884
+ }
885
+ }
886
+ stopRecording() {
887
+ this.recorderService.stopRecording();
888
+ }
889
+ handleRecordingComplete(blob) {
890
+ if (this.previewVideoUrl) {
891
+ URL.revokeObjectURL(this.previewVideoUrl);
892
+ }
893
+ this.previewVideoUrl = URL.createObjectURL(blob);
894
+ this.panelState = 'preview';
895
+ this.dispatchEvent(new CustomEvent('recording-stop', {
896
+ bubbles: true,
897
+ composed: true
898
+ }));
899
+ }
900
+ discardRecording() {
901
+ if (this.previewVideoUrl) {
902
+ URL.revokeObjectURL(this.previewVideoUrl);
903
+ this.previewVideoUrl = '';
904
+ }
905
+ this.recorderService.reset();
906
+ this.trimStart = 0;
907
+ this.trimEnd = 0;
908
+ this.videoDuration = 0;
909
+ this.isExporting = false;
910
+ this.recordingDuration = 0;
911
+ this.close();
912
+ }
913
+ async downloadRecording() {
914
+ const recordedBlob = this.recorderService.recordedBlob;
915
+ if (!recordedBlob)
916
+ return;
917
+ this.isExporting = true;
918
+ try {
919
+ let blobToDownload;
920
+ // Handle trimming if needed
921
+ const needsTrim = this.trimStart > 0.1 || this.trimEnd < this.videoDuration - 0.1;
922
+ if (needsTrim) {
923
+ const video = this.shadowRoot?.querySelector('.preview-video');
924
+ if (video) {
925
+ blobToDownload = await this.recorderService.exportTrimmedVideo(video, this.trimStart, this.trimEnd);
926
+ }
927
+ else {
928
+ blobToDownload = recordedBlob;
929
+ }
930
+ }
931
+ else {
932
+ blobToDownload = recordedBlob;
933
+ }
934
+ // Trigger download
935
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
936
+ const filename = `wcctools-recording-${timestamp}.webm`;
937
+ const url = URL.createObjectURL(blobToDownload);
938
+ const a = document.createElement('a');
939
+ a.href = url;
940
+ a.download = filename;
941
+ document.body.appendChild(a);
942
+ a.click();
943
+ document.body.removeChild(a);
944
+ URL.revokeObjectURL(url);
945
+ this.discardRecording();
946
+ }
947
+ catch (error) {
948
+ console.error('Error exporting video:', error);
949
+ this.isExporting = false;
950
+ }
951
+ }
952
+ // ==================== Trim Methods ====================
953
+ handleVideoLoaded(video) {
954
+ // WebM files from MediaRecorder may have Infinity/NaN duration
955
+ // Fall back to the tracked recording duration
956
+ const duration = Number.isFinite(video.duration) ? video.duration : this.recordingDuration;
957
+ this.videoDuration = duration;
958
+ this.trimStart = 0;
959
+ this.trimEnd = duration;
960
+ }
961
+ formatDuration(seconds) {
962
+ const mins = Math.floor(seconds / 60);
963
+ const secs = seconds % 60;
964
+ return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
965
+ }
966
+ getHandlePositionStyle(time) {
967
+ if (this.videoDuration === 0)
968
+ return '12px';
969
+ const percentage = time / this.videoDuration;
970
+ // Formula: 12px padding + percentage of remaining width (total - 24px padding)
971
+ // At 0%: 12px (left edge of track)
972
+ // At 100%: calc(100% - 12px) (right edge of track)
973
+ return `calc(12px + ${(percentage * 100).toFixed(2)}% - ${(percentage * 24).toFixed(2)}px)`;
974
+ }
975
+ getHandlePositionFromEndStyle(time) {
976
+ if (this.videoDuration === 0)
977
+ return '12px';
978
+ const percentage = time / this.videoDuration;
979
+ const remainingPercentage = 1 - percentage;
980
+ // For CSS 'right' property: distance from right edge
981
+ // At trimEnd = 100%: right = 12px (at right edge of track)
982
+ // At trimEnd = 0%: right = calc(100% - 12px) (at left edge of track)
983
+ return `calc(12px + ${(remainingPercentage * 100).toFixed(2)}% - ${(remainingPercentage * 24).toFixed(2)}px)`;
984
+ }
985
+ handleTimelineClick(e) {
986
+ if (this.isDraggingTrim)
987
+ return;
988
+ const timeline = e.currentTarget;
989
+ const rect = timeline.getBoundingClientRect();
990
+ const x = e.clientX - rect.left;
991
+ const percentage = Math.max(0, Math.min(1, (x - 12) / (rect.width - 24)));
992
+ const time = percentage * this.videoDuration;
993
+ const video = this.shadowRoot?.querySelector('.preview-video');
994
+ if (video) {
995
+ video.currentTime = time;
996
+ }
997
+ }
998
+ handleTimelineDrag(e) {
999
+ if (!this.isDraggingTrim)
1000
+ return;
1001
+ const timeline = e.currentTarget;
1002
+ const rect = timeline.getBoundingClientRect();
1003
+ const x = e.clientX - rect.left;
1004
+ const percentage = Math.max(0, Math.min(1, (x - 12) / (rect.width - 24)));
1005
+ const time = percentage * this.videoDuration;
1006
+ const minDuration = 1;
1007
+ if (this.isDraggingTrim === 'start') {
1008
+ this.trimStart = Math.min(time, this.trimEnd - minDuration);
1009
+ this.trimStart = Math.max(0, this.trimStart);
1010
+ }
1011
+ else if (this.isDraggingTrim === 'end') {
1012
+ this.trimEnd = Math.max(time, this.trimStart + minDuration);
1013
+ this.trimEnd = Math.min(this.videoDuration, this.trimEnd);
1014
+ }
1015
+ const video = this.shadowRoot?.querySelector('.preview-video');
1016
+ if (video) {
1017
+ video.currentTime = this.isDraggingTrim === 'start' ? this.trimStart : this.trimEnd;
1018
+ }
1019
+ }
1020
+ handleTimelineDragEnd() {
1021
+ this.isDraggingTrim = null;
1022
+ }
1023
+ resetTrim() {
1024
+ this.trimStart = 0;
1025
+ this.trimEnd = this.videoDuration;
1026
+ const video = this.shadowRoot?.querySelector('.preview-video');
1027
+ if (video) {
1028
+ video.currentTime = 0;
1029
+ }
1030
+ }
1031
+ previewTrimmedSection() {
1032
+ const video = this.shadowRoot?.querySelector('.preview-video');
1033
+ if (!video)
1034
+ return;
1035
+ video.currentTime = this.trimStart;
1036
+ video.play();
1037
+ const checkTime = () => {
1038
+ if (video.currentTime >= this.trimEnd) {
1039
+ video.pause();
1040
+ video.removeEventListener('timeupdate', checkTime);
1041
+ }
1042
+ };
1043
+ video.addEventListener('timeupdate', checkTime);
1044
+ }
1045
+ // ==================== Lifecycle ====================
1046
+ close() {
1047
+ this.recorderService.stopAudioMonitoring();
1048
+ this.dispatchEvent(new CustomEvent('close', {
1049
+ bubbles: true,
1050
+ composed: true
1051
+ }));
1052
+ }
1053
+ async disconnectedCallback() {
1054
+ await super.disconnectedCallback();
1055
+ this.recorderService.dispose();
1056
+ if (this.previewVideoUrl) {
1057
+ URL.revokeObjectURL(this.previewVideoUrl);
1058
+ }
1059
+ }
1060
+ static {
1061
+ __runInitializers(_classThis, _classExtraInitializers);
1062
+ }
1063
+ };
1064
+ return WccRecordingPanel = _classThis;
1065
+ })();
1066
+ export { WccRecordingPanel };
1067
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjLXJlY29yZGluZy1wYW5lbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3dlYi9lbGVtZW50cy93Y2MtcmVjb3JkaW5nLXBhbmVsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQXVCLE1BQU0sNkJBQTZCLENBQUM7QUFDMUgsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0lBSXJELGlCQUFpQjs0QkFEN0IsYUFBYSxDQUFDLHFCQUFxQixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7aUNBQW5CLFNBQVEsV0FBVzs7Ozt3Q0FFL0MsUUFBUSxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDO3NDQUk5QixLQUFLLEVBQUU7eUNBSVAsS0FBSyxFQUFFO3dDQUdQLEtBQUssRUFBRTtnREFHUCxLQUFLLEVBQUU7Z0RBR1AsS0FBSyxFQUFFO3NDQUdQLEtBQUssRUFBRTs2Q0FJUCxLQUFLLEVBQUU7MkNBSVAsS0FBSyxFQUFFO3FDQUdQLEtBQUssRUFBRTttQ0FHUCxLQUFLLEVBQUU7eUNBR1AsS0FBSyxFQUFFOzBDQUdQLEtBQUssRUFBRTt1Q0FHUCxLQUFLLEVBQUU7WUExQ1IseUxBQVMsWUFBWSw2QkFBWixZQUFZLG1HQUFlO1lBSXBDLG1MQUFTLFVBQVUsNkJBQVYsVUFBVSwrRkFBa0Q7WUFJckUsNExBQVMsYUFBYSw2QkFBYixhQUFhLHFHQUFxQztZQUczRCx5TEFBUyxZQUFZLDZCQUFaLFlBQVksbUdBQWtCO1lBR3ZDLGlOQUFTLG9CQUFvQiw2QkFBcEIsb0JBQW9CLG1IQUFjO1lBRzNDLGlOQUFTLG9CQUFvQiw2QkFBcEIsb0JBQW9CLG1IQUF5QjtZQUd0RCxtTEFBUyxVQUFVLDZCQUFWLFVBQVUsK0ZBQWE7WUFJaEMsd01BQVMsaUJBQWlCLDZCQUFqQixpQkFBaUIsNkdBQWE7WUFJdkMsa01BQVMsZUFBZSw2QkFBZixlQUFlLHlHQUFjO1lBR3RDLGdMQUFTLFNBQVMsNkJBQVQsU0FBUyw2RkFBYTtZQUcvQiwwS0FBUyxPQUFPLDZCQUFQLE9BQU8seUZBQWE7WUFHN0IsNExBQVMsYUFBYSw2QkFBYixhQUFhLHFHQUFhO1lBR25DLCtMQUFTLGNBQWMsNkJBQWQsY0FBYyx1R0FBZ0M7WUFHdkQsc0xBQVMsV0FBVyw2QkFBWCxXQUFXLGlHQUFrQjtZQTlDeEMsNktBNDhCQzs7OztRQXo4QkMsNkZBQW9DO1FBRnBDLHlCQUF5QjtRQUV6QixJQUFTLFlBQVksa0RBQWU7UUFBcEMsSUFBUyxZQUFZLHdEQUFlO1FBSXBDLDRJQUEyRCxTQUFTLEdBQUM7UUFGckUsY0FBYztRQUVkLElBQVMsVUFBVSxnREFBa0Q7UUFBckUsSUFBUyxVQUFVLHNEQUFrRDtRQUlyRSxnSkFBZ0QsVUFBVSxHQUFDO1FBRjNELG9CQUFvQjtRQUVwQixJQUFTLGFBQWEsbURBQXFDO1FBQTNELElBQVMsYUFBYSx5REFBcUM7UUFHM0QsaUpBQWlDLEtBQUssR0FBQztRQUF2QyxJQUFTLFlBQVksa0RBQWtCO1FBQXZDLElBQVMsWUFBWSx3REFBa0I7UUFHdkMsZ0tBQXdDLEVBQUUsR0FBQztRQUEzQyxJQUFTLG9CQUFvQiwwREFBYztRQUEzQyxJQUFTLG9CQUFvQixnRUFBYztRQUczQyx3S0FBbUQsRUFBRSxHQUFDO1FBQXRELElBQVMsb0JBQW9CLDBEQUF5QjtRQUF0RCxJQUFTLG9CQUFvQixnRUFBeUI7UUFHdEQsb0pBQThCLENBQUMsR0FBQztRQUFoQyxJQUFTLFVBQVUsZ0RBQWE7UUFBaEMsSUFBUyxVQUFVLHNEQUFhO1FBSWhDLHdKQUFxQyxDQUFDLEdBQUM7UUFGdkMsa0JBQWtCO1FBRWxCLElBQVMsaUJBQWlCLHVEQUFhO1FBQXZDLElBQVMsaUJBQWlCLDZEQUFhO1FBSXZDLDJKQUFtQyxFQUFFLEdBQUM7UUFGdEMscUJBQXFCO1FBRXJCLElBQVMsZUFBZSxxREFBYztRQUF0QyxJQUFTLGVBQWUsMkRBQWM7UUFHdEMsNklBQTZCLENBQUMsR0FBQztRQUEvQixJQUFTLFNBQVMsK0NBQWE7UUFBL0IsSUFBUyxTQUFTLHFEQUFhO1FBRy9CLG1JQUEyQixDQUFDLEdBQUM7UUFBN0IsSUFBUyxPQUFPLDZDQUFhO1FBQTdCLElBQVMsT0FBTyxtREFBYTtRQUc3Qiw2SUFBaUMsQ0FBQyxHQUFDO1FBQW5DLElBQVMsYUFBYSxtREFBYTtRQUFuQyxJQUFTLGFBQWEseURBQWE7UUFHbkMscUpBQWtELElBQUksR0FBQztRQUF2RCxJQUFTLGNBQWMsb0RBQWdDO1FBQXZELElBQVMsY0FBYywwREFBZ0M7UUFHdkQsZ0pBQWdDLEtBQUssR0FBQztRQUF0QyxJQUFTLFdBQVcsaURBQWtCO1FBQXRDLElBQVMsV0FBVyx1REFBa0I7UUFFdEMsbUJBQW1CO1FBQ1gsZUFBZSwyREFBa0I7UUFFekM7WUFDRSxLQUFLLEVBQUUsQ0FBQztZQUNSLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxlQUFlLENBQUM7Z0JBQ3pDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUU7b0JBQzdCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxRQUFRLENBQUM7b0JBQ2xDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxXQUFXLENBQUMsaUJBQWlCLEVBQUU7d0JBQ3BELE1BQU0sRUFBRSxFQUFFLFFBQVEsRUFBRTt3QkFDcEIsT0FBTyxFQUFFLElBQUk7d0JBQ2IsUUFBUSxFQUFFLElBQUk7cUJBQ2YsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sQ0FBQztnQkFDRCxtQkFBbUIsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO29CQUM1QixJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3JDLENBQUM7Z0JBQ0Qsa0JBQWtCLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtvQkFDNUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7Z0JBQzFCLENBQUM7Z0JBQ0QsYUFBYSxFQUFFLEdBQUcsRUFBRTtvQkFDbEIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUN2QixDQUFDO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVNLE1BQU0sQ0FBQyxNQUFNLEdBQUc7WUFDckIsR0FBRyxDQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0tBMmRGO1NBQ0YsQ0FBQztRQUVLLE1BQU07WUFDWCxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ2xDLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDbkMsQ0FBQztpQkFBTSxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3pDLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDbkMsQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFBLEVBQUUsQ0FBQztRQUNoQixDQUFDO1FBRU8sa0JBQWtCO1lBQ3hCLE9BQU8sSUFBSSxDQUFBOzs7OzJEQUk0QyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFOzs7Ozs7OzRDQU9qQyxJQUFJLENBQUMsYUFBYSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFO3lCQUN0RSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLFVBQVU7Ozs7OzRDQUtsQixJQUFJLENBQUMsYUFBYSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFO3lCQUNwRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxHQUFHLFFBQVE7Ozs7Ozs7Ozs7Ozs7MkJBYWpDLElBQUksQ0FBQyxZQUFZOzBCQUNsQixDQUFDLENBQVEsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFFLENBQUMsQ0FBQyxNQUEyQixDQUFDLE9BQU8sQ0FBQzs7Ozs7Y0FLeEYsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBOzs7eUJBR2IsSUFBSSxDQUFDLG9CQUFvQjswQkFDeEIsQ0FBQyxDQUFRLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBRSxDQUFDLENBQUMsTUFBNEIsQ0FBQyxLQUFLLENBQUM7OztrQkFHeEYsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQTtrQ0FDekIsR0FBRyxDQUFDLFFBQVEsSUFBSSxHQUFHLENBQUMsS0FBSyxJQUFJLGNBQWMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO2lCQUN0RixDQUFDOzs7Z0JBR0YsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7Ozs7a0VBSWtCLElBQUksQ0FBQyxVQUFVOzs7ZUFHbEUsQ0FBQyxDQUFDLENBQUMsSUFBSTthQUNULENBQUMsQ0FBQyxDQUFDLElBQUk7Ozt1REFHbUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRTs7Ozs7O0tBTTdFLENBQUM7UUFDSixDQUFDO1FBRU8sa0JBQWtCO1lBQ3hCLE9BQU8sSUFBSSxDQUFBO2tEQUNtQyxDQUFDLENBQVEsRUFBRSxFQUFFO2dCQUN2RCxJQUFLLENBQUMsQ0FBQyxNQUFzQixDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLENBQUMsRUFBRSxDQUFDO29CQUMxRSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDMUIsQ0FBQztZQUNILENBQUM7Ozs7eURBSWtELEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTs7Ozs7O3NCQU1oRSxJQUFJLENBQUMsZUFBZTs7a0NBRVIsQ0FBQyxDQUFRLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsTUFBMEIsQ0FBQzs7Ozs7Ozs7O29CQVNoRixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7b0JBQzlELElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWE7Z0JBQ3ZELENBQUMsQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxHQUFHO2dCQUN6RSxDQUFDLENBQUMsRUFBRTs7Ozs7OzZCQU1LLENBQUMsQ0FBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDOzZCQUM5QyxDQUFDLENBQWEsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQzsyQkFDL0MsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFOzhCQUMvQixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQUU7Ozs7O2lDQUsvQixJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDOzs7O2lDQUl2RyxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQzsrQkFDN0MsQ0FBQyxDQUFhLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQzs7OztpQ0FJeEUsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7K0JBQzNDLENBQUMsQ0FBYSxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7Ozs7O3dCQUsvRSxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO3dCQUMvQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDOzs7O3lEQUlaLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Ozt5REFHdEIsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFOzs7Ozs7OzsyREFRaEMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFOzs7MEJBRzlELElBQUksQ0FBQyxXQUFXO3VCQUNuQixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUU7O2dCQUVyQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUEsa0RBQWtELENBQUMsQ0FBQyxDQUFDLGVBQWU7Ozs7O0tBS3RHLENBQUM7UUFDSixDQUFDO1FBRUQsMERBQTBEO1FBRWxELEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxPQUFnQjtZQUM5QyxJQUFJLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQztZQUM1QixJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUM3RSxJQUFJLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7b0JBQ3ZFLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO29CQUNsRSxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7Z0JBQzdFLENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLGVBQWUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUMzQyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsRUFBRSxDQUFDO2dCQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQztRQUVPLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxRQUFnQjtZQUNuRCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsUUFBUSxDQUFDO1lBQ3JDLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzVELENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsZUFBZSxDQUFDLG1CQUFtQixFQUFFLENBQUM7Z0JBQzNDLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO1lBQ3RCLENBQUM7UUFDSCxDQUFDO1FBRUQsOERBQThEO1FBRXRELEtBQUssQ0FBQyxjQUFjO1lBQzFCLElBQUksQ0FBQztnQkFDSCxJQUFJLGVBQXdDLENBQUM7Z0JBQzdDLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxVQUFVLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO29CQUMzRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDO29CQUNsRCxlQUFlLEdBQUcsTUFBTSxRQUFRLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztnQkFDeEQsQ0FBQztnQkFFRCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsY0FBYyxDQUFDO29CQUN4QyxJQUFJLEVBQUUsSUFBSSxDQUFDLGFBQWE7b0JBQ3hCLGFBQWEsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLFNBQVM7b0JBQ3hFLGVBQWU7aUJBQ2hCLENBQUMsQ0FBQztnQkFFSCxJQUFJLENBQUMsVUFBVSxHQUFHLFdBQVcsQ0FBQztnQkFDOUIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRTtvQkFDcEQsT0FBTyxFQUFFLElBQUk7b0JBQ2IsUUFBUSxFQUFFLElBQUk7aUJBQ2YsQ0FBQyxDQUFDLENBQUM7WUFDTixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixPQUFPLENBQUMsS0FBSyxDQUFDLDRCQUE0QixFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNuRCxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztZQUM5QixDQUFDO1FBQ0gsQ0FBQztRQUVNLGFBQWE7WUFDbEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN2QyxDQUFDO1FBRU8sdUJBQXVCLENBQUMsSUFBVTtZQUN4QyxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDekIsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDNUMsQ0FBQztZQUNELElBQUksQ0FBQyxlQUFlLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNqRCxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztZQUM1QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksV0FBVyxDQUFDLGdCQUFnQixFQUFFO2dCQUNuRCxPQUFPLEVBQUUsSUFBSTtnQkFDYixRQUFRLEVBQUUsSUFBSTthQUNmLENBQUMsQ0FBQyxDQUFDO1FBQ04sQ0FBQztRQUVPLGdCQUFnQjtZQUN0QixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDekIsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1lBQzVCLENBQUM7WUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7WUFDM0IsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsQ0FBQztRQUVPLEtBQUssQ0FBQyxpQkFBaUI7WUFDN0IsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUM7WUFDdkQsSUFBSSxDQUFDLFlBQVk7Z0JBQUUsT0FBTztZQUUxQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztZQUV4QixJQUFJLENBQUM7Z0JBQ0gsSUFBSSxjQUFvQixDQUFDO2dCQUV6Qiw0QkFBNEI7Z0JBQzVCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxJQUFJLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsR0FBRyxHQUFHLENBQUM7Z0JBRWxGLElBQUksU0FBUyxFQUFFLENBQUM7b0JBQ2QsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxhQUFhLENBQUMsZ0JBQWdCLENBQXFCLENBQUM7b0JBQ25GLElBQUksS0FBSyxFQUFFLENBQUM7d0JBQ1YsY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBQ3RHLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixjQUFjLEdBQUcsWUFBWSxDQUFDO29CQUNoQyxDQUFDO2dCQUNILENBQUM7cUJBQU0sQ0FBQztvQkFDTixjQUFjLEdBQUcsWUFBWSxDQUFDO2dCQUNoQyxDQUFDO2dCQUVELG1CQUFtQjtnQkFDbkIsTUFBTSxTQUFTLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQzlFLE1BQU0sUUFBUSxHQUFHLHNCQUFzQixTQUFTLE9BQU8sQ0FBQztnQkFFeEQsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDaEQsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDdEMsQ0FBQyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUM7Z0JBQ2IsQ0FBQyxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7Z0JBQ3RCLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM3QixDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1YsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzdCLEdBQUcsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBRXpCLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFCLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQy9DLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1lBQzNCLENBQUM7UUFDSCxDQUFDO1FBRUQseURBQXlEO1FBRWpELGlCQUFpQixDQUFDLEtBQXVCO1lBQy9DLCtEQUErRDtZQUMvRCw4Q0FBOEM7WUFDOUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztZQUMzRixJQUFJLENBQUMsYUFBYSxHQUFHLFFBQVEsQ0FBQztZQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQztZQUNuQixJQUFJLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQztRQUMxQixDQUFDO1FBRU8sY0FBYyxDQUFDLE9BQWU7WUFDcEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDdEMsTUFBTSxJQUFJLEdBQUcsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUMxQixPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNuRixDQUFDO1FBRU8sc0JBQXNCLENBQUMsSUFBWTtZQUN6QyxJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssQ0FBQztnQkFBRSxPQUFPLE1BQU0sQ0FBQztZQUM1QyxNQUFNLFVBQVUsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUM3QywrRUFBK0U7WUFDL0UsbUNBQW1DO1lBQ25DLG1EQUFtRDtZQUNuRCxPQUFPLGVBQWUsQ0FBQyxVQUFVLEdBQUcsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1FBQzlGLENBQUM7UUFFTyw2QkFBNkIsQ0FBQyxJQUFZO1lBQ2hELElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxDQUFDO2dCQUFFLE9BQU8sTUFBTSxDQUFDO1lBQzVDLE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1lBQzdDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxHQUFHLFVBQVUsQ0FBQztZQUMzQyxxREFBcUQ7WUFDckQsMkRBQTJEO1lBQzNELHFFQUFxRTtZQUNyRSxPQUFPLGVBQWUsQ0FBQyxtQkFBbUIsR0FBRyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsR0FBRyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNoSCxDQUFDO1FBRU8sbUJBQW1CLENBQUMsQ0FBYTtZQUN2QyxJQUFJLElBQUksQ0FBQyxjQUFjO2dCQUFFLE9BQU87WUFFaEMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLGFBQTRCLENBQUM7WUFDaEQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDOUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2hDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUUsTUFBTSxJQUFJLEdBQUcsVUFBVSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7WUFFN0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxhQUFhLENBQUMsZ0JBQWdCLENBQXFCLENBQUM7WUFDbkYsSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDVixLQUFLLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztZQUMzQixDQUFDO1FBQ0gsQ0FBQztRQUVPLGtCQUFrQixDQUFDLENBQWE7WUFDdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjO2dCQUFFLE9BQU87WUFFakMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLGFBQTRCLENBQUM7WUFDaEQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDOUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2hDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUUsTUFBTSxJQUFJLEdBQUcsVUFBVSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7WUFFN0MsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1lBRXRCLElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxPQUFPLEVBQUUsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxHQUFHLFdBQVcsQ0FBQyxDQUFDO2dCQUM1RCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMvQyxDQUFDO2lCQUFNLElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDekMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQyxDQUFDO2dCQUM1RCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDNUQsQ0FBQztZQUVELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDLGdCQUFnQixDQUFxQixDQUFDO1lBQ25GLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ1YsS0FBSyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztZQUN0RixDQUFDO1FBQ0gsQ0FBQztRQUVPLHFCQUFxQjtZQUMzQixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQztRQUM3QixDQUFDO1FBRU8sU0FBUztZQUNmLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO1lBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUVsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBcUIsQ0FBQztZQUNuRixJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUNWLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLENBQUM7UUFDSCxDQUFDO1FBRU8scUJBQXFCO1lBQzNCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDLGdCQUFnQixDQUFxQixDQUFDO1lBQ25GLElBQUksQ0FBQyxLQUFLO2dCQUFFLE9BQU87WUFFbkIsS0FBSyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ25DLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUViLE1BQU0sU0FBUyxHQUFHLEdBQUcsRUFBRTtnQkFDckIsSUFBSSxLQUFLLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDdEMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNkLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsU0FBUyxDQUFDLENBQUM7Z0JBQ3JELENBQUM7WUFDSCxDQUFDLENBQUM7WUFFRixLQUFLLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ2xELENBQUM7UUFFRCxzREFBc0Q7UUFFOUMsS0FBSztZQUNYLElBQUksQ0FBQyxlQUFlLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRTtnQkFDMUMsT0FBTyxFQUFFLElBQUk7Z0JBQ2IsUUFBUSxFQUFFLElBQUk7YUFDZixDQUFDLENBQUMsQ0FBQztRQUNOLENBQUM7UUFFRCxLQUFLLENBQUMsb0JBQW9CO1lBQ3hCLE1BQU0sS0FBSyxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMvQixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDekIsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDNUMsQ0FBQztRQUNILENBQUM7O1lBMzhCVSx1REFBaUI7Ozs7O1NBQWpCLGlCQUFpQiJ9