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 Planner
ruixen-ui/calendar-plannerRemovedComponent
Vertical day stream — past fades, today glows, events live inline. Select a day, type, press Enter.
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-planner.jsonSource
1"use client";23import { useRef, useState, useMemo, useEffect, useCallback } from "react";4import { motion, AnimatePresence } from "motion/react";5import { cn } from "@/lib/utils";67/**8 * Calendar Planner — a vertical stream of days.9 *10 * No grid. Time flows downward like a notebook.11 * Past days fade, today glows with an accent bar,12 * future days wait quietly. Events live inline,13 * right next to the date they belong to.14 * Select a day, type, press Enter.15 *16 * The stream IS the schedule.17 */1819/* ── Types ── */2021export interface PlannerEvent {22 id: string;23 title: string;24 date: string; // "YYYY-MM-DD"25}2627export interface CalendarPlannerProps {28 events?: PlannerEvent[];29 onAdd?: (event: PlannerEvent) => void;30 onRemove?: (id: string) => void;31 sound?: boolean;32}3334/* ── Constants ── */3536const DAY_NAMES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];3738/* ── Helpers ── */3940function pad2(n: number): string {41 return String(n).padStart(2, "0");42}4344function toKey(y: number, m: number, d: number): string {45 return `${y}-${pad2(m + 1)}-${pad2(d)}`;46}4748function getDayName(y: number, m: number, d: number): string {49 return DAY_NAMES[(new Date(y, m, d).getDay() + 6) % 7];50}5152function isWeekend(y: number, m: number, d: number): boolean {53 const dow = new Date(y, m, d).getDay();54 return dow === 0 || dow === 6;55}5657/* ── Audio ── */5859let _ctx: AudioContext | null = null;60let _buf: AudioBuffer | null = null;6162function audioCtx() {63 if (!_ctx) {64 _ctx = new (window.AudioContext ||65 (window as unknown as { webkitAudioContext: typeof AudioContext })66 .webkitAudioContext)();67 }68 if (_ctx.state === "suspended") _ctx.resume();69 return _ctx;70}7172function ensureBuf(ac: AudioContext): AudioBuffer {73 if (_buf && _buf.sampleRate === ac.sampleRate) return _buf;74 const rate = ac.sampleRate;75 const len = Math.floor(rate * 0.003);76 const buf = ac.createBuffer(1, len, rate);77 const ch = buf.getChannelData(0);78 for (let i = 0; i < len; i++) {79 const t = i / len;80 ch[i] = (Math.random() * 2 - 1) * (1 - t) ** 4;81 }82 _buf = buf;83 return buf;84}8586function playTick(last: React.MutableRefObject<number>) {87 const now = performance.now();88 if (now - last.current < 80) return;89 last.current = now;90 try {91 const ac = audioCtx();92 const buf = ensureBuf(ac);93 const src = ac.createBufferSource();94 const gain = ac.createGain();95 src.buffer = buf;96 src.playbackRate.value = 1.15;97// … truncated
What it pulls in
npm packages
