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 Scheduler
ruixen-ui/calendar-schedulerRemovedComponent
Week-strip scheduler — horizontal day ribbon, vertical time ruler, one-tap booking with spring physics.
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-scheduler.jsonSource
1"use client";23import { useState, useMemo, useCallback, useRef, useEffect } from "react";4import { AnimatePresence, motion } from "motion/react";5import { cn } from "@/lib/utils";67/* ── constants ── */8const MONTHS = [9 "January",10 "February",11 "March",12 "April",13 "May",14 "June",15 "July",16 "August",17 "September",18 "October",19 "November",20 "December",21] as const;2223const WK = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"] as const;24const WKFULL = [25 "Sunday",26 "Monday",27 "Tuesday",28 "Wednesday",29 "Thursday",30 "Friday",31 "Saturday",32] as const;3334/* ── date math ── */35function dim(y: number, m: number) {36 return new Date(y, m + 1, 0).getDate();37}38function soff(y: number, m: number) {39 return (new Date(y, m, 1).getDay() + 6) % 7;40}41function pad(n: number) {42 return String(n).padStart(2, "0");43}44function fmtDate(y: number, m: number, d: number) {45 return `${y}-${pad(m + 1)}-${pad(d)}`;46}47function fmt12(h: number, m: number) {48 const ap = h >= 12 ? "PM" : "AM";49 const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h;50 return `${h12}:${pad(m)} ${ap}`;51}5253/* ── sound ── */54let _ctx: AudioContext | null = null;55let _buf: AudioBuffer | null = null;56function _init() {57 if (_ctx) return;58 _ctx = new AudioContext();59 const n = Math.ceil(_ctx.sampleRate * 0.003);60 _buf = _ctx.createBuffer(1, n, _ctx.sampleRate);61 const ch = _buf.getChannelData(0);62 for (let i = 0; i < n; i++) {63 const t = i / n;64 ch[i] = (Math.random() * 2 - 1) * Math.pow(1 - t, 4) * 0.12;65 }66}67let _last = 0;68function _tick() {69 const now = Date.now();70 if (now - _last < 60) return;71 _last = now;72 if (!_ctx || !_buf) return;73 const s = _ctx.createBufferSource();74 s.buffer = _buf;75 s.connect(_ctx.destination);76 s.start();77}7879/* ── types ── */80export interface CalendarSchedulerProps {81 /** Fires on confirm with ISO date string + 12h time string */82 onConfirm?: (value: { date: string; time: string }) => void;83 /** First bookable hour (0-23). Default 8 */84 startHour?: number;85 /** Last bookable hour (0-23, inclusive of :00). Default 18 */86 endHour?: number;87 /** Slot interval in minutes. Default 30 */88 interval?: number;89 /** Enable tick sound. Default true */90 sound?: boolean;91}9293type Slot = "month" | "day" | "time" | null;9495/* ── stagger helper ── */96const stagger = (i: number) => ({97 initial: { opacity: 0, y: 6 } as const,98 animate: { opacity: 1, y: 0, transition: { delay: i * 0.018 } } as const,99});100101// … truncated
What it pulls in
npm packages
