npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agsci/fullcalendar-svelte-shadcn

v0.1.0

Published

A Svelte 5 component library wrapping FullCalendar with shadcn-svelte styling. Fully themeable, dark mode ready, TypeScript support.

Readme

FullCalendar Svelte + shadcn

A Svelte 5 component library wrapping FullCalendar with shadcn-svelte styling. Fully themeable, accessible, and designed to integrate seamlessly with your existing shadcn design system.

Features

  • Svelte 5 Runes - Built with $state, $derived, and $effect for optimal reactivity
  • Full FullCalendar Power - Day, week, month views with drag-and-drop, resizing, and selection
  • Themeable - Automatically inherits your shadcn theme via CSS custom properties
  • Dark Mode Ready - Works with your existing dark mode setup out of the box
  • Tree-shakeable - Only import what you need
  • TypeScript - Full type definitions included

Installation

npm install @agsci/fullcalendar-svelte-shadcn @fullcalendar/core

Optional Plugins

Install the FullCalendar plugins you need:

# For day/week views (time grid)
npm install @fullcalendar/daygrid @fullcalendar/timegrid

# For drag-and-drop and selection
npm install @fullcalendar/interaction

# For list view
npm install @fullcalendar/list

Quick Start

<script lang="ts">
  import { Calendar, CalendarNav, type CalendarEvent, type CalendarView } from '@agsci/fullcalendar-svelte-shadcn';
  import '@agsci/fullcalendar-svelte-shadcn/styles';

  let events = $state<CalendarEvent[]>([
    {
      id: '1',
      title: 'Team Meeting',
      start: new Date(),
      end: new Date(Date.now() + 60 * 60 * 1000),
      backgroundColor: '#3b82f6'
    }
  ]);

  let viewedDate = $state(new Date());
  let currentView = $state<CalendarView>('week');
  let calendarRef: { prev: () => void; next: () => void; today: () => void; changeView: (v: CalendarView) => void };
</script>

<CalendarNav
  {viewedDate}
  {currentView}
  onPrev={() => calendarRef?.prev()}
  onNext={() => calendarRef?.next()}
  onToday={() => calendarRef?.today()}
  onViewChange={(v) => { currentView = v; calendarRef?.changeView(v); }}
/>

<Calendar
  bind:this={calendarRef}
  {events}
  config={{ initialView: 'week', editable: true, selectable: true }}
  onEventClick={(event) => console.log('Clicked:', event)}
  onDatesSet={(start) => viewedDate = start}
  onViewChange={(v) => currentView = v}
/>

Components

Calendar

The main calendar component wrapping FullCalendar.

<Calendar
  events={events}
  config={{
    initialView: 'week',      // 'day' | 'week' | 'month' | 'list'
    slotMinTime: '07:00',     // Earliest time slot
    slotMaxTime: '21:00',     // Latest time slot
    height: '600px',          // Calendar height
    editable: true,           // Enable drag-and-drop
    selectable: true,         // Enable date range selection
    nowIndicator: true,       // Show current time line
    firstDay: 0               // Week start (0=Sunday, 1=Monday)
  }}
  onEventClick={(event) => {}}
  onEventChange={(event, oldEvent, revert) => {}}
  onDateSelect={(start, end, allDay) => {}}
  onDateClick={(date, allDay) => {}}
  onDatesSet={(start, end) => {}}
  onViewChange={(view) => {}}
/>

CalendarNav

Navigation controls with month/year selectors and view switcher.

<CalendarNav
  viewedDate={viewedDate}
  currentView={currentView}
  onPrev={() => calendarRef?.prev()}
  onNext={() => calendarRef?.next()}
  onToday={() => calendarRef?.today()}
  onViewChange={(view) => calendarRef?.changeView(view)}
  onDateChange={(date) => calendarRef?.gotoDate(date)}
/>

Event Dialogs

Pre-built dialogs for viewing, adding, editing, and deleting events.

<script>
  import { EventView, EventAddDialog, EventEditDialog, EventDeleteDialog } from '@agsci/fullcalendar-svelte-shadcn';
</script>

<EventView
  event={selectedEvent}
  open={viewOpen}
  onClose={() => viewOpen = false}
  onEdit={(event) => { /* open edit dialog */ }}
  onDelete={(event) => { /* open delete dialog */ }}
/>

<EventAddDialog
  open={addOpen}
  defaultStart={selectedStart}
  defaultEnd={selectedEnd}
  onClose={() => addOpen = false}
  onAdd={(eventData) => events = [...events, { id: Date.now().toString(), ...eventData }]}
/>

<EventEditDialog
  event={selectedEvent}
  open={editOpen}
  onClose={() => editOpen = false}
  onSave={(id, updates) => events = events.map(e => e.id === id ? { ...e, ...updates } : e)}
/>

<EventDeleteDialog
  event={selectedEvent}
  open={deleteOpen}
  onClose={() => deleteOpen = false}
  onConfirm={(id) => events = events.filter(e => e.id !== id)}
/>

Customization

Theming via CSS Custom Properties

The calendar automatically inherits your shadcn theme. It uses CSS custom properties that map to your theme tokens:

/* The library uses these variables (with sensible fallbacks) */
:root {
  --fc-border-color: var(--border);
  --fc-bg: var(--background);
  --fc-text: var(--foreground);
  --fc-muted: var(--muted-foreground);
  --fc-today-bg: var(--accent);
  --fc-hover-bg: var(--secondary);
  --fc-primary: var(--primary);
  --fc-primary-foreground: var(--primary-foreground);
}

No extra configuration needed - if you have shadcn-svelte set up, the calendar matches your theme automatically.

Custom Theme Overrides

Override specific calendar styles in your app's CSS:

/* Make the calendar more compact */
:root {
  --fc-slot-height: 2.5rem;
  --fc-header-height: 2.5rem;
}

/* Custom event colors */
.fc-event {
  --fc-event-radius: 0.5rem;
}

/* Different today highlight */
.fc-day-today {
  --fc-today-bg: hsl(var(--primary) / 0.1);
}

Dark Mode

The calendar respects your dark mode setup. If you use the standard .dark class approach:

.dark {
  --border: hsl(240 3.7% 15.9%);
  --background: hsl(240 10% 3.9%);
  --foreground: hsl(0 0% 98%);
  /* ... your other dark mode tokens */
}

The calendar will automatically adapt.

Component-Level Styling

Pass custom classes to components:

<Calendar class="rounded-lg shadow-lg" />
<CalendarNav class="mb-4 px-2" />

Event Styling

Control event appearance via the event data:

const event: CalendarEvent = {
  id: '1',
  title: 'Important Meeting',
  start: new Date(),
  end: new Date(),
  backgroundColor: '#ef4444',  // Red background
  textColor: '#ffffff',        // White text
};

Or use the color picker in the Add/Edit dialogs.

Types

interface CalendarEvent {
  id: string;
  title: string;
  start: Date;
  end: Date;
  description?: string;
  backgroundColor?: string;
  textColor?: string;
  allDay?: boolean;
  extendedProps?: Record<string, unknown>;
}

interface CalendarConfig {
  initialView?: 'day' | 'week' | 'month' | 'list';
  slotMinTime?: string;  // e.g., '07:00'
  slotMaxTime?: string;  // e.g., '21:00'
  firstDay?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
  editable?: boolean;
  selectable?: boolean;
  nowIndicator?: boolean;
  height?: string | number;
  allDaySlot?: boolean;
  timeZone?: string;
}

type CalendarView = 'day' | 'week' | 'month' | 'list';

State Management

For complex apps, use the provided state utilities:

import { createCalendarState, setCalendarContext, getCalendarContext } from '@agsci/fullcalendar-svelte-shadcn';

// In a parent component
const calendarState = createCalendarState(initialEvents);
setCalendarContext(calendarState);

// In child components
const state = getCalendarContext();
state.addEvent(newEvent);
state.selectEvent(event);
state.openModal('add');

Utilities

Helpful date utilities are exported:

import {
  formatDate,      // 'Dec 8, 2024'
  formatTime,      // '2:30 PM'
  formatDateRange, // 'Dec 8, 2:00 PM - 3:00 PM'
  isSameDay,
  isToday,
  toDateString,    // '2024-12-08' (for inputs)
  toTimeString,    // '14:30' (for inputs)
} from '@agsci/fullcalendar-svelte-shadcn';

Requirements

  • Svelte 5.x
  • @fullcalendar/core 6.x
  • A project with shadcn-svelte set up (for theme tokens)

Development

# Install dependencies
pnpm install

# Start dev server
pnpm dev

# Type check
pnpm check

# Build library
pnpm build

License

MIT

Credits