@editframe/elements 0.11.0-beta.1 → 0.11.0-beta.10
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/EF_FRAMEGEN.d.ts +8 -15
- package/dist/elements/EFMedia.d.ts +2 -2
- package/dist/elements/EFTemporal.browsertest.d.ts +10 -0
- package/dist/elements/EFTemporal.d.ts +10 -2
- package/dist/elements/EFTimegroup.browsertest.d.ts +4 -0
- package/dist/elements/EFTimegroup.d.ts +12 -1
- package/dist/elements/EFWaveform.d.ts +3 -3
- package/dist/elements/durationConverter.d.ts +4 -0
- package/dist/elements/src/EF_FRAMEGEN.js +24 -26
- package/dist/elements/src/elements/EFImage.js +3 -7
- package/dist/elements/src/elements/EFMedia.js +27 -9
- package/dist/elements/src/elements/EFTemporal.js +100 -3
- package/dist/elements/src/elements/EFTimegroup.js +26 -5
- package/dist/elements/src/elements/EFVideo.js +7 -7
- package/dist/elements/src/elements/EFWaveform.js +14 -8
- package/dist/elements/src/gui/ContextMixin.js +20 -6
- package/dist/elements/src/gui/EFFilmstrip.js +28 -8
- package/dist/elements/src/gui/EFTogglePlay.js +38 -6
- package/dist/elements/src/gui/TWMixin.css.js +1 -1
- package/dist/gui/ContextMixin.d.ts +1 -0
- package/dist/gui/EFFilmstrip.d.ts +4 -4
- package/dist/gui/EFTogglePlay.d.ts +4 -0
- package/dist/style.css +15 -4
- package/package.json +2 -2
- package/src/elements/EFImage.ts +4 -8
- package/src/elements/EFMedia.browsertest.ts +231 -2
- package/src/elements/EFMedia.ts +48 -9
- package/src/elements/EFTemporal.browsertest.ts +79 -0
- package/src/elements/EFTemporal.ts +133 -6
- package/src/elements/EFTimegroup.browsertest.ts +38 -1
- package/src/elements/EFTimegroup.ts +27 -6
- package/src/elements/EFVideo.ts +7 -8
- package/src/elements/EFWaveform.ts +14 -9
- package/src/elements/durationConverter.ts +4 -0
- package/src/gui/ContextMixin.browsertest.ts +28 -2
- package/src/gui/ContextMixin.ts +23 -7
- package/src/gui/EFFilmstrip.ts +37 -17
- package/src/gui/EFTogglePlay.ts +38 -7
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { LitElement, html, css, type PropertyValueMap } from "lit";
|
|
2
1
|
import { provide } from "@lit/context";
|
|
3
2
|
import { Task } from "@lit/task";
|
|
4
|
-
import { customElement, property } from "lit/decorators.js";
|
|
5
3
|
import debug from "debug";
|
|
4
|
+
import { LitElement, type PropertyValueMap, css, html } from "lit";
|
|
5
|
+
import { customElement, property } from "lit/decorators.js";
|
|
6
6
|
|
|
7
|
+
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
|
|
8
|
+
import { isContextMixin } from "../gui/ContextMixin.ts";
|
|
9
|
+
import { deepGetMediaElements } from "./EFMedia.ts";
|
|
7
10
|
import {
|
|
8
11
|
EFTemporal,
|
|
9
12
|
isEFTemporal,
|
|
@@ -11,8 +14,6 @@ import {
|
|
|
11
14
|
timegroupContext,
|
|
12
15
|
} from "./EFTemporal.ts";
|
|
13
16
|
import { TimegroupController } from "./TimegroupController.ts";
|
|
14
|
-
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
|
|
15
|
-
import { deepGetMediaElements } from "./EFMedia.ts";
|
|
16
17
|
import { durationConverter } from "./durationConverter.ts";
|
|
17
18
|
|
|
18
19
|
const log = debug("ef:elements:EFTimegroup");
|
|
@@ -243,12 +244,32 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
243
244
|
}
|
|
244
245
|
}
|
|
245
246
|
|
|
247
|
+
get contextProvider() {
|
|
248
|
+
let parent = this.parentNode;
|
|
249
|
+
while (parent) {
|
|
250
|
+
if (isContextMixin(parent)) {
|
|
251
|
+
return parent;
|
|
252
|
+
}
|
|
253
|
+
parent = parent.parentNode;
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Returns true if the timegroup should be wrapped with a workbench.
|
|
260
|
+
*
|
|
261
|
+
* A timegroup should be wrapped with a workbench if it is the root-most timegroup
|
|
262
|
+
* and EF_INTERACTIVE is true.
|
|
263
|
+
*
|
|
264
|
+
* If the timegroup is already wrappedin a context provider like ef-preview,
|
|
265
|
+
* it should NOT be wrapped in a workbench.
|
|
266
|
+
*
|
|
267
|
+
*/
|
|
246
268
|
shouldWrapWithWorkbench() {
|
|
247
269
|
return (
|
|
248
270
|
EF_INTERACTIVE &&
|
|
249
271
|
this.closest("ef-timegroup") === this &&
|
|
250
|
-
this.
|
|
251
|
-
this.closest("ef-preview") === null
|
|
272
|
+
this.contextProvider === null
|
|
252
273
|
);
|
|
253
274
|
}
|
|
254
275
|
|
package/src/elements/EFVideo.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { html, css } from "lit";
|
|
2
1
|
import { Task } from "@lit/task";
|
|
3
|
-
import {
|
|
2
|
+
import { css, html } from "lit";
|
|
4
3
|
import { customElement } from "lit/decorators.js";
|
|
4
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
5
5
|
|
|
6
|
-
import { EFMedia } from "./EFMedia.ts";
|
|
7
6
|
import { TWMixin } from "../gui/TWMixin.ts";
|
|
7
|
+
import { EFMedia } from "./EFMedia.ts";
|
|
8
8
|
|
|
9
9
|
@customElement("ef-video")
|
|
10
10
|
export class EFVideo extends TWMixin(EFMedia) {
|
|
@@ -13,15 +13,14 @@ export class EFVideo extends TWMixin(EFMedia) {
|
|
|
13
13
|
:host {
|
|
14
14
|
display: block;
|
|
15
15
|
}
|
|
16
|
+
canvas {
|
|
17
|
+
all: inherit;
|
|
18
|
+
}
|
|
16
19
|
`,
|
|
17
20
|
];
|
|
18
21
|
canvasRef = createRef<HTMLCanvasElement>();
|
|
19
|
-
|
|
20
22
|
render() {
|
|
21
|
-
return html` <canvas
|
|
22
|
-
class="h-full w-full object-fill"
|
|
23
|
-
${ref(this.canvasRef)}
|
|
24
|
-
></canvas>`;
|
|
23
|
+
return html` <canvas ${ref(this.canvasRef)}></canvas>`;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
get canvasElement() {
|
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
import { EFAudio } from "./EFAudio.ts";
|
|
2
2
|
|
|
3
|
-
import { LitElement, html } from "lit";
|
|
4
|
-
import { customElement, property } from "lit/decorators.js";
|
|
5
|
-
import { EFVideo } from "./EFVideo.ts";
|
|
6
|
-
import { EFTemporal } from "./EFTemporal.ts";
|
|
7
|
-
import { CrossUpdateController } from "./CrossUpdateController.ts";
|
|
8
|
-
import { TWMixin } from "../gui/TWMixin.ts";
|
|
9
3
|
import { Task } from "@lit/task";
|
|
10
4
|
import * as d3 from "d3";
|
|
5
|
+
import { LitElement, css, html } from "lit";
|
|
6
|
+
import { customElement, property } from "lit/decorators.js";
|
|
11
7
|
import { type Ref, createRef, ref } from "lit/directives/ref.js";
|
|
12
8
|
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
|
|
9
|
+
import { TWMixin } from "../gui/TWMixin.ts";
|
|
10
|
+
import { CrossUpdateController } from "./CrossUpdateController.ts";
|
|
11
|
+
import { EFTemporal } from "./EFTemporal.ts";
|
|
12
|
+
import { EFVideo } from "./EFVideo.ts";
|
|
13
13
|
|
|
14
14
|
@customElement("ef-waveform")
|
|
15
15
|
export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
|
|
16
|
-
static styles = [
|
|
16
|
+
static styles = [
|
|
17
|
+
css`
|
|
18
|
+
svg {
|
|
19
|
+
all: inherit;
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
];
|
|
17
23
|
svgRef: Ref<SVGElement> = createRef();
|
|
18
24
|
createRenderRoot() {
|
|
19
25
|
return this;
|
|
20
26
|
}
|
|
21
27
|
render() {
|
|
22
|
-
return html` <svg ${ref(this.svgRef)}
|
|
28
|
+
return html` <svg ${ref(this.svgRef)} store></svg> `;
|
|
23
29
|
}
|
|
24
|
-
|
|
25
30
|
@property({
|
|
26
31
|
type: String,
|
|
27
32
|
attribute: "mode",
|
|
@@ -24,3 +24,7 @@ export const trimDurationConverter = positiveDurationConverter(
|
|
|
24
24
|
export const imageDurationConverter = positiveDurationConverter(
|
|
25
25
|
"Image duration must be a positive value in milliseconds or seconds (1s, 1000ms)",
|
|
26
26
|
);
|
|
27
|
+
|
|
28
|
+
export const sourceDurationConverter = positiveDurationConverter(
|
|
29
|
+
"Sourcein & sourceout must be a positive value in milliseconds or seconds (1s, 1000ms)",
|
|
30
|
+
);
|
|
@@ -2,10 +2,13 @@ import { LitElement } from "lit";
|
|
|
2
2
|
import { customElement } from "lit/decorators/custom-element.js";
|
|
3
3
|
import { describe, expect, test, vi } from "vitest";
|
|
4
4
|
|
|
5
|
-
import { ContextMixin } from "./ContextMixin.ts";
|
|
6
5
|
import { consume } from "@lit/context";
|
|
6
|
+
import { ContextMixin } from "./ContextMixin.ts";
|
|
7
7
|
import { apiHostContext } from "./apiHostContext.ts";
|
|
8
8
|
|
|
9
|
+
// Required to test timeupdate event, we need a duration, and timegroups are a quick way to do that
|
|
10
|
+
import "../elements/EFTimegroup.ts";
|
|
11
|
+
|
|
9
12
|
@customElement("test-context")
|
|
10
13
|
class TestContext extends ContextMixin(LitElement) {}
|
|
11
14
|
|
|
@@ -49,7 +52,6 @@ describe("ContextMixin", () => {
|
|
|
49
52
|
expect(element.apiHost).toBe("test2");
|
|
50
53
|
});
|
|
51
54
|
});
|
|
52
|
-
|
|
53
55
|
describe("Playback", () => {
|
|
54
56
|
test("should start playback", () => {
|
|
55
57
|
const element = document.createElement("test-context");
|
|
@@ -78,4 +80,28 @@ describe("ContextMixin", () => {
|
|
|
78
80
|
expect(playbackSpy).toHaveBeenCalled();
|
|
79
81
|
});
|
|
80
82
|
});
|
|
83
|
+
|
|
84
|
+
test("Time update event when the currentTimeMs changed", async () => {
|
|
85
|
+
const timegroup = document.createElement("ef-timegroup");
|
|
86
|
+
timegroup.mode = "fixed";
|
|
87
|
+
timegroup.duration = "10s";
|
|
88
|
+
|
|
89
|
+
const preview = document.createElement("test-context");
|
|
90
|
+
preview.append(timegroup);
|
|
91
|
+
document.body.append(preview);
|
|
92
|
+
|
|
93
|
+
type CurrentTimeEvent = CustomEvent<{ currentTimeMs: number }>;
|
|
94
|
+
|
|
95
|
+
// Expect the timeupdate event to be dispatched
|
|
96
|
+
const timeupdatePromise = new Promise<CurrentTimeEvent>((resolve) => {
|
|
97
|
+
preview.addEventListener(
|
|
98
|
+
"timeupdate",
|
|
99
|
+
(event: Event) => resolve(event as CurrentTimeEvent),
|
|
100
|
+
{ once: true },
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
preview.currentTimeMs = 1000;
|
|
104
|
+
const event = await timeupdatePromise;
|
|
105
|
+
expect(event.detail.currentTimeMs).toBe(1000);
|
|
106
|
+
});
|
|
81
107
|
});
|
package/src/gui/ContextMixin.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { LitElement } from "lit";
|
|
2
1
|
import { provide } from "@lit/context";
|
|
2
|
+
import type { LitElement } from "lit";
|
|
3
3
|
import { property, state } from "lit/decorators.js";
|
|
4
4
|
|
|
5
|
-
import { focusContext, type FocusContext } from "./focusContext.ts";
|
|
6
|
-
import { focusedElementContext } from "./focusedElementContext.ts";
|
|
7
|
-
import { fetchContext } from "./fetchContext.ts";
|
|
8
5
|
import { createRef } from "lit/directives/ref.js";
|
|
9
|
-
import { loopContext, playingContext } from "./playingContext.ts";
|
|
10
6
|
import type { EFTimegroup } from "../elements/EFTimegroup.ts";
|
|
11
|
-
import { efContext } from "./efContext.ts";
|
|
12
7
|
import { apiHostContext } from "./apiHostContext.ts";
|
|
8
|
+
import { efContext } from "./efContext.ts";
|
|
9
|
+
import { fetchContext } from "./fetchContext.ts";
|
|
10
|
+
import { type FocusContext, focusContext } from "./focusContext.ts";
|
|
11
|
+
import { focusedElementContext } from "./focusedElementContext.ts";
|
|
12
|
+
import { loopContext, playingContext } from "./playingContext.ts";
|
|
13
13
|
|
|
14
14
|
export declare class ContextMixinInterface {
|
|
15
15
|
signingURL?: string;
|
|
@@ -26,9 +26,19 @@ export declare class ContextMixinInterface {
|
|
|
26
26
|
pause(): void;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
const contextMixinSymbol = Symbol("contextMixin");
|
|
30
|
+
|
|
31
|
+
export function isContextMixin(value: any): value is ContextMixinInterface {
|
|
32
|
+
return (
|
|
33
|
+
typeof value === "object" && value !== null && contextMixinSymbol in value
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
type Constructor<T = {}> = new (...args: any[]) => T;
|
|
30
38
|
export function ContextMixin<T extends Constructor<LitElement>>(superClass: T) {
|
|
31
39
|
class ContextElement extends superClass {
|
|
40
|
+
[contextMixinSymbol] = true;
|
|
41
|
+
|
|
32
42
|
@provide({ context: focusContext })
|
|
33
43
|
focusContext = this as FocusContext;
|
|
34
44
|
|
|
@@ -164,10 +174,16 @@ export function ContextMixin<T extends Constructor<LitElement>>(superClass: T) {
|
|
|
164
174
|
this.stopPlayback();
|
|
165
175
|
}
|
|
166
176
|
}
|
|
167
|
-
|
|
168
177
|
if (changedProperties.has("currentTimeMs") && this.targetTimegroup) {
|
|
169
178
|
if (this.targetTimegroup.currentTimeMs !== this.currentTimeMs) {
|
|
170
179
|
this.targetTimegroup.currentTimeMs = this.currentTimeMs;
|
|
180
|
+
if (this.isConnected) {
|
|
181
|
+
this.dispatchEvent(
|
|
182
|
+
new CustomEvent("timeupdate", {
|
|
183
|
+
detail: { currentTimeMs: this.currentTimeMs },
|
|
184
|
+
}),
|
|
185
|
+
);
|
|
186
|
+
}
|
|
171
187
|
}
|
|
172
188
|
}
|
|
173
189
|
super.update(changedProperties);
|
package/src/gui/EFFilmstrip.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
+
import { consume } from "@lit/context";
|
|
1
2
|
import {
|
|
2
3
|
LitElement,
|
|
3
|
-
|
|
4
|
+
type PropertyValueMap,
|
|
5
|
+
type ReactiveController,
|
|
6
|
+
type TemplateResult,
|
|
4
7
|
css,
|
|
8
|
+
html,
|
|
5
9
|
nothing,
|
|
6
|
-
type TemplateResult,
|
|
7
|
-
type ReactiveController,
|
|
8
|
-
type PropertyValueMap,
|
|
9
10
|
} from "lit";
|
|
10
11
|
import {
|
|
11
12
|
customElement,
|
|
12
|
-
property,
|
|
13
13
|
eventOptions,
|
|
14
|
+
property,
|
|
14
15
|
state,
|
|
15
16
|
} from "lit/decorators.js";
|
|
16
|
-
import {
|
|
17
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
17
18
|
import { styleMap } from "lit/directives/style-map.js";
|
|
18
|
-
import { ref, createRef } from "lit/directives/ref.js";
|
|
19
19
|
|
|
20
|
-
import { EFImage } from "../elements/EFImage.ts";
|
|
21
20
|
import { EFAudio } from "../elements/EFAudio.ts";
|
|
22
|
-
import { EFVideo } from "../elements/EFVideo.ts";
|
|
23
21
|
import { EFCaptions, EFCaptionsActiveWord } from "../elements/EFCaptions.ts";
|
|
24
|
-
import {
|
|
25
|
-
import { EFTimegroup } from "../elements/EFTimegroup.ts";
|
|
22
|
+
import { EFImage } from "../elements/EFImage.ts";
|
|
26
23
|
import type { TemporalMixinInterface } from "../elements/EFTemporal.ts";
|
|
24
|
+
import { EFTimegroup } from "../elements/EFTimegroup.ts";
|
|
25
|
+
import { EFVideo } from "../elements/EFVideo.ts";
|
|
26
|
+
import { EFWaveform } from "../elements/EFWaveform.ts";
|
|
27
27
|
import { TimegroupController } from "../elements/TimegroupController.ts";
|
|
28
|
-
import { TWMixin } from "./TWMixin.ts";
|
|
29
28
|
import { msToTimeCode } from "../msToTimeCode.ts";
|
|
30
|
-
import { focusedElementContext } from "./focusedElementContext.ts";
|
|
31
|
-
import { type FocusContext, focusContext } from "./focusContext.ts";
|
|
32
|
-
import { playingContext, loopContext } from "./playingContext.ts";
|
|
33
|
-
import type { EFWorkbench } from "./EFWorkbench.ts";
|
|
34
29
|
import type { EFPreview } from "./EFPreview.ts";
|
|
30
|
+
import type { EFWorkbench } from "./EFWorkbench.ts";
|
|
31
|
+
import { TWMixin } from "./TWMixin.ts";
|
|
32
|
+
import { type FocusContext, focusContext } from "./focusContext.ts";
|
|
33
|
+
import { focusedElementContext } from "./focusedElementContext.ts";
|
|
34
|
+
import { loopContext, playingContext } from "./playingContext.ts";
|
|
35
35
|
|
|
36
36
|
class ElementFilmstripController implements ReactiveController {
|
|
37
37
|
constructor(
|
|
@@ -87,6 +87,13 @@ class FilmstripItem extends TWMixin(LitElement) {
|
|
|
87
87
|
pixelsPerMs = 0.04;
|
|
88
88
|
|
|
89
89
|
get gutterStyles() {
|
|
90
|
+
if (this.element.sourceInMs || this.element.sourceOutMs) {
|
|
91
|
+
return {
|
|
92
|
+
position: "relative",
|
|
93
|
+
left: `${this.pixelsPerMs * (this.element.startTimeWithinParentMs - this.element.trimStartMs - this.element.sourceInMs)}px`,
|
|
94
|
+
width: `${this.pixelsPerMs * (this.element.durationMs + this.element.trimStartMs + this.element.trimEndMs + this.element.sourceOutMs + this.element.sourceInMs)}px`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
90
97
|
return {
|
|
91
98
|
position: "relative",
|
|
92
99
|
left: `${this.pixelsPerMs * (this.element.startTimeWithinParentMs - this.element.trimStartMs)}px`,
|
|
@@ -95,6 +102,12 @@ class FilmstripItem extends TWMixin(LitElement) {
|
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
get trimPortionStyles() {
|
|
105
|
+
if (this.element.sourceInMs || this.element.sourceOutMs) {
|
|
106
|
+
return {
|
|
107
|
+
width: `${this.pixelsPerMs * this.element.durationMs}px`,
|
|
108
|
+
left: `${this.pixelsPerMs * (this.element.trimStartMs + this.element.sourceInMs)}px`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
98
111
|
return {
|
|
99
112
|
width: `${this.pixelsPerMs * this.element.durationMs}px`,
|
|
100
113
|
left: `${this.pixelsPerMs * this.element.trimStartMs}px`,
|
|
@@ -694,7 +707,14 @@ export class EFFilmstrip extends TWMixin(LitElement) {
|
|
|
694
707
|
/>
|
|
695
708
|
<code>${msToTimeCode(this.currentTimeMs, true)} </code> /
|
|
696
709
|
<code>${msToTimeCode(target?.durationMs ?? 0, true)}</code>
|
|
697
|
-
<ef-toggle-play
|
|
710
|
+
<ef-toggle-play class="inline-block mx-2">
|
|
711
|
+
<div slot="pause">
|
|
712
|
+
<button class="bg-white">▶</button>
|
|
713
|
+
</div>
|
|
714
|
+
<div slot="play">
|
|
715
|
+
<button>⏸️</button>
|
|
716
|
+
</div>
|
|
717
|
+
</ef-toggle-play>
|
|
698
718
|
<ef-toggle-loop><button>${this.loop ? "🔁" : html`<span class="opacity-50">🔁</span>`}</button></ef-toggle-loop>
|
|
699
719
|
</div>
|
|
700
720
|
<div
|
package/src/gui/EFTogglePlay.ts
CHANGED
|
@@ -1,33 +1,64 @@
|
|
|
1
|
-
import { css, html, LitElement } from "lit";
|
|
2
|
-
import { customElement } from "lit/decorators.js";
|
|
3
1
|
import { consume } from "@lit/context";
|
|
2
|
+
import { LitElement, css, html } from "lit";
|
|
3
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
4
4
|
|
|
5
|
-
import { efContext } from "./efContext.ts";
|
|
6
5
|
import type { ContextMixinInterface } from "./ContextMixin.ts";
|
|
6
|
+
import { efContext } from "./efContext.ts";
|
|
7
7
|
|
|
8
8
|
@customElement("ef-toggle-play")
|
|
9
9
|
export class EFTogglePlay extends LitElement {
|
|
10
10
|
static styles = [
|
|
11
11
|
css`
|
|
12
12
|
:host {}
|
|
13
|
+
div {
|
|
14
|
+
all: inherit;
|
|
15
|
+
}
|
|
13
16
|
`,
|
|
14
17
|
];
|
|
15
18
|
|
|
16
|
-
@consume({ context: efContext })
|
|
19
|
+
@consume({ context: efContext, subscribe: true })
|
|
17
20
|
context?: ContextMixinInterface | null;
|
|
18
21
|
|
|
22
|
+
@property({ type: String })
|
|
23
|
+
play = '<button class="text-2xl cursor-pointer">▶️</button>';
|
|
24
|
+
|
|
25
|
+
@property({ type: String })
|
|
26
|
+
pause = '<button class="text-2xl cursor-pointer">⏸️</button>';
|
|
27
|
+
|
|
28
|
+
@state()
|
|
29
|
+
playing = false;
|
|
30
|
+
|
|
19
31
|
render() {
|
|
20
32
|
return html`
|
|
21
|
-
<
|
|
33
|
+
<div
|
|
34
|
+
@click=${() => {
|
|
22
35
|
if (this.context) {
|
|
23
36
|
if (this.context.playing) {
|
|
24
37
|
this.context.pause();
|
|
38
|
+
this.playing = false;
|
|
25
39
|
} else {
|
|
26
40
|
this.context.play();
|
|
41
|
+
this.playing = true;
|
|
27
42
|
}
|
|
28
43
|
}
|
|
29
|
-
}}
|
|
30
|
-
|
|
44
|
+
}}>
|
|
45
|
+
${
|
|
46
|
+
this.playing
|
|
47
|
+
? html`<slot name="play"></slot>`
|
|
48
|
+
: html`<slot name="pause"></slot>`
|
|
49
|
+
}
|
|
50
|
+
</div>`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
togglePlay() {
|
|
54
|
+
this.requestUpdate();
|
|
55
|
+
if (this.context) {
|
|
56
|
+
if (this.context.playing) {
|
|
57
|
+
this.context.pause();
|
|
58
|
+
} else {
|
|
59
|
+
this.context.play();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
31
62
|
}
|
|
32
63
|
}
|
|
33
64
|
|