+ {bands.map((band, idx) => {
+ const angle = (idx / _barCount) * Math.PI * 2;
+
+ return (
+
+ );
+ })}
+
+ );
+}
diff --git a/packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.ts b/packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.ts
new file mode 100644
index 000000000..ea7188afa
--- /dev/null
+++ b/packages/shadcn/hooks/agents-ui/use-agent-audio-visualizer-grid.ts
@@ -0,0 +1,114 @@
+import { useEffect, useState } from 'react';
+import { type AgentState } from '@livekit/components-react';
+
+export interface Coordinate {
+ x: number;
+ y: number;
+}
+
+export function generateConnectingSequence(rows: number, columns: number, radius: number) {
+ const seq = [];
+ const centerY = Math.floor(rows / 2);
+
+ // Calculate the boundaries of the ring based on the ring distance
+ const topLeft = {
+ x: Math.max(0, centerY - radius),
+ y: Math.max(0, centerY - radius),
+ };
+ const bottomRight = {
+ x: columns - 1 - topLeft.x,
+ y: Math.min(rows - 1, centerY + radius),
+ };
+
+ // Top edge
+ for (let x = topLeft.x; x <= bottomRight.x; x++) {
+ seq.push({ x, y: topLeft.y });
+ }
+
+ // Right edge
+ for (let y = topLeft.y + 1; y <= bottomRight.y; y++) {
+ seq.push({ x: bottomRight.x, y });
+ }
+
+ // Bottom edge
+ for (let x = bottomRight.x - 1; x >= topLeft.x; x--) {
+ seq.push({ x, y: bottomRight.y });
+ }
+
+ // Left edge
+ for (let y = bottomRight.y - 1; y > topLeft.y; y--) {
+ seq.push({ x: topLeft.x, y });
+ }
+
+ return seq;
+}
+
+export function generateListeningSequence(rows: number, columns: number) {
+ const center = { x: Math.floor(columns / 2), y: Math.floor(rows / 2) };
+ const noIndex = { x: -1, y: -1 };
+
+ return [center, noIndex, noIndex, noIndex, noIndex, noIndex, noIndex, noIndex, noIndex];
+}
+
+export function generateThinkingSequence(rows: number, columns: number) {
+ const seq = [];
+ const y = Math.floor(rows / 2);
+ for (let x = 0; x < columns; x++) {
+ seq.push({ x, y });
+ }
+ for (let x = columns - 1; x >= 0; x--) {
+ seq.push({ x, y });
+ }
+
+ return seq;
+}
+
+export function useAgentAudioVisualizerGridAnimator(
+ state: AgentState,
+ rows: number,
+ columns: number,
+ interval: number,
+ radius?: number,
+): Coordinate {
+ const [index, setIndex] = useState(0);
+ const [sequence, setSequence] = useState