This component no longer exists. It was in ruixen-ui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-12 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
Calendar Wave
ruixen-ui/calendar-waveRemovedComponent
A calendar where days rise toward your cursor like water — cosine wave ripple, spring physics, shadow depth.
Live preview
live · rendered by the registry
Rendered by ruixen-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ruixen.com/r/calendar-wave.jsonSource
1"use client";23import { useState, useMemo, useRef, useCallback } from "react";4import { AnimatePresence, motion } from "motion/react";5import { cn } from "@/lib/utils";67/**8 * Calendar Wave — a calendar where days respond to your cursor9 * like the surface of water.10 *11 * Move over the grid: nearby days rise toward you, creating a12 * smooth cosine wave that ripples outward. Lifted cells brighten13 * and cast deeper shadows. Click to select — the chosen day14 * locks at peak height with a spring pop.15 *16 * The surface IS the interaction.17 */1819/* ── constants ── */20const MONTHS = [21 "January",22 "February",23 "March",24 "April",25 "May",26 "June",27 "July",28 "August",29 "September",30 "October",31 "November",32 "December",33];34const DOW = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];35const CELL = 40;36const GAP = 2;37const STEP = CELL + GAP;38const RADIUS = 110;39const MAX_LIFT = 8;4041/* ── date math ── */42function dim(y: number, m: number) {43 return new Date(y, m + 1, 0).getDate();44}45function soff(y: number, m: number) {46 return (new Date(y, m, 1).getDay() + 6) % 7;47}48function pad(n: number) {49 return String(n).padStart(2, "0");50}51function toKey(y: number, m: number, d: number) {52 return `${y}-${pad(m + 1)}-${pad(d)}`;53}54function parseKey(k: string) {55 const [y, m, d] = k.split("-").map(Number);56 return { y, m: m - 1, d };57}5859/* ── wave math ── */60function waveLift(mx: number, my: number, col: number, row: number): number {61 const cx = col * STEP + CELL / 2;62 const cy = row * STEP + CELL / 2;63 const dx = mx - cx;64 const dy = my - cy;65 const dist = Math.sqrt(dx * dx + dy * dy);66 if (dist >= RADIUS) return 0;67 const t = dist / RADIUS;68 return (MAX_LIFT * (1 + Math.cos(Math.PI * t))) / 2;69}7071/* ── sound ── */72let _ctx: AudioContext | null = null;73let _buf: AudioBuffer | null = null;7475function _init() {76 if (_ctx) return;77 _ctx = new AudioContext();78 const n = Math.ceil(_ctx.sampleRate * 0.003);79 _buf = _ctx.createBuffer(1, n, _ctx.sampleRate);80 const ch = _buf.getChannelData(0);81 for (let i = 0; i < n; i++) {82 const t = i / n;83 ch[i] = (Math.random() * 2 - 1) * Math.pow(1 - t, 4) * 0.12;84 }85}8687let _last = 0;88function _tick() {89 const now = Date.now();90 if (now - _last < 60) return;91 _last = now;92 if (!_ctx || !_buf) return;93 const s = _ctx.createBufferSource();94 s.buffer = _buf;95 s.connect(_ctx.destination);96 s.start();97}9899/* ── types ── */100export interface CalendarWaveProps {101// … truncated
What it pulls in
npm packages
