import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators.js";
@customElement("play-soundbite")
export class PlaySoundbite extends LitElement {
@property({ attribute: "audio-src" })
audioSrc!: string;
@property({ type: Number, attribute: "start-time" })
startTime!: number;
@property({ type: Number })
duration!: number;
@property({ attribute: "play-label" })
playLabel!: string;
@property({ attribute: "playing-label" })
playingLabel!: string;
@state()
_audio: HTMLAudioElement | null = null;
@state()
_isPlaying = false;
@state()
_isLoading = false;
_audioEvents = [
{
name: "play",
onEvent: () => {
this._isPlaying = true;
},
},
{
name: "pause",
onEvent: () => {
this._isPlaying = false;
},
},
{
name: "timeupdate",
onEvent: () => {
if (this._audio) {
if (this._audio.currentTime < this.startTime) {
this._isLoading = true;
this._audio.currentTime = this.startTime;
} else if (this._audio.currentTime > this.startTime + this.duration) {
this.stopSoundbite();
} else {
this._isLoading = false;
}
}
},
},
];
playSoundbite() {
if (this._audio === null) {
this._audio = new Audio(this.audioSrc);
for (const event of this._audioEvents) {
this._audio.addEventListener(event.name, event.onEvent);
}
}
this._audio.currentTime = this.startTime;
this._audio.play();
}
stopSoundbite() {
if (this._audio !== null) {
this._audio.pause();
this._audio.currentTime = this.startTime;
}
}
disconnectedCallback(): void {
if (this._audio) {
for (const event of this._audioEvents) {
this._audio.removeEventListener(event.name, event.onEvent);
}
}
}
static styles = css`
button {
background-color: hsl(var(--color-accent-base));
cursor: pointer;
display: inline-flex;
align-items: center;
padding: 0.5rem;
font-size: 0.875rem;
border: 2px solid transparent;
border-radius: 9999px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
button:hover {
background-color: hsl(var(--color-accent-hover));
}
button:focus {
outline: none;
box-shadow: 0 0 0 2px hsl(var(--color-background-base)),
0 0 0 4px hsl(var(--color-accent-base));
}
button.playing {
background-color: hsl(var(--color-background-base));
border: 2px solid hsl(var(--color-accent-base));
}
button.playing:hover {
background-color: hsl(var(--color-background-elevated));
}
button.playing svg {
color: hsl(var(--color-accent-base));
}
svg {
color: hsl(var(--color-accent-contrast));
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 3s linear infinite;
}
`;
render(): TemplateResult<1> {
return html``;
}
}