@design.estate/dees-wcctools 1.2.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_bundle/bundle.js +1764 -218
- package/dist_bundle/bundle.js.map +4 -4
- package/dist_ts_demotools/demotools.d.ts +1 -1
- package/dist_ts_demotools/demotools.js +86 -38
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/wcc-dashboard.d.ts +11 -10
- package/dist_ts_web/elements/wcc-dashboard.js +370 -246
- package/dist_ts_web/elements/wcc-frame.d.ts +3 -3
- package/dist_ts_web/elements/wcc-frame.js +108 -57
- package/dist_ts_web/elements/wcc-properties.d.ts +14 -8
- package/dist_ts_web/elements/wcc-properties.js +442 -323
- package/dist_ts_web/elements/wcc-record-button.d.ts +12 -0
- package/dist_ts_web/elements/wcc-record-button.js +165 -0
- package/dist_ts_web/elements/wcc-recording-panel.d.ts +42 -0
- package/dist_ts_web/elements/wcc-recording-panel.js +1067 -0
- package/dist_ts_web/elements/wcc-sidebar.d.ts +7 -5
- package/dist_ts_web/elements/wcc-sidebar.js +250 -81
- package/dist_ts_web/elements/wcctools.helpers.d.ts +13 -0
- package/dist_ts_web/elements/wcctools.helpers.js +26 -1
- package/dist_ts_web/index.d.ts +3 -0
- package/dist_ts_web/index.js +5 -1
- package/dist_ts_web/services/ffmpeg.service.d.ts +42 -0
- package/dist_ts_web/services/ffmpeg.service.js +276 -0
- package/dist_ts_web/services/mp4.service.d.ts +32 -0
- package/dist_ts_web/services/mp4.service.js +139 -0
- package/dist_ts_web/services/recorder.service.d.ts +44 -0
- package/dist_ts_web/services/recorder.service.js +307 -0
- package/dist_watch/bundle.js +2126 -541
- package/dist_watch/bundle.js.map +4 -4
- package/package.json +8 -8
- package/readme.md +133 -141
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/wcc-dashboard.ts +86 -26
- package/ts_web/elements/wcc-frame.ts +3 -3
- package/ts_web/elements/wcc-properties.ts +53 -9
- package/ts_web/elements/wcc-record-button.ts +108 -0
- package/ts_web/elements/wcc-recording-panel.ts +978 -0
- package/ts_web/elements/wcc-sidebar.ts +133 -22
- package/ts_web/elements/wcctools.helpers.ts +31 -0
- package/ts_web/index.ts +5 -0
- package/ts_web/readme.md +123 -0
- package/ts_web/services/recorder.service.ts +393 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DeesElement, property, html, customElement, type TemplateResult, queryAsync, render, domtools } from '@design.estate/dees-element';
|
|
2
|
-
import { resolveTemplateFactory } from './wcctools.helpers.js';
|
|
2
|
+
import { resolveTemplateFactory, getDemoAtIndex, getDemoCount, hasMultipleDemos } from './wcctools.helpers.js';
|
|
3
3
|
import type { TTemplateFactory } from './wcctools.helpers.js';
|
|
4
4
|
|
|
5
5
|
import * as plugins from '../wcctools.plugins.js';
|
|
@@ -17,38 +17,41 @@ import { WccFrame } from './wcc-frame.js';
|
|
|
17
17
|
export class WccDashboard extends DeesElement {
|
|
18
18
|
|
|
19
19
|
@property()
|
|
20
|
-
|
|
20
|
+
accessor selectedType: TElementType;
|
|
21
21
|
|
|
22
22
|
@property()
|
|
23
|
-
|
|
23
|
+
accessor selectedItemName: string;
|
|
24
24
|
|
|
25
25
|
@property()
|
|
26
|
-
|
|
26
|
+
accessor selectedItem: TTemplateFactory | DeesElement;
|
|
27
|
+
|
|
28
|
+
@property({ type: Number })
|
|
29
|
+
accessor selectedDemoIndex: number = 0;
|
|
27
30
|
|
|
28
31
|
@property()
|
|
29
|
-
|
|
32
|
+
accessor selectedViewport: plugins.deesDomtools.breakpoints.TViewport = 'desktop';
|
|
30
33
|
|
|
31
34
|
@property()
|
|
32
|
-
|
|
35
|
+
accessor selectedTheme: TTheme = 'dark';
|
|
33
36
|
|
|
34
37
|
@property()
|
|
35
|
-
|
|
38
|
+
accessor isFullscreen: boolean = false;
|
|
36
39
|
|
|
37
40
|
@property()
|
|
38
|
-
|
|
41
|
+
accessor pages: Record<string, TTemplateFactory> = {};
|
|
39
42
|
|
|
40
43
|
@property()
|
|
41
|
-
|
|
44
|
+
accessor elements: { [key: string]: DeesElement } = {};
|
|
42
45
|
|
|
43
46
|
@property()
|
|
44
|
-
|
|
47
|
+
accessor warning: string = null;
|
|
45
48
|
|
|
46
49
|
private frameScrollY: number = 0;
|
|
47
50
|
private sidebarScrollY: number = 0;
|
|
48
51
|
private scrollPositionsApplied: boolean = false;
|
|
49
52
|
|
|
50
53
|
@queryAsync('wcc-frame')
|
|
51
|
-
|
|
54
|
+
accessor wccFrame: Promise<WccFrame>;
|
|
52
55
|
|
|
53
56
|
constructor(
|
|
54
57
|
elementsArg?: { [key: string]: DeesElement },
|
|
@@ -151,11 +154,53 @@ export class WccDashboard extends DeesElement {
|
|
|
151
154
|
this.setupScrollListeners();
|
|
152
155
|
}, 500);
|
|
153
156
|
|
|
157
|
+
// Route with demo index (new format)
|
|
158
|
+
this.domtools.router.on(
|
|
159
|
+
'/wcctools-route/:itemType/:itemName/:demoIndex/:viewport/:theme',
|
|
160
|
+
async (routeInfo) => {
|
|
161
|
+
this.selectedType = routeInfo.params.itemType as TElementType;
|
|
162
|
+
this.selectedItemName = routeInfo.params.itemName;
|
|
163
|
+
this.selectedDemoIndex = parseInt(routeInfo.params.demoIndex) || 0;
|
|
164
|
+
this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
|
|
165
|
+
this.selectedTheme = routeInfo.params.theme as TTheme;
|
|
166
|
+
if (routeInfo.params.itemType === 'element') {
|
|
167
|
+
this.selectedItem = this.elements[routeInfo.params.itemName];
|
|
168
|
+
} else if (routeInfo.params.itemType === 'page') {
|
|
169
|
+
this.selectedItem = this.pages[routeInfo.params.itemName];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Restore scroll positions from query parameters
|
|
173
|
+
if (routeInfo.queryParams) {
|
|
174
|
+
const frameScrollY = routeInfo.queryParams.frameScrollY;
|
|
175
|
+
const sidebarScrollY = routeInfo.queryParams.sidebarScrollY;
|
|
176
|
+
|
|
177
|
+
if (frameScrollY) {
|
|
178
|
+
this.frameScrollY = parseInt(frameScrollY);
|
|
179
|
+
}
|
|
180
|
+
if (sidebarScrollY) {
|
|
181
|
+
this.sidebarScrollY = parseInt(sidebarScrollY);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Apply scroll positions after a short delay to ensure DOM is ready
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
this.applyScrollPositions();
|
|
187
|
+
}, 100);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const domtoolsInstance = await plugins.deesDomtools.elementBasic.setup();
|
|
191
|
+
this.selectedTheme === 'bright'
|
|
192
|
+
? domtoolsInstance.themeManager.goBright()
|
|
193
|
+
: domtoolsInstance.themeManager.goDark();
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Legacy route without demo index (for backwards compatibility)
|
|
154
198
|
this.domtools.router.on(
|
|
155
199
|
'/wcctools-route/:itemType/:itemName/:viewport/:theme',
|
|
156
200
|
async (routeInfo) => {
|
|
157
201
|
this.selectedType = routeInfo.params.itemType as TElementType;
|
|
158
202
|
this.selectedItemName = routeInfo.params.itemName;
|
|
203
|
+
this.selectedDemoIndex = 0; // Default to first demo
|
|
159
204
|
this.selectedViewport = routeInfo.params.viewport as breakpoints.TViewport;
|
|
160
205
|
this.selectedTheme = routeInfo.params.theme as TTheme;
|
|
161
206
|
if (routeInfo.params.itemType === 'element') {
|
|
@@ -163,25 +208,25 @@ export class WccDashboard extends DeesElement {
|
|
|
163
208
|
} else if (routeInfo.params.itemType === 'page') {
|
|
164
209
|
this.selectedItem = this.pages[routeInfo.params.itemName];
|
|
165
210
|
}
|
|
166
|
-
|
|
211
|
+
|
|
167
212
|
// Restore scroll positions from query parameters
|
|
168
213
|
if (routeInfo.queryParams) {
|
|
169
214
|
const frameScrollY = routeInfo.queryParams.frameScrollY;
|
|
170
215
|
const sidebarScrollY = routeInfo.queryParams.sidebarScrollY;
|
|
171
|
-
|
|
216
|
+
|
|
172
217
|
if (frameScrollY) {
|
|
173
218
|
this.frameScrollY = parseInt(frameScrollY);
|
|
174
219
|
}
|
|
175
220
|
if (sidebarScrollY) {
|
|
176
221
|
this.sidebarScrollY = parseInt(sidebarScrollY);
|
|
177
222
|
}
|
|
178
|
-
|
|
223
|
+
|
|
179
224
|
// Apply scroll positions after a short delay to ensure DOM is ready
|
|
180
225
|
setTimeout(() => {
|
|
181
226
|
this.applyScrollPositions();
|
|
182
227
|
}, 100);
|
|
183
228
|
}
|
|
184
|
-
|
|
229
|
+
|
|
185
230
|
const domtoolsInstance = await plugins.deesDomtools.elementBasic.setup();
|
|
186
231
|
this.selectedTheme === 'bright'
|
|
187
232
|
? domtoolsInstance.themeManager.goBright()
|
|
@@ -218,33 +263,48 @@ export class WccDashboard extends DeesElement {
|
|
|
218
263
|
this.setWarning(`component ${anonItem.name} does not expose a demo property.`);
|
|
219
264
|
return;
|
|
220
265
|
}
|
|
221
|
-
|
|
266
|
+
|
|
267
|
+
// Support both single demo (function) and multiple demos (array)
|
|
268
|
+
const isArray = Array.isArray(anonItem.demo);
|
|
269
|
+
const isFunction = typeof anonItem.demo === 'function';
|
|
270
|
+
|
|
271
|
+
if (!isArray && !isFunction) {
|
|
222
272
|
this.setWarning(
|
|
223
|
-
`component ${anonItem.name} has demo property, but it is not of
|
|
273
|
+
`component ${anonItem.name} has demo property, but it is not a function or array of functions`
|
|
224
274
|
);
|
|
225
275
|
return;
|
|
226
276
|
}
|
|
277
|
+
|
|
278
|
+
// Get the specific demo to render
|
|
279
|
+
const demoFactory = getDemoAtIndex(anonItem.demo, this.selectedDemoIndex);
|
|
280
|
+
if (!demoFactory) {
|
|
281
|
+
this.setWarning(
|
|
282
|
+
`component ${anonItem.name} does not have a demo at index ${this.selectedDemoIndex + 1}`
|
|
283
|
+
);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
227
287
|
this.setWarning(null);
|
|
228
288
|
const viewport = await wccFrame.getViewportElement();
|
|
229
|
-
const demoTemplate = await resolveTemplateFactory(
|
|
289
|
+
const demoTemplate = await resolveTemplateFactory(demoFactory);
|
|
230
290
|
render(demoTemplate, viewport);
|
|
231
291
|
}
|
|
232
292
|
}
|
|
233
293
|
|
|
234
294
|
public buildUrl() {
|
|
235
|
-
const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedViewport}/${this.selectedTheme}`;
|
|
295
|
+
const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
|
|
236
296
|
const queryParams = new URLSearchParams();
|
|
237
|
-
|
|
297
|
+
|
|
238
298
|
if (this.frameScrollY > 0) {
|
|
239
299
|
queryParams.set('frameScrollY', this.frameScrollY.toString());
|
|
240
300
|
}
|
|
241
301
|
if (this.sidebarScrollY > 0) {
|
|
242
302
|
queryParams.set('sidebarScrollY', this.sidebarScrollY.toString());
|
|
243
303
|
}
|
|
244
|
-
|
|
304
|
+
|
|
245
305
|
const queryString = queryParams.toString();
|
|
246
306
|
const fullUrl = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
|
247
|
-
|
|
307
|
+
|
|
248
308
|
this.domtools.router.pushUrl(fullUrl);
|
|
249
309
|
}
|
|
250
310
|
|
|
@@ -286,19 +346,19 @@ export class WccDashboard extends DeesElement {
|
|
|
286
346
|
}
|
|
287
347
|
|
|
288
348
|
private updateUrlWithScrollState() {
|
|
289
|
-
const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedViewport}/${this.selectedTheme}`;
|
|
349
|
+
const baseUrl = `/wcctools-route/${this.selectedType}/${this.selectedItemName}/${this.selectedDemoIndex}/${this.selectedViewport}/${this.selectedTheme}`;
|
|
290
350
|
const queryParams = new URLSearchParams();
|
|
291
|
-
|
|
351
|
+
|
|
292
352
|
if (this.frameScrollY > 0) {
|
|
293
353
|
queryParams.set('frameScrollY', this.frameScrollY.toString());
|
|
294
354
|
}
|
|
295
355
|
if (this.sidebarScrollY > 0) {
|
|
296
356
|
queryParams.set('sidebarScrollY', this.sidebarScrollY.toString());
|
|
297
357
|
}
|
|
298
|
-
|
|
358
|
+
|
|
299
359
|
const queryString = queryParams.toString();
|
|
300
360
|
const fullUrl = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
|
301
|
-
|
|
361
|
+
|
|
302
362
|
// Use replaceState to update URL without navigation
|
|
303
363
|
window.history.replaceState(null, '', fullUrl);
|
|
304
364
|
}
|
|
@@ -11,13 +11,13 @@ declare global {
|
|
|
11
11
|
@customElement('wcc-frame')
|
|
12
12
|
export class WccFrame extends DeesElement {
|
|
13
13
|
@property()
|
|
14
|
-
|
|
14
|
+
accessor viewport: string;
|
|
15
15
|
|
|
16
16
|
@property({ type: Boolean })
|
|
17
|
-
|
|
17
|
+
accessor advancedEditorOpen: boolean = false;
|
|
18
18
|
|
|
19
19
|
@property({ type: Boolean })
|
|
20
|
-
|
|
20
|
+
accessor isFullscreen: boolean = false;
|
|
21
21
|
|
|
22
22
|
public static styles = [
|
|
23
23
|
css`
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { DeesElement, property, html, customElement, type TemplateResult, state } from '@design.estate/dees-element';
|
|
2
2
|
import { WccDashboard } from './wcc-dashboard.js';
|
|
3
3
|
import type { TTemplateFactory } from './wcctools.helpers.js';
|
|
4
|
+
import './wcc-record-button.js';
|
|
5
|
+
import './wcc-recording-panel.js';
|
|
4
6
|
|
|
5
7
|
export type TPropertyType = 'String' | 'Number' | 'Boolean' | 'Object' | 'Enum' | 'Array';
|
|
6
8
|
|
|
@@ -18,28 +20,28 @@ export class WccProperties extends DeesElement {
|
|
|
18
20
|
@property({
|
|
19
21
|
type: WccDashboard
|
|
20
22
|
})
|
|
21
|
-
|
|
23
|
+
accessor dashboardRef: WccDashboard;
|
|
22
24
|
|
|
23
25
|
@property()
|
|
24
|
-
|
|
26
|
+
accessor selectedItem: TTemplateFactory | DeesElement;
|
|
25
27
|
|
|
26
28
|
@property()
|
|
27
|
-
|
|
29
|
+
accessor selectedViewport: TEnvironment = 'native';
|
|
28
30
|
|
|
29
31
|
@property()
|
|
30
|
-
|
|
32
|
+
accessor selectedTheme: TTheme = 'dark';
|
|
31
33
|
|
|
32
34
|
@property()
|
|
33
|
-
|
|
35
|
+
accessor warning: string = null;
|
|
34
36
|
|
|
35
37
|
@property()
|
|
36
|
-
|
|
38
|
+
accessor isFullscreen: boolean = false;
|
|
37
39
|
|
|
38
40
|
@state()
|
|
39
|
-
propertyContent: TemplateResult[] = [];
|
|
41
|
+
accessor propertyContent: TemplateResult[] = [];
|
|
40
42
|
|
|
41
43
|
@state()
|
|
42
|
-
editingProperties: Array<{
|
|
44
|
+
accessor editingProperties: Array<{
|
|
43
45
|
id: string;
|
|
44
46
|
name: string;
|
|
45
47
|
value: any;
|
|
@@ -48,6 +50,16 @@ export class WccProperties extends DeesElement {
|
|
|
48
50
|
editorError: string;
|
|
49
51
|
}> = [];
|
|
50
52
|
|
|
53
|
+
// Recording coordination state
|
|
54
|
+
@state()
|
|
55
|
+
accessor showRecordingPanel: boolean = false;
|
|
56
|
+
|
|
57
|
+
@state()
|
|
58
|
+
accessor isRecording: boolean = false;
|
|
59
|
+
|
|
60
|
+
@state()
|
|
61
|
+
accessor recordingDuration: number = 0;
|
|
62
|
+
|
|
51
63
|
public editorHeight: number = 300;
|
|
52
64
|
|
|
53
65
|
public render(): TemplateResult {
|
|
@@ -88,7 +100,7 @@ export class WccProperties extends DeesElement {
|
|
|
88
100
|
}
|
|
89
101
|
.grid {
|
|
90
102
|
display: grid;
|
|
91
|
-
grid-template-columns: 1fr 150px 300px 70px;
|
|
103
|
+
grid-template-columns: 1fr 150px 300px 70px 70px;
|
|
92
104
|
height: 100%;
|
|
93
105
|
}
|
|
94
106
|
.properties {
|
|
@@ -654,9 +666,26 @@ export class WccProperties extends DeesElement {
|
|
|
654
666
|
${this.isFullscreen ? 'fullscreen_exit' : 'fullscreen'}
|
|
655
667
|
</i>
|
|
656
668
|
</div>
|
|
669
|
+
<!-- Recording Button -->
|
|
670
|
+
<wcc-record-button
|
|
671
|
+
.state=${this.isRecording ? 'recording' : 'idle'}
|
|
672
|
+
.duration=${this.recordingDuration}
|
|
673
|
+
@record-click=${() => this.handleRecordButtonClick()}
|
|
674
|
+
></wcc-record-button>
|
|
657
675
|
</div>
|
|
658
676
|
${this.warning ? html`<div class="warning">${this.warning}</div>` : null}
|
|
659
677
|
</div>
|
|
678
|
+
|
|
679
|
+
<!-- Recording Panel (options + preview) -->
|
|
680
|
+
${this.showRecordingPanel ? html`
|
|
681
|
+
<wcc-recording-panel
|
|
682
|
+
.dashboardRef=${this.dashboardRef}
|
|
683
|
+
@recording-start=${() => { this.isRecording = true; }}
|
|
684
|
+
@recording-stop=${() => { this.isRecording = false; }}
|
|
685
|
+
@duration-update=${(e: CustomEvent) => { this.recordingDuration = e.detail.duration; }}
|
|
686
|
+
@close=${() => { this.showRecordingPanel = false; this.isRecording = false; this.recordingDuration = 0; }}
|
|
687
|
+
></wcc-recording-panel>
|
|
688
|
+
` : null}
|
|
660
689
|
`;
|
|
661
690
|
}
|
|
662
691
|
|
|
@@ -994,4 +1023,19 @@ export class WccProperties extends DeesElement {
|
|
|
994
1023
|
})
|
|
995
1024
|
);
|
|
996
1025
|
}
|
|
1026
|
+
|
|
1027
|
+
// ==================== Recording Methods ====================
|
|
1028
|
+
|
|
1029
|
+
private handleRecordButtonClick() {
|
|
1030
|
+
if (this.isRecording) {
|
|
1031
|
+
// Stop recording by calling the panel's stopRecording method
|
|
1032
|
+
const panel = this.shadowRoot?.querySelector('wcc-recording-panel') as any;
|
|
1033
|
+
if (panel && panel.stopRecording) {
|
|
1034
|
+
panel.stopRecording();
|
|
1035
|
+
}
|
|
1036
|
+
} else {
|
|
1037
|
+
// Toggle the recording panel
|
|
1038
|
+
this.showRecordingPanel = !this.showRecordingPanel;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
997
1041
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { DeesElement, customElement, html, css, property, type TemplateResult } from '@design.estate/dees-element';
|
|
2
|
+
|
|
3
|
+
@customElement('wcc-record-button')
|
|
4
|
+
export class WccRecordButton extends DeesElement {
|
|
5
|
+
@property({ type: String })
|
|
6
|
+
accessor state: 'idle' | 'recording' = 'idle';
|
|
7
|
+
|
|
8
|
+
@property({ type: Number })
|
|
9
|
+
accessor duration: number = 0;
|
|
10
|
+
|
|
11
|
+
public static styles = [
|
|
12
|
+
css`
|
|
13
|
+
:host {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
background: transparent;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
transition: all 0.15s ease;
|
|
20
|
+
color: #666;
|
|
21
|
+
user-select: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:host(:hover) {
|
|
25
|
+
background: rgba(239, 68, 68, 0.05);
|
|
26
|
+
color: #f87171;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:host(.recording) {
|
|
30
|
+
background: rgba(239, 68, 68, 0.15);
|
|
31
|
+
color: #f87171;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content {
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
gap: 0.25rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.rec-icon {
|
|
42
|
+
width: 12px;
|
|
43
|
+
height: 12px;
|
|
44
|
+
border-radius: 50%;
|
|
45
|
+
background: currentColor;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host(.recording) .rec-icon {
|
|
49
|
+
animation: pulse-recording 1s ease-in-out infinite;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@keyframes pulse-recording {
|
|
53
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
54
|
+
50% { opacity: 0.5; transform: scale(0.9); }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.recording-timer {
|
|
58
|
+
font-family: 'Consolas', 'Monaco', monospace;
|
|
59
|
+
font-size: 0.7rem;
|
|
60
|
+
}
|
|
61
|
+
`
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
private formatDuration(seconds: number): string {
|
|
65
|
+
const mins = Math.floor(seconds / 60);
|
|
66
|
+
const secs = seconds % 60;
|
|
67
|
+
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public render(): TemplateResult {
|
|
71
|
+
return html`
|
|
72
|
+
<div class="content">
|
|
73
|
+
<div class="rec-icon"></div>
|
|
74
|
+
${this.state === 'recording' ? html`
|
|
75
|
+
<span class="recording-timer">${this.formatDuration(this.duration)}</span>
|
|
76
|
+
` : null}
|
|
77
|
+
</div>
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async connectedCallback(): Promise<void> {
|
|
82
|
+
await super.connectedCallback();
|
|
83
|
+
this.addEventListener('click', this.handleClick);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async disconnectedCallback(): Promise<void> {
|
|
87
|
+
await super.disconnectedCallback();
|
|
88
|
+
this.removeEventListener('click', this.handleClick);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private handleClick = (): void => {
|
|
92
|
+
this.dispatchEvent(new CustomEvent('record-click', {
|
|
93
|
+
bubbles: true,
|
|
94
|
+
composed: true
|
|
95
|
+
}));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
updated(changedProperties: Map<string, unknown>): void {
|
|
99
|
+
super.updated(changedProperties);
|
|
100
|
+
if (changedProperties.has('state')) {
|
|
101
|
+
if (this.state === 'recording') {
|
|
102
|
+
this.classList.add('recording');
|
|
103
|
+
} else {
|
|
104
|
+
this.classList.remove('recording');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|