@getmicdrop/venue-calendar
v3.4.0
Published
A customizable Svelte calendar component for displaying comedy events
Downloads
4,615
Readme
@getmicdrop/venue-calendar
A beautiful, customizable calendar component built with Svelte for displaying comedy events. Perfect for comedy clubs, venues, and event organizers who want to showcase their upcoming shows.
Features
✨ Three View Modes: List, Gallery, and Calendar views 🎨 Beautiful UI: Modern, responsive design built with Tailwind CSS 📱 Mobile-Friendly: Swipe gestures, touch-optimized, responsive design 🔌 Easy Integration: Works with React, Vue, vanilla JS, and more 🌐 CDN Ready: Use directly in HTML via JSDelivr ⚡ Auto-Mount: Automatically finds and mounts to designated containers 🎯 Customizable: Configure views, navigation, and more 🌙 Dark Mode: Built-in light, dark, and high-contrast themes ♿ Accessible: ARIA labels, keyboard navigation, screen reader support 🎫 Event Status: Visual badges for "On Sale", "Selling Fast", "Sold Out"
Installation
NPM/Yarn
npm install @getmicdrop/venue-calendaror
yarn add @getmicdrop/venue-calendarCDN (JSDelivr)
<!-- Latest version -->
<script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
<!-- Specific version (recommended for production) -->
<script src="https://cdn.jsdelivr.net/npm/@getmicdrop/[email protected]/dist/venue-calendar.iife.js"></script>Quick Start
Method 1: Auto-Mount (Easiest)
Simply add a div with the class micdrop-calendar-container and the calendar will automatically mount:
<!DOCTYPE html>
<html>
<head>
<title>My Comedy Club</title>
</head>
<body>
<!-- Calendar will auto-mount here -->
<div class="micdrop-calendar-container"
data-venue-id="your-venue-id"
data-view="calendar"
data-show-view-options="true"
data-show-month-switcher="true">
</div>
<!-- Load the script -->
<script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
</body>
</html>Method 2: Web Component
Use the custom <micdrop-calendar> element:
<!DOCTYPE html>
<html>
<head>
<title>My Comedy Club</title>
</head>
<body>
<!-- Web Component -->
<micdrop-calendar
venue-id="your-venue-id"
view="calendar"
show-view-options="true"
show-month-switcher="true">
</micdrop-calendar>
<script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
</body>
</html>Method 3: JavaScript API
For more control, use the JavaScript API:
<!DOCTYPE html>
<html>
<head>
<title>My Comedy Club</title>
</head>
<body>
<div id="my-calendar"></div>
<script type="module">
import { initVenueCalendar } from 'https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.es.js';
initVenueCalendar({
target: '#my-calendar',
venueId: 'your-venue-id',
view: 'calendar',
events: [],
showViewOptions: true,
showMonthSwitcher: true,
});
</script>
</body>
</html>Framework Integration
React
import React, { useEffect, useRef } from 'react';
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
function VenueCalendarComponent({ venueId, view = 'calendar' }) {
const calendarRef = useRef(null);
const instanceRef = useRef(null);
useEffect(() => {
if (calendarRef.current) {
// Initialize calendar
instanceRef.current = initVenueCalendar({
target: calendarRef.current,
venueId,
view,
events: [],
showViewOptions: true,
showMonthSwitcher: true,
});
}
// Cleanup on unmount
return () => {
if (instanceRef.current && instanceRef.current.$destroy) {
instanceRef.current.$destroy();
}
};
}, [venueId, view]);
return <div ref={calendarRef}></div>;
}
export default VenueCalendarComponent;Usage in React App:
import React, { useState } from "react";
import VenueCalendarComponent from "./VenueCalendarComponent";
function App() {
const [venueId, setVenueId] = useState("comedy-club-123");
const [view, setView] = useState("calendar");
return (
<div style={{ padding: "20px" }}>
<h1>Event Viewer</h1>
<div style={{ marginBottom: "20px" }}>
<label>Venue ID:</label>
<input
type="text"
value={venueId}
onChange={(e) => setVenueId(e.target.value)}
/>
</div>
<div style={{ marginBottom: "20px" }}>
<label>Select View:</label>
<label>
<input
type="radio"
value="list"
checked={view === "list"}
onChange={(e) => setView(e.target.value)}
/>
List
</label>
<label>
<input
type="radio"
value="gallery"
checked={view === "gallery"}
onChange={(e) => setView(e.target.value)}
/>
Gallery
</label>
<label>
<input
type="radio"
value="calendar"
checked={view === "calendar"}
onChange={(e) => setView(e.target.value)}
/>
Calendar
</label>
</div>
<VenueCalendarComponent venueId={venueId} view={view} />
</div>
);
}
export default App;Vue 3
<template>
<div ref="calendarContainer"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
const props = defineProps({
venueId: String,
view: {
type: String,
default: 'calendar'
}
});
const calendarContainer = ref(null);
let calendarInstance = null;
onMounted(() => {
calendarInstance = initVenueCalendar({
target: calendarContainer.value,
venueId: props.venueId,
view: props.view,
events: [],
showViewOptions: true,
showMonthSwitcher: true,
});
});
onUnmounted(() => {
if (calendarInstance && calendarInstance.$destroy) {
calendarInstance.$destroy();
}
});
watch(() => props.venueId, (newId) => {
if (calendarInstance) {
calendarInstance.$destroy();
calendarInstance = initVenueCalendar({
target: calendarContainer.value,
venueId: newId,
view: props.view,
events: [],
showViewOptions: true,
showMonthSwitcher: true,
});
}
});
</script>Svelte
<script>
import { VenueCalendar } from '@getmicdrop/venue-calendar';
import { Calendar, Grid, List } from 'carbon-icons-svelte';
import { writable } from 'svelte/store';
let venueId = 'your-venue-id';
let currentMonth = writable(new Date().getUTCMonth());
let currentYear = writable(new Date().getUTCFullYear());
function handleNext() {
currentMonth.update(m => m + 1);
}
function handlePrev() {
currentMonth.update(m => m - 1);
}
</script>
<VenueCalendar
showViewOptions={[
{ id: 0, text: "List view", icon: List },
{ id: 1, text: "Gallery view", icon: Grid },
{ id: 2, text: "Calendar view", icon: Calendar }
]}
showMonthSwitcher={true}
events={[]}
{currentMonth}
{currentYear}
handleNext={handleNext}
handlePrev={handlePrev}
on:eventClick={(e) => console.log('Event clicked:', e.detail)}
/>Angular
import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
@Component({
selector: 'app-venue-calendar',
template: '<div #calendarContainer></div>',
})
export class VenueCalendarComponent implements OnInit, OnDestroy {
@ViewChild('calendarContainer', { static: true }) calendarContainer!: ElementRef;
private calendarInstance: any;
ngOnInit() {
this.calendarInstance = initVenueCalendar({
target: this.calendarContainer.nativeElement,
venueId: 'your-venue-id',
view: 'calendar',
events: [],
showViewOptions: true,
showMonthSwitcher: true,
});
}
ngOnDestroy() {
if (this.calendarInstance && this.calendarInstance.$destroy) {
this.calendarInstance.$destroy();
}
}
}Configuration Options
Data Attributes (for auto-mount)
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| data-venue-id | string | '' | The venue ID to fetch events for |
| data-view | string | 'calendar' | Initial view: 'list', 'gallery', or 'calendar' |
| data-show-view-options | boolean | true | Show view switcher buttons |
| data-show-month-switcher | boolean | true | Show month navigation controls |
JavaScript API Options
initVenueCalendar({
target: '.my-calendar', // CSS selector or HTMLElement (required)
venueId: 'venue-123', // Venue ID (optional)
view: 'calendar', // 'list', 'gallery', or 'calendar' (default: 'calendar')
events: [], // Array of event objects (default: [])
showViewOptions: true, // Show view switcher (default: true)
showMonthSwitcher: true, // Show month navigation (default: true)
});Event Object Structure
{
id: 'event-123',
name: 'Comedy Night',
date: '2024-10-25T20:00:00Z',
image: 'https://example.com/image.jpg',
status: 'On Sale',
timeline: '8:00 PM - 10:00 PM',
// ... other fields
}Views
Calendar View
The default view showing events in a monthly calendar grid. Perfect for venues with regular shows.
List View
A vertical list layout showing all upcoming events with details. Great for mobile experiences.
Gallery View
A grid layout displaying event posters in a gallery format. Ideal for showcasing event imagery.
WordPress Integration
For WordPress sites, you can add this to your page/post HTML:
<div class="micdrop-calendar-container"
data-venue-id="your-venue-id"
data-view="calendar">
</div>
<script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>Or add the script to your theme's footer and use the div anywhere in your content.
Styling
The calendar comes with built-in styles using Tailwind CSS. If you need to customize the appearance, you can override the CSS classes or add your own styles.
/* Example: Custom styling */
.micdrop-calendar-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}Theming
The calendar supports comprehensive theming via CSS custom properties and JavaScript utilities.
Using CSS Custom Properties
Override the default theme by setting CSS custom properties:
/* Custom brand colors */
.micdrop-calendar-container {
--Brand-Primary: 270 76% 60%; /* Purple */
--Text-Primary: 0 0% 10%;
--BG-Primary: 0 0% 100%;
}
/* Dark mode */
.dark .micdrop-calendar-container,
[data-theme="dark"] .micdrop-calendar-container {
--Brand-Primary: 270 76% 70%;
--Text-Primary: 0 0% 95%;
--BG-Primary: 0 0% 10%;
}Available CSS Variables
| Variable | Description | Default (Light) |
|----------|-------------|-----------------|
| --Brand-Primary | Primary brand color | 217 91% 60% (Blue) |
| --Text-Primary | Main text color | 0 0% 0% |
| --Text-Secondary | Secondary text | 0 0% 40% |
| --BG-Primary | Main background | 0 0% 100% |
| --BG-Secondary | Secondary background | 0 0% 98% |
| --Stroke-Primary | Border colors | 0 0% 80% |
| --Status-OnSale | "On Sale" badge | 217 91% 60% |
| --Status-SellingFast | "Selling Fast" badge | 38 92% 50% |
| --Status-SoldOut | "Sold Out" badge | 0 84% 60% |
| --Today-BG | Today's date background | 217 91% 97% |
| --Focus-Ring | Keyboard focus ring | 217 91% 60% |
Using JavaScript Theme Utilities
import { applyTheme, themes, generateThemeCSS } from '@getmicdrop/venue-calendar';
// Apply a preset theme
applyTheme(themes.dark);
// Apply to a specific container
const container = document.querySelector('.micdrop-calendar-container');
applyTheme(themes.dark, container);
// Create a custom theme
const myTheme = {
brandPrimary: '270 76% 60%', // Purple
textPrimary: '0 0% 10%',
bgPrimary: '0 0% 100%',
statusOnSale: '142 71% 45%', // Green for on sale
};
applyTheme(myTheme);
// Generate CSS string for embedding
const cssString = generateThemeCSS(myTheme);
console.log(cssString);
// Output: :root { --Brand-Primary: 270 76% 60%; ... }Preset Themes
Three themes are included out of the box:
import { themes } from '@getmicdrop/venue-calendar';
// Light theme (default)
applyTheme(themes.light);
// Dark theme
applyTheme(themes.dark);
// High contrast (accessibility)
applyTheme(themes.highContrast);Automatic Dark Mode
The calendar automatically respects the user's system preference:
/* Automatically applied when user prefers dark mode */
@media (prefers-color-scheme: dark) {
/* Dark theme variables are applied */
}You can also manually toggle dark mode:
<!-- Add 'dark' class to enable dark theme -->
<div class="dark">
<div class="micdrop-calendar-container" data-venue-id="123"></div>
</div>
<!-- Or use data-theme attribute -->
<div data-theme="dark">
<div class="micdrop-calendar-container" data-venue-id="123"></div>
</div>Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
Development
Building the Package
# Install dependencies
npm install
# Build the library
npm run build:lib
# Development mode (SvelteKit app)
npm run dev
# Preview production build
npm run previewProject Structure
venue-calendar/
├── src/
│ ├── components/ # Svelte components
│ │ ├── Calendar/
│ │ ├── CalendarContainer/
│ │ └── Button/
│ ├── lib/ # Library entry points
│ │ ├── VenueCalendar.js
│ │ └── web-component.js
│ └── routes/ # SvelteKit routes (for dev)
├── dist/ # Built package (generated)
├── package.json
├── vite.config.lib.js # Library build config
└── README.mdAPI Reference
initVenueCalendar(options)
Initialize a calendar instance.
Parameters:
options(Object): Configuration options
Returns: Svelte component instance
Example:
const calendar = initVenueCalendar({
target: '#calendar',
venueId: 'venue-123',
view: 'calendar',
});autoMount()
Automatically mount calendars to all elements with class micdrop-calendar-container.
Example:
import { autoMount } from '@getmicdrop/venue-calendar';
autoMount();Component Events
The calendar component emits events that you can listen to:
const calendar = initVenueCalendar({
target: '#calendar',
// ... other options
});
// Listen to component events (if using Svelte component directly)
calendar.$on('eventClick', (event) => {
console.log('Event clicked:', event.detail);
});Troubleshooting
Calendar not appearing
- Check the script is loaded: Open browser console and verify no errors
- Verify container exists: Make sure the target element exists in the DOM
- Check data attributes: Ensure attributes are correctly formatted with
data-prefix
Styles not applying
- CSS not loaded: The styles are bundled in the JS file and auto-injected
- CSS conflicts: Check if other styles are overriding the calendar styles
- CDN issues: Try using a specific version instead of
@latest
Events not showing
- Check event data format: Ensure events match the expected structure
- Date format: Use ISO 8601 format for dates (
YYYY-MM-DDTHH:mm:ssZ) - Venue ID: Verify the venue ID is correct
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT © MicDrop
Support
For issues, questions, or feature requests, please visit: https://github.com/get-micdrop/venue-calendar/issues
Made with ❤️ by the MicDrop team
