@agenda-kit/svelte
v0.1.5
Published
Booking/agenda calendar micro-plugin for Svelte 5 (runes) — wraps FullCalendar with reactive state, a DaisyUI toolbar, and an overridable create/edit dialog.
Downloads
562
Readme
AgendaCalendar — Micro-Plugin
FullCalendar v6 · Svelte 5 (Runes) · DaisyUI · Lucide Icons Experimental: Do not use in production until v1.0.0. Agenda calendar for multi-resource platforms.
Why FullCalendar?
FullCalendar is the industry-standard calendar library (10M+ weekly downloads). It handles everything that is genuinely hard to build correctly:
- Timezone & DST awareness
- Drag-and-drop with collision detection
- Event resizing with snap-to-grid
- Recurring events (RRULE)
- iCal import/export
- Accessibility (ARIA, keyboard navigation, screen reader tested)
- Touch / mobile gesture support
- 50K+ unit tests upstream
We wrap it with a thin Svelte 5 controller so you get all of that for free, plus reactive Svelte state, DaisyUI styling, and our domain API on top.
Install
npm install \
@fullcalendar/core \
@fullcalendar/daygrid \
@fullcalendar/timegrid \
@fullcalendar/list \
@fullcalendar/interactionOptional (premium, requires license key — needed for the multi-resource view):
npm install \
@fullcalendar/resource \
@fullcalendar/resource-timegrid \
@fullcalendar/resource-daygridSee FullCalendar Pricing for the Scheduler license. The free plugins cover month, week, day, and list views — fully functional for most operators.
Quick Start
<script lang="ts">
import AgendaCalendar, { generateMockData } from '@agenda-kit/svelte';
const { resources, events } = generateMockData();
</script>
<AgendaCalendar {resources} {events} />Usage Patterns
Pattern 1 — Minimal
<AgendaCalendar {resources} {events} />Component self-manages its FullCalendar instance. Simplest possible usage.
Pattern 2 — With options
<AgendaCalendar
{resources}
{events}
options={{
initialView: 'listWeek',
firstDayOfWeek: 1,
onEventSave: async (payload) => await api.saveEvent(payload),
onEventDelete: async (id) => await api.deleteEvent(id),
onEventMove: async (event) => await api.moveEvent(event),
i18n: { today: "Aujourd'hui", viewMonth: 'Mois' }
}}
/>Pattern 3 — External controller (full control)
<script lang="ts">
import AgendaCalendar, { createAgendaCalendarController, FCView } from '@agenda-kit/svelte';
const ctrl = createAgendaCalendarController({ resources, events });
</script>
<!-- Drive the calendar from anywhere in your page -->
<button onclick={() => ctrl.changeView(FCView.LIST_WEEK)}>Schedule</button>
<button onclick={() => ctrl.today()}>Today</button>
<!-- Pass the controller in -->
<AgendaCalendar controller={ctrl} />Controller API
Readable state
| Property | Type | Description |
| ----------------- | ------------------ | ---------------------------------- |
| resources | AgendaResource[] | All resources |
| events | AgendaEvent[] | All events |
| activeView | string | Current FC view name |
| headerLabel | string | Toolbar title text |
| filterResourceId | string \| null | Active filter |
| filteredEvents | AgendaEvent[] | Events after filter |
| popoverOpen | boolean | Is the EventForm open? |
| fc | Calendar \| null | The raw FC instance (escape hatch) |
Navigation
ctrl.next();
ctrl.prev();
ctrl.today();
ctrl.goToDate('2025-12-25');
ctrl.changeView(FCView.TIME_GRID_WEEK);Data mutation
ctrl.setResources(newResources);
ctrl.addResource(resource);
ctrl.removeResource(id);
ctrl.setEvents(newEvents);
ctrl.addEvent(event);
ctrl.updateEvent(updatedEvent);
ctrl.removeEvent(id);
ctrl.setFilter(resourceId); // null = show allPopover API
ctrl.openCreatePopover(slotStart?, slotEnd?, resourceId?)
ctrl.openEditPopover(event)
ctrl.closePopover()
await ctrl.handleEventSave(payload)
await ctrl.handleEventDelete(id)Views
| FCView enum | FullCalendar name | Plugin |
| -------------------- | ---------------------- | -------------------------------------------- |
| DAY_GRID_MONTH | dayGridMonth | @fullcalendar/daygrid (free) |
| DAY_GRID_WEEK | dayGridWeek | @fullcalendar/daygrid (free) |
| TIME_GRID_WEEK | timeGridWeek | @fullcalendar/timegrid (free) |
| TIME_GRID_DAY | timeGridDay | @fullcalendar/timegrid (free) |
| LIST_WEEK | listWeek | @fullcalendar/list (free) |
| RESOURCE_TIME_WEEK | resourceTimeGridWeek | @fullcalendar/resource-timegrid ⚠️ premium |
| RESOURCE_DAY_GRID | resourceDayGridWeek | @fullcalendar/resource-daygrid ⚠️ premium |
i18n
Pass any subset of CalendarI18n — missing keys fall back to English.
<AgendaCalendar
{resources}
{events}
options={{
i18n: {
today: "Aujourd'hui",
viewMonth: 'Mois',
viewWeek: 'Semaine',
viewDay: 'Jour',
viewList: 'Agenda',
newEvent: 'Nouvel événement',
save: 'Enregistrer',
cancel: 'Annuler',
delete: 'Supprimer',
allResources: 'Toutes les annonces'
}
}}
/>Or with the controller:
import { createAgendaCalendarController, mergeI18n } from '@agenda-kit/svelte';
const ctrl = createAgendaCalendarController({
resources,
events,
i18n: mergeI18n({ today: 'Hoy', viewMonth: 'Mes' }) // Spanish
});Styling with DaisyUI
The AgendaCalendar.svelte file includes a <style> block that maps
FullCalendar's CSS custom properties to DaisyUI variables:
.agenda-calendar {
--fc-border-color: /* DaisyUI base-content/15 */ --fc-today-bg-color:
/* DaisyUI primary/6 */
--fc-highlight-color: /* DaisyUI primary/12 */ --fc-event-border-color: transparent;
--fc-now-indicator-color: /* DaisyUI error */;
}You can extend these overrides in your own CSS:
/* In your global CSS or app.css */
.agenda-calendar {
--fc-small-font-size: 0.8em;
--fc-daygrid-event-dot-width: 8px;
}Adding the Scheduler (resource views)
resources is already forwarded to FullCalendar by buildFCOptions — no
source changes needed, just add the plugin and a licence key:
Get a license from fullcalendar.io/pricing
Install the packages:
npm install @fullcalendar/resource @fullcalendar/resource-timegridRegister the plugins and licence key via the
calendarOptionsescape hatch:import resourcePlugin from '@fullcalendar/resource'; import resourceTimePlugin from '@fullcalendar/resource-timegrid'; const ctrl = createAgendaCalendarController({ resources, events, calendarOptions: { plugins: [resourcePlugin, resourceTimePlugin], schedulerLicenseKey: 'YOUR_KEY' } });Use the view:
ctrl.changeView(FCView.RESOURCE_TIME_WEEK);
Production Checklist
- [ ] Replace
generateMockData()with your API - [ ] Implement
onEventSave→POST /api/events - [ ] Implement
onEventDelete→DELETE /api/events/:id - [ ] Implement
onEventMove→PATCH /api/events/:id - [ ] Add iCal sync → push
ctrl.setEvents(synced)on a timer - [ ] Scope to authenticated user (server-side, in
+page.server.ts) - [ ] Delete
utils/mocks.tsfrom production bundle - [ ] Add
schedulerLicenseKeyif you need resource views - [ ] Configure locale in FullCalendar if you need non-Latin scripts:
calendarOptions: { locale: 'fr'; } // or import a locale file - [ ] Test on iOS Safari (date input polyfill may be needed)
