{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "matrix-demo", "registryDependencies": [ "https://ui.elevenlabs.io/r/matrix.json" ], "files": [ { "path": "examples/matrix-demo.tsx", "content": "\"use client\"\n\nimport { useEffect, useState } from \"react\"\n\nimport {\n Matrix,\n pulse,\n snake,\n wave,\n type Frame,\n} from \"@/components/ui/matrix\"\n\nconst Example = () => {\n const [mode, setMode] = useState<\n \"individual\" | \"focus\" | \"expand\" | \"unified\" | \"collapse\" | \"burst\"\n >(\"individual\")\n const [unifiedFrame, setUnifiedFrame] = useState(0)\n const [expandProgress, setExpandProgress] = useState(0)\n const [collapseProgress, setCollapseProgress] = useState(0)\n\n useEffect(() => {\n let timeout: NodeJS.Timeout\n\n if (mode === \"individual\") {\n timeout = setTimeout(() => setMode(\"focus\"), 4000)\n } else if (mode === \"focus\") {\n timeout = setTimeout(() => setMode(\"expand\"), 2000)\n } else if (mode === \"expand\") {\n timeout = setTimeout(() => setMode(\"unified\"), 2500)\n } else if (mode === \"unified\") {\n timeout = setTimeout(() => setMode(\"collapse\"), 4000)\n } else if (mode === \"collapse\") {\n timeout = setTimeout(() => setMode(\"burst\"), 2500)\n } else if (mode === \"burst\") {\n timeout = setTimeout(() => setMode(\"individual\"), 800)\n }\n\n return () => clearTimeout(timeout)\n }, [mode])\n\n useEffect(() => {\n if (mode !== \"unified\") return\n\n let frame = 0\n const animate = setInterval(() => {\n frame += 1\n setUnifiedFrame(frame)\n }, 50)\n\n return () => clearInterval(animate)\n }, [mode])\n\n useEffect(() => {\n if (mode !== \"expand\") {\n setExpandProgress(0)\n return\n }\n\n let start = 0\n const duration = 2500\n let animationFrame: number\n\n const animate = (timestamp: number) => {\n if (start === 0) start = timestamp\n const elapsed = timestamp - start\n const progress = Math.min(elapsed / duration, 1)\n\n setExpandProgress(progress)\n\n if (progress < 1) {\n animationFrame = requestAnimationFrame(animate)\n }\n }\n\n animationFrame = requestAnimationFrame(animate)\n return () => cancelAnimationFrame(animationFrame)\n }, [mode])\n\n useEffect(() => {\n if (mode !== \"collapse\") {\n setCollapseProgress(0)\n return\n }\n\n let start = 0\n const duration = 2500\n let animationFrame: number\n\n const animate = (timestamp: number) => {\n if (start === 0) start = timestamp\n const elapsed = timestamp - start\n const progress = Math.min(elapsed / duration, 1)\n\n setCollapseProgress(progress)\n\n if (progress < 1) {\n animationFrame = requestAnimationFrame(animate)\n }\n }\n\n animationFrame = requestAnimationFrame(animate)\n return () => cancelAnimationFrame(animationFrame)\n }, [mode])\n\n const configurations = [\n { animation: pulse, fps: 16 },\n { animation: wave, fps: 20 },\n { animation: spinner, fps: 10 },\n { animation: snake, fps: 15 },\n { animation: elevenLogo, fps: 12 },\n { animation: sandTimer, fps: 12 },\n { animation: corners, fps: 10 },\n { animation: sweep, fps: 14 },\n { animation: expand, fps: 12 },\n ]\n\n const unifiedPatterns =\n mode === \"unified\" ? createUnifiedPattern(unifiedFrame) : []\n\n const expandedPatterns =\n mode === \"expand\" ? createExpandedLogo(expandProgress) : []\n const collapsePatterns =\n mode === \"collapse\" ? createCollapseEffect(collapseProgress) : []\n\n const getPatternForMatrix = (index: number) => {\n if (mode === \"individual\") {\n return undefined\n } else if (mode === \"focus\") {\n if (index === 4) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n for (let r = 1; r <= 5; r++) {\n frame[r][2] = 1\n frame[r][4] = 1\n }\n return frame\n }\n return Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n } else if (mode === \"expand\") {\n return expandedPatterns[index]\n } else if (mode === \"unified\") {\n return unifiedPatterns[index]\n } else if (mode === \"collapse\") {\n return collapsePatterns[index]\n } else if (mode === \"burst\") {\n return undefined\n }\n }\n\n const getFramesForMatrix = (index: number) => {\n if (mode === \"individual\") {\n return configurations[index].animation\n } else if (mode === \"burst\") {\n return burst\n }\n return undefined\n }\n\n const getFps = (index: number) => {\n if (mode === \"burst\") return 30\n return configurations[index].fps\n }\n\n return (\n
\n \n {configurations.map((config, index) => (\n \n \n
\n ))}\n \n \n )\n}\nfunction createUnifiedPattern(frameIndex: number): Frame[] {\n const totalRows = 21\n const totalCols = 21\n const pattern: number[][] = []\n\n for (let row = 0; row < totalRows; row++) {\n pattern[row] = []\n for (let col = 0; col < totalCols; col++) {\n const centerX = totalCols / 2\n const centerY = totalRows / 2\n const distance = Math.sqrt(\n Math.pow(col - centerX, 2) + Math.pow(row - centerY, 2)\n )\n const wave = Math.sin(distance * 0.5 - frameIndex * 0.2)\n const value = (wave + 1) / 2\n pattern[row][col] = value\n }\n }\n\n const matrices: Frame[] = []\n for (let matrixRow = 0; matrixRow < 3; matrixRow++) {\n for (let matrixCol = 0; matrixCol < 3; matrixCol++) {\n const matrixFrame: Frame = []\n for (let row = 0; row < 7; row++) {\n matrixFrame[row] = []\n for (let col = 0; col < 7; col++) {\n const globalRow = matrixRow * 7 + row\n const globalCol = matrixCol * 7 + col\n matrixFrame[row][col] = pattern[globalRow][globalCol]\n }\n }\n matrices.push(matrixFrame)\n }\n }\n\n return matrices\n}\n\nconst elevenLogo: Frame[] = (() => {\n const frames: Frame[] = []\n const totalFrames = 30\n\n for (let f = 0; f < totalFrames; f++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n\n const phase = (f / totalFrames) * Math.PI * 2\n const intensity = ((Math.sin(phase) + 1) / 2) * 0.3 + 0.7\n\n for (let r = 1; r <= 5; r++) {\n frame[r][2] = intensity\n frame[r][4] = intensity\n }\n\n frames.push(frame)\n }\n return frames\n})()\n\nconst sandTimer: Frame[] = (() => {\n const frames: Frame[] = []\n const totalFrames = 60\n\n for (let f = 0; f < totalFrames; f++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n\n frame[0][2] = 1\n frame[0][3] = 1\n frame[0][4] = 1\n frame[1][2] = 1\n frame[1][4] = 1\n frame[5][2] = 1\n frame[5][4] = 1\n frame[6][2] = 1\n frame[6][3] = 1\n frame[6][4] = 1\n\n const progress = f / totalFrames\n\n const topSand = Math.floor((1 - progress) * 8)\n for (let i = 0; i < topSand; i++) {\n if (i < 3) frame[1][3] = 1\n if (i >= 3) frame[2][3] = 1\n }\n\n const bottomSand = Math.floor(progress * 8)\n for (let i = 0; i < bottomSand; i++) {\n if (i < 3) frame[5][3] = 1\n if (i >= 3 && i < 6) frame[4][3] = 1\n if (i >= 6) frame[3][3] = 0.5\n }\n\n frames.push(frame)\n }\n return frames\n})()\n\nconst spinner: Frame[] = (() => {\n const frames: Frame[] = []\n const segments = 8\n\n for (let f = 0; f < segments; f++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n\n const positions = [\n [1, 3],\n [1, 4],\n [2, 5],\n [3, 5],\n [4, 5],\n [5, 4],\n [5, 3],\n [5, 2],\n [4, 1],\n [3, 1],\n [2, 1],\n [1, 2],\n ]\n\n for (let i = 0; i < 3; i++) {\n const idx = (f + i) % positions.length\n const [r, c] = positions[idx]\n frame[r][c] = 1 - i * 0.3\n }\n\n frames.push(frame)\n }\n return frames\n})()\n\nconst corners: Frame[] = (() => {\n const frames: Frame[] = []\n for (let i = 0; i < 16; i++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n const progress = i / 16\n\n for (let r = 0; r < 7; r++) {\n for (let c = 0; c < 7; c++) {\n const distFromCorner = Math.min(\n Math.sqrt(r * r + c * c),\n Math.sqrt(r * r + (6 - c) * (6 - c)),\n Math.sqrt((6 - r) * (6 - r) + c * c),\n Math.sqrt((6 - r) * (6 - r) + (6 - c) * (6 - c))\n )\n const threshold = progress * 8\n if (distFromCorner <= threshold) {\n frame[r][c] = Math.max(0, 1 - Math.abs(distFromCorner - threshold))\n }\n }\n }\n frames.push(frame)\n }\n return frames\n})()\n\nconst sweep: Frame[] = (() => {\n const frames: Frame[] = []\n for (let i = 0; i < 14; i++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n for (let r = 0; r < 7; r++) {\n for (let c = 0; c < 7; c++) {\n if (r + c === i) {\n frame[r][c] = 1\n } else if (r + c === i - 1) {\n frame[r][c] = 0.5\n } else if (r + c === i + 1) {\n frame[r][c] = 0.5\n }\n }\n }\n frames.push(frame)\n }\n return frames\n})()\n\nconst expand: Frame[] = (() => {\n const frames: Frame[] = []\n for (let i = 0; i <= 6; i++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n for (let r = 3 - i; r <= 3 + i; r++) {\n for (let c = 3 - i; c <= 3 + i; c++) {\n if (r >= 0 && r < 7 && c >= 0 && c < 7) {\n if (r === 3 - i || r === 3 + i || c === 3 - i || c === 3 + i) {\n frame[r][c] = 1\n }\n }\n }\n }\n frames.push(frame)\n }\n for (let i = 5; i >= 0; i--) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n for (let r = 3 - i; r <= 3 + i; r++) {\n for (let c = 3 - i; c <= 3 + i; c++) {\n if (r >= 0 && r < 7 && c >= 0 && c < 7) {\n if (r === 3 - i || r === 3 + i || c === 3 - i || c === 3 + i) {\n frame[r][c] = 1\n }\n }\n }\n }\n frames.push(frame)\n }\n return frames\n})()\n\nconst burst: Frame[] = (() => {\n const frames: Frame[] = []\n for (let f = 0; f < 8; f++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n\n const intensity = f < 4 ? f / 3 : (7 - f) / 3\n\n if (f < 6) {\n for (let r = 0; r < 7; r++) {\n for (let c = 0; c < 7; c++) {\n const distance = Math.sqrt(Math.pow(r - 3, 2) + Math.pow(c - 3, 2))\n if (Math.abs(distance - f * 0.8) < 1.2) {\n frame[r][c] = intensity\n }\n }\n }\n }\n\n frames.push(frame)\n }\n return frames\n})()\n\nfunction createExpandedLogo(progress: number): Frame[] {\n const matrices: Frame[] = []\n\n for (let matrixIdx = 0; matrixIdx < 9; matrixIdx++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n matrices.push(frame)\n }\n\n const easeProgress =\n progress < 0.5\n ? 2 * progress * progress\n : 1 - Math.pow(-2 * progress + 2, 2) / 2\n\n if (easeProgress < 0.3) {\n const centerMatrix = matrices[4]\n for (let r = 1; r <= 5; r++) {\n centerMatrix[r][2] = 1\n centerMatrix[r][4] = 1\n }\n return matrices\n }\n\n const expandProgress = (easeProgress - 0.3) / 0.7\n\n for (let globalRow = 0; globalRow < 21; globalRow++) {\n for (let globalCol = 0; globalCol < 21; globalCol++) {\n const matrixRow = Math.floor(globalRow / 7)\n const matrixCol = Math.floor(globalCol / 7)\n const matrixIdx = matrixRow * 3 + matrixCol\n const localRow = globalRow % 7\n const localCol = globalCol % 7\n\n const leftBarStart = Math.floor(9 + (5 - 9) * expandProgress)\n const leftBarEnd = Math.floor(9 + (7 - 9) * expandProgress)\n const rightBarStart = Math.floor(11 + (13 - 11) * expandProgress)\n const rightBarEnd = Math.floor(11 + (15 - 11) * expandProgress)\n\n const isLeftBar = globalCol >= leftBarStart && globalCol <= leftBarEnd\n const isRightBar = globalCol >= rightBarStart && globalCol <= rightBarEnd\n const inVerticalRange = globalRow >= 4 && globalRow <= 16\n\n if ((isLeftBar || isRightBar) && inVerticalRange) {\n matrices[matrixIdx][localRow][localCol] = 1\n }\n }\n }\n\n return matrices\n}\n\nfunction createCollapseEffect(progress: number): Frame[] {\n const matrices: Frame[] = []\n\n for (let matrixIdx = 0; matrixIdx < 9; matrixIdx++) {\n const frame: Frame = Array(7)\n .fill(0)\n .map(() => Array(7).fill(0))\n matrices.push(frame)\n }\n\n const easeProgress =\n progress < 0.5\n ? 2 * progress * progress\n : 1 - Math.pow(-2 * progress + 2, 2) / 2\n\n if (easeProgress < 0.4) {\n const collapseProgress = easeProgress / 0.4\n\n for (let globalRow = 0; globalRow < 21; globalRow++) {\n for (let globalCol = 0; globalCol < 21; globalCol++) {\n const matrixRow = Math.floor(globalRow / 7)\n const matrixCol = Math.floor(globalCol / 7)\n const matrixIdx = matrixRow * 3 + matrixCol\n const localRow = globalRow % 7\n const localCol = globalCol % 7\n\n const leftBarStart = Math.floor(5 + (9 - 5) * collapseProgress)\n const leftBarEnd = Math.floor(7 + (9 - 7) * collapseProgress)\n const rightBarStart = Math.floor(13 + (11 - 13) * collapseProgress)\n const rightBarEnd = Math.floor(15 + (11 - 15) * collapseProgress)\n\n const isLeftBar = globalCol >= leftBarStart && globalCol <= leftBarEnd\n const isRightBar =\n globalCol >= rightBarStart && globalCol <= rightBarEnd\n const inVerticalRange = globalRow >= 4 && globalRow <= 16\n\n if ((isLeftBar || isRightBar) && inVerticalRange) {\n matrices[matrixIdx][localRow][localCol] = 1\n }\n }\n }\n } else {\n const centerMatrix = matrices[4]\n const fadeProgress = (easeProgress - 0.4) / 0.6\n const brightness = 1 - fadeProgress\n\n for (let r = 1; r <= 5; r++) {\n centerMatrix[r][2] = brightness\n centerMatrix[r][4] = brightness\n }\n }\n\n return matrices\n}\n\nexport default Example\n", "type": "registry:example" } ], "type": "registry:example" }