Spaces:
Running
Running
| /** | |
| * Copyright 2024 Google LLC | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| import "./audio-pulse.scss"; | |
| import React from "react"; | |
| import { useEffect, useRef } from "react"; | |
| import c from "classnames"; | |
| const lineCount = 3; | |
| export type AudioPulseProps = { | |
| active: boolean; | |
| volume: number; | |
| hover?: boolean; | |
| }; | |
| export default function AudioPulse({ active, volume, hover }: AudioPulseProps) { | |
| const lines = useRef<HTMLDivElement[]>([]); | |
| useEffect(() => { | |
| let timeout: number | null = null; | |
| const update = () => { | |
| lines.current.forEach( | |
| (line, i) => | |
| (line.style.height = `${Math.min( | |
| 24, | |
| 4 + volume * (i === 1 ? 400 : 60), | |
| )}px`), | |
| ); | |
| timeout = window.setTimeout(update, 100); | |
| }; | |
| update(); | |
| return () => clearTimeout((timeout as number)!); | |
| }, [volume]); | |
| return ( | |
| <div className={c("audioPulse", { active, hover })}> | |
| {Array(lineCount) | |
| .fill(null) | |
| .map((_, i) => ( | |
| <div | |
| key={i} | |
| ref={(el) => (lines.current[i] = el!)} | |
| style={{ animationDelay: `${i * 133}ms` }} | |
| /> | |
| ))} | |
| </div> | |
| ); | |
| } | |