@getmicdrop/venue-calendar 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,661 +1,661 @@
1
- # @getmicdrop/venue-calendar
2
-
3
- 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.
4
-
5
- ## Features
6
-
7
- ✨ **Three View Modes**: List, Gallery, and Calendar views
8
- 🎨 **Beautiful UI**: Modern, responsive design built with Tailwind CSS
9
- 📱 **Mobile-Friendly**: Swipe gestures, touch-optimized, responsive design
10
- 🔌 **Easy Integration**: Works with React, Vue, vanilla JS, and more
11
- 🌐 **CDN Ready**: Use directly in HTML via JSDelivr
12
- ⚡ **Auto-Mount**: Automatically finds and mounts to designated containers
13
- 🎯 **Customizable**: Configure views, navigation, and more
14
- 🌙 **Dark Mode**: Built-in light, dark, and high-contrast themes
15
- ♿ **Accessible**: ARIA labels, keyboard navigation, screen reader support
16
- 🎫 **Event Status**: Visual badges for "On Sale", "Selling Fast", "Sold Out"
17
-
18
- ## Installation
19
-
20
- ### NPM/Yarn
21
-
22
- ```bash
23
- npm install @getmicdrop/venue-calendar
24
- ```
25
-
26
- or
27
-
28
- ```bash
29
- yarn add @getmicdrop/venue-calendar
30
- ```
31
-
32
- ### CDN (JSDelivr)
33
-
34
- ```html
35
- <!-- Latest version -->
36
- <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
37
-
38
- <!-- Specific version (recommended for production) -->
39
- <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar@1.3.0/dist/venue-calendar.iife.js"></script>
40
- ```
41
-
42
- ## Quick Start
43
-
44
- ### Method 1: Auto-Mount (Easiest)
45
-
46
- Simply add a div with the class `micdrop-calendar-container` and the calendar will automatically mount:
47
-
48
- ```html
49
- <!DOCTYPE html>
50
- <html>
51
- <head>
52
- <title>My Comedy Club</title>
53
- </head>
54
- <body>
55
- <!-- Calendar will auto-mount here -->
56
- <div class="micdrop-calendar-container"
57
- data-venue-id="your-venue-id"
58
- data-view="calendar"
59
- data-show-view-options="true"
60
- data-show-month-switcher="true">
61
- </div>
62
-
63
- <!-- Load the script -->
64
- <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
65
- </body>
66
- </html>
67
- ```
68
-
69
- ### Method 2: Web Component
70
-
71
- Use the custom `<micdrop-calendar>` element:
72
-
73
- ```html
74
- <!DOCTYPE html>
75
- <html>
76
- <head>
77
- <title>My Comedy Club</title>
78
- </head>
79
- <body>
80
- <!-- Web Component -->
81
- <micdrop-calendar
82
- venue-id="your-venue-id"
83
- view="calendar"
84
- show-view-options="true"
85
- show-month-switcher="true">
86
- </micdrop-calendar>
87
-
88
- <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
89
- </body>
90
- </html>
91
- ```
92
-
93
- ### Method 3: JavaScript API
94
-
95
- For more control, use the JavaScript API:
96
-
97
- ```html
98
- <!DOCTYPE html>
99
- <html>
100
- <head>
101
- <title>My Comedy Club</title>
102
- </head>
103
- <body>
104
- <div id="my-calendar"></div>
105
-
106
- <script type="module">
107
- import { initVenueCalendar } from 'https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.es.js';
108
-
109
- initVenueCalendar({
110
- target: '#my-calendar',
111
- venueId: 'your-venue-id',
112
- view: 'calendar',
113
- events: [],
114
- showViewOptions: true,
115
- showMonthSwitcher: true,
116
- });
117
- </script>
118
- </body>
119
- </html>
120
- ```
121
-
122
- ## Framework Integration
123
-
124
- ### React
125
-
126
- ```jsx
127
- import React, { useEffect, useRef } from 'react';
128
- import { initVenueCalendar } from '@getmicdrop/venue-calendar';
129
-
130
- function VenueCalendarComponent({ venueId, view = 'calendar' }) {
131
- const calendarRef = useRef(null);
132
- const instanceRef = useRef(null);
133
-
134
- useEffect(() => {
135
- if (calendarRef.current) {
136
- // Initialize calendar
137
- instanceRef.current = initVenueCalendar({
138
- target: calendarRef.current,
139
- venueId,
140
- view,
141
- events: [],
142
- showViewOptions: true,
143
- showMonthSwitcher: true,
144
- });
145
- }
146
-
147
- // Cleanup on unmount
148
- return () => {
149
- if (instanceRef.current && instanceRef.current.$destroy) {
150
- instanceRef.current.$destroy();
151
- }
152
- };
153
- }, [venueId, view]);
154
-
155
- return <div ref={calendarRef}></div>;
156
- }
157
-
158
- export default VenueCalendarComponent;
159
- ```
160
-
161
- **Usage in React App:**
162
-
163
- ```jsx
164
- import React, { useState } from "react";
165
- import VenueCalendarComponent from "./VenueCalendarComponent";
166
-
167
- function App() {
168
- const [venueId, setVenueId] = useState("comedy-club-123");
169
- const [view, setView] = useState("calendar");
170
-
171
- return (
172
- <div style={{ padding: "20px" }}>
173
- <h1>Event Viewer</h1>
174
-
175
- <div style={{ marginBottom: "20px" }}>
176
- <label>Venue ID:</label>
177
- <input
178
- type="text"
179
- value={venueId}
180
- onChange={(e) => setVenueId(e.target.value)}
181
- />
182
- </div>
183
-
184
- <div style={{ marginBottom: "20px" }}>
185
- <label>Select View:</label>
186
- <label>
187
- <input
188
- type="radio"
189
- value="list"
190
- checked={view === "list"}
191
- onChange={(e) => setView(e.target.value)}
192
- />
193
- List
194
- </label>
195
- <label>
196
- <input
197
- type="radio"
198
- value="gallery"
199
- checked={view === "gallery"}
200
- onChange={(e) => setView(e.target.value)}
201
- />
202
- Gallery
203
- </label>
204
- <label>
205
- <input
206
- type="radio"
207
- value="calendar"
208
- checked={view === "calendar"}
209
- onChange={(e) => setView(e.target.value)}
210
- />
211
- Calendar
212
- </label>
213
- </div>
214
-
215
- <VenueCalendarComponent venueId={venueId} view={view} />
216
- </div>
217
- );
218
- }
219
-
220
- export default App;
221
- ```
222
-
223
- ### Vue 3
224
-
225
- ```vue
226
- <template>
227
- <div ref="calendarContainer"></div>
228
- </template>
229
-
230
- <script setup>
231
- import { ref, onMounted, onUnmounted, watch } from 'vue';
232
- import { initVenueCalendar } from '@getmicdrop/venue-calendar';
233
-
234
- const props = defineProps({
235
- venueId: String,
236
- view: {
237
- type: String,
238
- default: 'calendar'
239
- }
240
- });
241
-
242
- const calendarContainer = ref(null);
243
- let calendarInstance = null;
244
-
245
- onMounted(() => {
246
- calendarInstance = initVenueCalendar({
247
- target: calendarContainer.value,
248
- venueId: props.venueId,
249
- view: props.view,
250
- events: [],
251
- showViewOptions: true,
252
- showMonthSwitcher: true,
253
- });
254
- });
255
-
256
- onUnmounted(() => {
257
- if (calendarInstance && calendarInstance.$destroy) {
258
- calendarInstance.$destroy();
259
- }
260
- });
261
-
262
- watch(() => props.venueId, (newId) => {
263
- if (calendarInstance) {
264
- calendarInstance.$destroy();
265
- calendarInstance = initVenueCalendar({
266
- target: calendarContainer.value,
267
- venueId: newId,
268
- view: props.view,
269
- events: [],
270
- showViewOptions: true,
271
- showMonthSwitcher: true,
272
- });
273
- }
274
- });
275
- </script>
276
- ```
277
-
278
- ### Svelte
279
-
280
- ```svelte
281
- <script>
282
- import { VenueCalendar } from '@getmicdrop/venue-calendar';
283
- import { Calendar, Grid, List } from 'carbon-icons-svelte';
284
- import { writable } from 'svelte/store';
285
-
286
- let venueId = 'your-venue-id';
287
- let currentMonth = writable(new Date().getUTCMonth());
288
- let currentYear = writable(new Date().getUTCFullYear());
289
-
290
- function handleNext() {
291
- currentMonth.update(m => m + 1);
292
- }
293
-
294
- function handlePrev() {
295
- currentMonth.update(m => m - 1);
296
- }
297
- </script>
298
-
299
- <VenueCalendar
300
- showViewOptions={[
301
- { id: 0, text: "List view", icon: List },
302
- { id: 1, text: "Gallery view", icon: Grid },
303
- { id: 2, text: "Calendar view", icon: Calendar }
304
- ]}
305
- showMonthSwitcher={true}
306
- events={[]}
307
- {currentMonth}
308
- {currentYear}
309
- handleNext={handleNext}
310
- handlePrev={handlePrev}
311
- on:eventClick={(e) => console.log('Event clicked:', e.detail)}
312
- />
313
- ```
314
-
315
- ### Angular
316
-
317
- ```typescript
318
- import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
319
- import { initVenueCalendar } from '@getmicdrop/venue-calendar';
320
-
321
- @Component({
322
- selector: 'app-venue-calendar',
323
- template: '<div #calendarContainer></div>',
324
- })
325
- export class VenueCalendarComponent implements OnInit, OnDestroy {
326
- @ViewChild('calendarContainer', { static: true }) calendarContainer!: ElementRef;
327
- private calendarInstance: any;
328
-
329
- ngOnInit() {
330
- this.calendarInstance = initVenueCalendar({
331
- target: this.calendarContainer.nativeElement,
332
- venueId: 'your-venue-id',
333
- view: 'calendar',
334
- events: [],
335
- showViewOptions: true,
336
- showMonthSwitcher: true,
337
- });
338
- }
339
-
340
- ngOnDestroy() {
341
- if (this.calendarInstance && this.calendarInstance.$destroy) {
342
- this.calendarInstance.$destroy();
343
- }
344
- }
345
- }
346
- ```
347
-
348
- ## Configuration Options
349
-
350
- ### Data Attributes (for auto-mount)
351
-
352
- | Attribute | Type | Default | Description |
353
- |-----------|------|---------|-------------|
354
- | `data-venue-id` | string | `''` | The venue ID to fetch events for |
355
- | `data-view` | string | `'calendar'` | Initial view: `'list'`, `'gallery'`, or `'calendar'` |
356
- | `data-show-view-options` | boolean | `true` | Show view switcher buttons |
357
- | `data-show-month-switcher` | boolean | `true` | Show month navigation controls |
358
-
359
- ### JavaScript API Options
360
-
361
- ```javascript
362
- initVenueCalendar({
363
- target: '.my-calendar', // CSS selector or HTMLElement (required)
364
- venueId: 'venue-123', // Venue ID (optional)
365
- view: 'calendar', // 'list', 'gallery', or 'calendar' (default: 'calendar')
366
- events: [], // Array of event objects (default: [])
367
- showViewOptions: true, // Show view switcher (default: true)
368
- showMonthSwitcher: true, // Show month navigation (default: true)
369
- });
370
- ```
371
-
372
- ### Event Object Structure
373
-
374
- ```javascript
375
- {
376
- id: 'event-123',
377
- name: 'Comedy Night',
378
- date: '2024-10-25T20:00:00Z',
379
- image: 'https://example.com/image.jpg',
380
- status: 'On Sale',
381
- timeline: '8:00 PM - 10:00 PM',
382
- // ... other fields
383
- }
384
- ```
385
-
386
- ## Views
387
-
388
- ### Calendar View
389
- The default view showing events in a monthly calendar grid. Perfect for venues with regular shows.
390
-
391
- ### List View
392
- A vertical list layout showing all upcoming events with details. Great for mobile experiences.
393
-
394
- ### Gallery View
395
- A grid layout displaying event posters in a gallery format. Ideal for showcasing event imagery.
396
-
397
- ## WordPress Integration
398
-
399
- For WordPress sites, you can add this to your page/post HTML:
400
-
401
- ```html
402
- <div class="micdrop-calendar-container"
403
- data-venue-id="your-venue-id"
404
- data-view="calendar">
405
- </div>
406
-
407
- <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
408
- ```
409
-
410
- Or add the script to your theme's footer and use the div anywhere in your content.
411
-
412
- ## Styling
413
-
414
- 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.
415
-
416
- ```css
417
- /* Example: Custom styling */
418
- .micdrop-calendar-container {
419
- max-width: 1200px;
420
- margin: 0 auto;
421
- padding: 20px;
422
- }
423
- ```
424
-
425
- ## Theming
426
-
427
- The calendar supports comprehensive theming via CSS custom properties and JavaScript utilities.
428
-
429
- ### Using CSS Custom Properties
430
-
431
- Override the default theme by setting CSS custom properties:
432
-
433
- ```css
434
- /* Custom brand colors */
435
- .micdrop-calendar-container {
436
- --Brand-Primary: 270 76% 60%; /* Purple */
437
- --Text-Primary: 0 0% 10%;
438
- --BG-Primary: 0 0% 100%;
439
- }
440
-
441
- /* Dark mode */
442
- .dark .micdrop-calendar-container,
443
- [data-theme="dark"] .micdrop-calendar-container {
444
- --Brand-Primary: 270 76% 70%;
445
- --Text-Primary: 0 0% 95%;
446
- --BG-Primary: 0 0% 10%;
447
- }
448
- ```
449
-
450
- ### Available CSS Variables
451
-
452
- | Variable | Description | Default (Light) |
453
- |----------|-------------|-----------------|
454
- | `--Brand-Primary` | Primary brand color | `217 91% 60%` (Blue) |
455
- | `--Text-Primary` | Main text color | `0 0% 0%` |
456
- | `--Text-Secondary` | Secondary text | `0 0% 40%` |
457
- | `--BG-Primary` | Main background | `0 0% 100%` |
458
- | `--BG-Secondary` | Secondary background | `0 0% 98%` |
459
- | `--Stroke-Primary` | Border colors | `0 0% 80%` |
460
- | `--Status-OnSale` | "On Sale" badge | `217 91% 60%` |
461
- | `--Status-SellingFast` | "Selling Fast" badge | `38 92% 50%` |
462
- | `--Status-SoldOut` | "Sold Out" badge | `0 84% 60%` |
463
- | `--Today-BG` | Today's date background | `217 91% 97%` |
464
- | `--Focus-Ring` | Keyboard focus ring | `217 91% 60%` |
465
-
466
- ### Using JavaScript Theme Utilities
467
-
468
- ```javascript
469
- import { applyTheme, themes, generateThemeCSS } from '@getmicdrop/venue-calendar';
470
-
471
- // Apply a preset theme
472
- applyTheme(themes.dark);
473
-
474
- // Apply to a specific container
475
- const container = document.querySelector('.micdrop-calendar-container');
476
- applyTheme(themes.dark, container);
477
-
478
- // Create a custom theme
479
- const myTheme = {
480
- brandPrimary: '270 76% 60%', // Purple
481
- textPrimary: '0 0% 10%',
482
- bgPrimary: '0 0% 100%',
483
- statusOnSale: '142 71% 45%', // Green for on sale
484
- };
485
- applyTheme(myTheme);
486
-
487
- // Generate CSS string for embedding
488
- const cssString = generateThemeCSS(myTheme);
489
- console.log(cssString);
490
- // Output: :root { --Brand-Primary: 270 76% 60%; ... }
491
- ```
492
-
493
- ### Preset Themes
494
-
495
- Three themes are included out of the box:
496
-
497
- ```javascript
498
- import { themes } from '@getmicdrop/venue-calendar';
499
-
500
- // Light theme (default)
501
- applyTheme(themes.light);
502
-
503
- // Dark theme
504
- applyTheme(themes.dark);
505
-
506
- // High contrast (accessibility)
507
- applyTheme(themes.highContrast);
508
- ```
509
-
510
- ### Automatic Dark Mode
511
-
512
- The calendar automatically respects the user's system preference:
513
-
514
- ```css
515
- /* Automatically applied when user prefers dark mode */
516
- @media (prefers-color-scheme: dark) {
517
- /* Dark theme variables are applied */
518
- }
519
- ```
520
-
521
- You can also manually toggle dark mode:
522
-
523
- ```html
524
- <!-- Add 'dark' class to enable dark theme -->
525
- <div class="dark">
526
- <div class="micdrop-calendar-container" data-venue-id="123"></div>
527
- </div>
528
-
529
- <!-- Or use data-theme attribute -->
530
- <div data-theme="dark">
531
- <div class="micdrop-calendar-container" data-venue-id="123"></div>
532
- </div>
533
- ```
534
-
535
- ## Browser Support
536
-
537
- - Chrome (latest)
538
- - Firefox (latest)
539
- - Safari (latest)
540
- - Edge (latest)
541
- - Mobile browsers (iOS Safari, Chrome Mobile)
542
-
543
- ## Development
544
-
545
- ### Building the Package
546
-
547
- ```bash
548
- # Install dependencies
549
- npm install
550
-
551
- # Build the library
552
- npm run build:lib
553
-
554
- # Development mode (SvelteKit app)
555
- npm run dev
556
-
557
- # Preview production build
558
- npm run preview
559
- ```
560
-
561
- ### Project Structure
562
-
563
- ```
564
- venue-calendar/
565
- ├── src/
566
- │ ├── components/ # Svelte components
567
- │ │ ├── Calendar/
568
- │ │ ├── CalendarContainer/
569
- │ │ └── Button/
570
- │ ├── lib/ # Library entry points
571
- │ │ ├── VenueCalendar.js
572
- │ │ └── web-component.js
573
- │ └── routes/ # SvelteKit routes (for dev)
574
- ├── dist/ # Built package (generated)
575
- ├── package.json
576
- ├── vite.config.lib.js # Library build config
577
- └── README.md
578
- ```
579
-
580
- ## API Reference
581
-
582
- ### `initVenueCalendar(options)`
583
-
584
- Initialize a calendar instance.
585
-
586
- **Parameters:**
587
- - `options` (Object): Configuration options
588
-
589
- **Returns:** Svelte component instance
590
-
591
- **Example:**
592
- ```javascript
593
- const calendar = initVenueCalendar({
594
- target: '#calendar',
595
- venueId: 'venue-123',
596
- view: 'calendar',
597
- });
598
- ```
599
-
600
- ### `autoMount()`
601
-
602
- Automatically mount calendars to all elements with class `micdrop-calendar-container`.
603
-
604
- **Example:**
605
- ```javascript
606
- import { autoMount } from '@getmicdrop/venue-calendar';
607
- autoMount();
608
- ```
609
-
610
- ### Component Events
611
-
612
- The calendar component emits events that you can listen to:
613
-
614
- ```javascript
615
- const calendar = initVenueCalendar({
616
- target: '#calendar',
617
- // ... other options
618
- });
619
-
620
- // Listen to component events (if using Svelte component directly)
621
- calendar.$on('eventClick', (event) => {
622
- console.log('Event clicked:', event.detail);
623
- });
624
- ```
625
-
626
- ## Troubleshooting
627
-
628
- ### Calendar not appearing
629
-
630
- 1. **Check the script is loaded**: Open browser console and verify no errors
631
- 2. **Verify container exists**: Make sure the target element exists in the DOM
632
- 3. **Check data attributes**: Ensure attributes are correctly formatted with `data-` prefix
633
-
634
- ### Styles not applying
635
-
636
- 1. **CSS not loaded**: The styles are bundled in the JS file and auto-injected
637
- 2. **CSS conflicts**: Check if other styles are overriding the calendar styles
638
- 3. **CDN issues**: Try using a specific version instead of `@latest`
639
-
640
- ### Events not showing
641
-
642
- 1. **Check event data format**: Ensure events match the expected structure
643
- 2. **Date format**: Use ISO 8601 format for dates (`YYYY-MM-DDTHH:mm:ssZ`)
644
- 3. **Venue ID**: Verify the venue ID is correct
645
-
646
- ## Contributing
647
-
648
- Contributions are welcome! Please feel free to submit a Pull Request.
649
-
650
- ## License
651
-
652
- MIT © MicDrop
653
-
654
- ## Support
655
-
656
- For issues, questions, or feature requests, please visit:
657
- https://github.com/get-micdrop/venue-calendar/issues
658
-
659
- ---
660
-
661
- Made with ❤️ by the MicDrop team
1
+ # @getmicdrop/venue-calendar
2
+
3
+ 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.
4
+
5
+ ## Features
6
+
7
+ ✨ **Three View Modes**: List, Gallery, and Calendar views
8
+ 🎨 **Beautiful UI**: Modern, responsive design built with Tailwind CSS
9
+ 📱 **Mobile-Friendly**: Swipe gestures, touch-optimized, responsive design
10
+ 🔌 **Easy Integration**: Works with React, Vue, vanilla JS, and more
11
+ 🌐 **CDN Ready**: Use directly in HTML via JSDelivr
12
+ ⚡ **Auto-Mount**: Automatically finds and mounts to designated containers
13
+ 🎯 **Customizable**: Configure views, navigation, and more
14
+ 🌙 **Dark Mode**: Built-in light, dark, and high-contrast themes
15
+ ♿ **Accessible**: ARIA labels, keyboard navigation, screen reader support
16
+ 🎫 **Event Status**: Visual badges for "On Sale", "Selling Fast", "Sold Out"
17
+
18
+ ## Installation
19
+
20
+ ### NPM/Yarn
21
+
22
+ ```bash
23
+ npm install @getmicdrop/venue-calendar
24
+ ```
25
+
26
+ or
27
+
28
+ ```bash
29
+ yarn add @getmicdrop/venue-calendar
30
+ ```
31
+
32
+ ### CDN (JSDelivr)
33
+
34
+ ```html
35
+ <!-- Latest version -->
36
+ <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
37
+
38
+ <!-- Specific version (recommended for production) -->
39
+ <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar@1.3.0/dist/venue-calendar.iife.js"></script>
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ### Method 1: Auto-Mount (Easiest)
45
+
46
+ Simply add a div with the class `micdrop-calendar-container` and the calendar will automatically mount:
47
+
48
+ ```html
49
+ <!DOCTYPE html>
50
+ <html>
51
+ <head>
52
+ <title>My Comedy Club</title>
53
+ </head>
54
+ <body>
55
+ <!-- Calendar will auto-mount here -->
56
+ <div class="micdrop-calendar-container"
57
+ data-venue-id="your-venue-id"
58
+ data-view="calendar"
59
+ data-show-view-options="true"
60
+ data-show-month-switcher="true">
61
+ </div>
62
+
63
+ <!-- Load the script -->
64
+ <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
65
+ </body>
66
+ </html>
67
+ ```
68
+
69
+ ### Method 2: Web Component
70
+
71
+ Use the custom `<micdrop-calendar>` element:
72
+
73
+ ```html
74
+ <!DOCTYPE html>
75
+ <html>
76
+ <head>
77
+ <title>My Comedy Club</title>
78
+ </head>
79
+ <body>
80
+ <!-- Web Component -->
81
+ <micdrop-calendar
82
+ venue-id="your-venue-id"
83
+ view="calendar"
84
+ show-view-options="true"
85
+ show-month-switcher="true">
86
+ </micdrop-calendar>
87
+
88
+ <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
89
+ </body>
90
+ </html>
91
+ ```
92
+
93
+ ### Method 3: JavaScript API
94
+
95
+ For more control, use the JavaScript API:
96
+
97
+ ```html
98
+ <!DOCTYPE html>
99
+ <html>
100
+ <head>
101
+ <title>My Comedy Club</title>
102
+ </head>
103
+ <body>
104
+ <div id="my-calendar"></div>
105
+
106
+ <script type="module">
107
+ import { initVenueCalendar } from 'https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.es.js';
108
+
109
+ initVenueCalendar({
110
+ target: '#my-calendar',
111
+ venueId: 'your-venue-id',
112
+ view: 'calendar',
113
+ events: [],
114
+ showViewOptions: true,
115
+ showMonthSwitcher: true,
116
+ });
117
+ </script>
118
+ </body>
119
+ </html>
120
+ ```
121
+
122
+ ## Framework Integration
123
+
124
+ ### React
125
+
126
+ ```jsx
127
+ import React, { useEffect, useRef } from 'react';
128
+ import { initVenueCalendar } from '@getmicdrop/venue-calendar';
129
+
130
+ function VenueCalendarComponent({ venueId, view = 'calendar' }) {
131
+ const calendarRef = useRef(null);
132
+ const instanceRef = useRef(null);
133
+
134
+ useEffect(() => {
135
+ if (calendarRef.current) {
136
+ // Initialize calendar
137
+ instanceRef.current = initVenueCalendar({
138
+ target: calendarRef.current,
139
+ venueId,
140
+ view,
141
+ events: [],
142
+ showViewOptions: true,
143
+ showMonthSwitcher: true,
144
+ });
145
+ }
146
+
147
+ // Cleanup on unmount
148
+ return () => {
149
+ if (instanceRef.current && instanceRef.current.$destroy) {
150
+ instanceRef.current.$destroy();
151
+ }
152
+ };
153
+ }, [venueId, view]);
154
+
155
+ return <div ref={calendarRef}></div>;
156
+ }
157
+
158
+ export default VenueCalendarComponent;
159
+ ```
160
+
161
+ **Usage in React App:**
162
+
163
+ ```jsx
164
+ import React, { useState } from "react";
165
+ import VenueCalendarComponent from "./VenueCalendarComponent";
166
+
167
+ function App() {
168
+ const [venueId, setVenueId] = useState("comedy-club-123");
169
+ const [view, setView] = useState("calendar");
170
+
171
+ return (
172
+ <div style={{ padding: "20px" }}>
173
+ <h1>Event Viewer</h1>
174
+
175
+ <div style={{ marginBottom: "20px" }}>
176
+ <label>Venue ID:</label>
177
+ <input
178
+ type="text"
179
+ value={venueId}
180
+ onChange={(e) => setVenueId(e.target.value)}
181
+ />
182
+ </div>
183
+
184
+ <div style={{ marginBottom: "20px" }}>
185
+ <label>Select View:</label>
186
+ <label>
187
+ <input
188
+ type="radio"
189
+ value="list"
190
+ checked={view === "list"}
191
+ onChange={(e) => setView(e.target.value)}
192
+ />
193
+ List
194
+ </label>
195
+ <label>
196
+ <input
197
+ type="radio"
198
+ value="gallery"
199
+ checked={view === "gallery"}
200
+ onChange={(e) => setView(e.target.value)}
201
+ />
202
+ Gallery
203
+ </label>
204
+ <label>
205
+ <input
206
+ type="radio"
207
+ value="calendar"
208
+ checked={view === "calendar"}
209
+ onChange={(e) => setView(e.target.value)}
210
+ />
211
+ Calendar
212
+ </label>
213
+ </div>
214
+
215
+ <VenueCalendarComponent venueId={venueId} view={view} />
216
+ </div>
217
+ );
218
+ }
219
+
220
+ export default App;
221
+ ```
222
+
223
+ ### Vue 3
224
+
225
+ ```vue
226
+ <template>
227
+ <div ref="calendarContainer"></div>
228
+ </template>
229
+
230
+ <script setup>
231
+ import { ref, onMounted, onUnmounted, watch } from 'vue';
232
+ import { initVenueCalendar } from '@getmicdrop/venue-calendar';
233
+
234
+ const props = defineProps({
235
+ venueId: String,
236
+ view: {
237
+ type: String,
238
+ default: 'calendar'
239
+ }
240
+ });
241
+
242
+ const calendarContainer = ref(null);
243
+ let calendarInstance = null;
244
+
245
+ onMounted(() => {
246
+ calendarInstance = initVenueCalendar({
247
+ target: calendarContainer.value,
248
+ venueId: props.venueId,
249
+ view: props.view,
250
+ events: [],
251
+ showViewOptions: true,
252
+ showMonthSwitcher: true,
253
+ });
254
+ });
255
+
256
+ onUnmounted(() => {
257
+ if (calendarInstance && calendarInstance.$destroy) {
258
+ calendarInstance.$destroy();
259
+ }
260
+ });
261
+
262
+ watch(() => props.venueId, (newId) => {
263
+ if (calendarInstance) {
264
+ calendarInstance.$destroy();
265
+ calendarInstance = initVenueCalendar({
266
+ target: calendarContainer.value,
267
+ venueId: newId,
268
+ view: props.view,
269
+ events: [],
270
+ showViewOptions: true,
271
+ showMonthSwitcher: true,
272
+ });
273
+ }
274
+ });
275
+ </script>
276
+ ```
277
+
278
+ ### Svelte
279
+
280
+ ```svelte
281
+ <script>
282
+ import { VenueCalendar } from '@getmicdrop/venue-calendar';
283
+ import { Calendar, Grid, List } from 'carbon-icons-svelte';
284
+ import { writable } from 'svelte/store';
285
+
286
+ let venueId = 'your-venue-id';
287
+ let currentMonth = writable(new Date().getUTCMonth());
288
+ let currentYear = writable(new Date().getUTCFullYear());
289
+
290
+ function handleNext() {
291
+ currentMonth.update(m => m + 1);
292
+ }
293
+
294
+ function handlePrev() {
295
+ currentMonth.update(m => m - 1);
296
+ }
297
+ </script>
298
+
299
+ <VenueCalendar
300
+ showViewOptions={[
301
+ { id: 0, text: "List view", icon: List },
302
+ { id: 1, text: "Gallery view", icon: Grid },
303
+ { id: 2, text: "Calendar view", icon: Calendar }
304
+ ]}
305
+ showMonthSwitcher={true}
306
+ events={[]}
307
+ {currentMonth}
308
+ {currentYear}
309
+ handleNext={handleNext}
310
+ handlePrev={handlePrev}
311
+ on:eventClick={(e) => console.log('Event clicked:', e.detail)}
312
+ />
313
+ ```
314
+
315
+ ### Angular
316
+
317
+ ```typescript
318
+ import { Component, OnInit, OnDestroy, ElementRef, ViewChild } from '@angular/core';
319
+ import { initVenueCalendar } from '@getmicdrop/venue-calendar';
320
+
321
+ @Component({
322
+ selector: 'app-venue-calendar',
323
+ template: '<div #calendarContainer></div>',
324
+ })
325
+ export class VenueCalendarComponent implements OnInit, OnDestroy {
326
+ @ViewChild('calendarContainer', { static: true }) calendarContainer!: ElementRef;
327
+ private calendarInstance: any;
328
+
329
+ ngOnInit() {
330
+ this.calendarInstance = initVenueCalendar({
331
+ target: this.calendarContainer.nativeElement,
332
+ venueId: 'your-venue-id',
333
+ view: 'calendar',
334
+ events: [],
335
+ showViewOptions: true,
336
+ showMonthSwitcher: true,
337
+ });
338
+ }
339
+
340
+ ngOnDestroy() {
341
+ if (this.calendarInstance && this.calendarInstance.$destroy) {
342
+ this.calendarInstance.$destroy();
343
+ }
344
+ }
345
+ }
346
+ ```
347
+
348
+ ## Configuration Options
349
+
350
+ ### Data Attributes (for auto-mount)
351
+
352
+ | Attribute | Type | Default | Description |
353
+ |-----------|------|---------|-------------|
354
+ | `data-venue-id` | string | `''` | The venue ID to fetch events for |
355
+ | `data-view` | string | `'calendar'` | Initial view: `'list'`, `'gallery'`, or `'calendar'` |
356
+ | `data-show-view-options` | boolean | `true` | Show view switcher buttons |
357
+ | `data-show-month-switcher` | boolean | `true` | Show month navigation controls |
358
+
359
+ ### JavaScript API Options
360
+
361
+ ```javascript
362
+ initVenueCalendar({
363
+ target: '.my-calendar', // CSS selector or HTMLElement (required)
364
+ venueId: 'venue-123', // Venue ID (optional)
365
+ view: 'calendar', // 'list', 'gallery', or 'calendar' (default: 'calendar')
366
+ events: [], // Array of event objects (default: [])
367
+ showViewOptions: true, // Show view switcher (default: true)
368
+ showMonthSwitcher: true, // Show month navigation (default: true)
369
+ });
370
+ ```
371
+
372
+ ### Event Object Structure
373
+
374
+ ```javascript
375
+ {
376
+ id: 'event-123',
377
+ name: 'Comedy Night',
378
+ date: '2024-10-25T20:00:00Z',
379
+ image: 'https://example.com/image.jpg',
380
+ status: 'On Sale',
381
+ timeline: '8:00 PM - 10:00 PM',
382
+ // ... other fields
383
+ }
384
+ ```
385
+
386
+ ## Views
387
+
388
+ ### Calendar View
389
+ The default view showing events in a monthly calendar grid. Perfect for venues with regular shows.
390
+
391
+ ### List View
392
+ A vertical list layout showing all upcoming events with details. Great for mobile experiences.
393
+
394
+ ### Gallery View
395
+ A grid layout displaying event posters in a gallery format. Ideal for showcasing event imagery.
396
+
397
+ ## WordPress Integration
398
+
399
+ For WordPress sites, you can add this to your page/post HTML:
400
+
401
+ ```html
402
+ <div class="micdrop-calendar-container"
403
+ data-venue-id="your-venue-id"
404
+ data-view="calendar">
405
+ </div>
406
+
407
+ <script src="https://cdn.jsdelivr.net/npm/@getmicdrop/venue-calendar/dist/venue-calendar.iife.js"></script>
408
+ ```
409
+
410
+ Or add the script to your theme's footer and use the div anywhere in your content.
411
+
412
+ ## Styling
413
+
414
+ 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.
415
+
416
+ ```css
417
+ /* Example: Custom styling */
418
+ .micdrop-calendar-container {
419
+ max-width: 1200px;
420
+ margin: 0 auto;
421
+ padding: 20px;
422
+ }
423
+ ```
424
+
425
+ ## Theming
426
+
427
+ The calendar supports comprehensive theming via CSS custom properties and JavaScript utilities.
428
+
429
+ ### Using CSS Custom Properties
430
+
431
+ Override the default theme by setting CSS custom properties:
432
+
433
+ ```css
434
+ /* Custom brand colors */
435
+ .micdrop-calendar-container {
436
+ --Brand-Primary: 270 76% 60%; /* Purple */
437
+ --Text-Primary: 0 0% 10%;
438
+ --BG-Primary: 0 0% 100%;
439
+ }
440
+
441
+ /* Dark mode */
442
+ .dark .micdrop-calendar-container,
443
+ [data-theme="dark"] .micdrop-calendar-container {
444
+ --Brand-Primary: 270 76% 70%;
445
+ --Text-Primary: 0 0% 95%;
446
+ --BG-Primary: 0 0% 10%;
447
+ }
448
+ ```
449
+
450
+ ### Available CSS Variables
451
+
452
+ | Variable | Description | Default (Light) |
453
+ |----------|-------------|-----------------|
454
+ | `--Brand-Primary` | Primary brand color | `217 91% 60%` (Blue) |
455
+ | `--Text-Primary` | Main text color | `0 0% 0%` |
456
+ | `--Text-Secondary` | Secondary text | `0 0% 40%` |
457
+ | `--BG-Primary` | Main background | `0 0% 100%` |
458
+ | `--BG-Secondary` | Secondary background | `0 0% 98%` |
459
+ | `--Stroke-Primary` | Border colors | `0 0% 80%` |
460
+ | `--Status-OnSale` | "On Sale" badge | `217 91% 60%` |
461
+ | `--Status-SellingFast` | "Selling Fast" badge | `38 92% 50%` |
462
+ | `--Status-SoldOut` | "Sold Out" badge | `0 84% 60%` |
463
+ | `--Today-BG` | Today's date background | `217 91% 97%` |
464
+ | `--Focus-Ring` | Keyboard focus ring | `217 91% 60%` |
465
+
466
+ ### Using JavaScript Theme Utilities
467
+
468
+ ```javascript
469
+ import { applyTheme, themes, generateThemeCSS } from '@getmicdrop/venue-calendar';
470
+
471
+ // Apply a preset theme
472
+ applyTheme(themes.dark);
473
+
474
+ // Apply to a specific container
475
+ const container = document.querySelector('.micdrop-calendar-container');
476
+ applyTheme(themes.dark, container);
477
+
478
+ // Create a custom theme
479
+ const myTheme = {
480
+ brandPrimary: '270 76% 60%', // Purple
481
+ textPrimary: '0 0% 10%',
482
+ bgPrimary: '0 0% 100%',
483
+ statusOnSale: '142 71% 45%', // Green for on sale
484
+ };
485
+ applyTheme(myTheme);
486
+
487
+ // Generate CSS string for embedding
488
+ const cssString = generateThemeCSS(myTheme);
489
+ console.log(cssString);
490
+ // Output: :root { --Brand-Primary: 270 76% 60%; ... }
491
+ ```
492
+
493
+ ### Preset Themes
494
+
495
+ Three themes are included out of the box:
496
+
497
+ ```javascript
498
+ import { themes } from '@getmicdrop/venue-calendar';
499
+
500
+ // Light theme (default)
501
+ applyTheme(themes.light);
502
+
503
+ // Dark theme
504
+ applyTheme(themes.dark);
505
+
506
+ // High contrast (accessibility)
507
+ applyTheme(themes.highContrast);
508
+ ```
509
+
510
+ ### Automatic Dark Mode
511
+
512
+ The calendar automatically respects the user's system preference:
513
+
514
+ ```css
515
+ /* Automatically applied when user prefers dark mode */
516
+ @media (prefers-color-scheme: dark) {
517
+ /* Dark theme variables are applied */
518
+ }
519
+ ```
520
+
521
+ You can also manually toggle dark mode:
522
+
523
+ ```html
524
+ <!-- Add 'dark' class to enable dark theme -->
525
+ <div class="dark">
526
+ <div class="micdrop-calendar-container" data-venue-id="123"></div>
527
+ </div>
528
+
529
+ <!-- Or use data-theme attribute -->
530
+ <div data-theme="dark">
531
+ <div class="micdrop-calendar-container" data-venue-id="123"></div>
532
+ </div>
533
+ ```
534
+
535
+ ## Browser Support
536
+
537
+ - Chrome (latest)
538
+ - Firefox (latest)
539
+ - Safari (latest)
540
+ - Edge (latest)
541
+ - Mobile browsers (iOS Safari, Chrome Mobile)
542
+
543
+ ## Development
544
+
545
+ ### Building the Package
546
+
547
+ ```bash
548
+ # Install dependencies
549
+ npm install
550
+
551
+ # Build the library
552
+ npm run build:lib
553
+
554
+ # Development mode (SvelteKit app)
555
+ npm run dev
556
+
557
+ # Preview production build
558
+ npm run preview
559
+ ```
560
+
561
+ ### Project Structure
562
+
563
+ ```
564
+ venue-calendar/
565
+ ├── src/
566
+ │ ├── components/ # Svelte components
567
+ │ │ ├── Calendar/
568
+ │ │ ├── CalendarContainer/
569
+ │ │ └── Button/
570
+ │ ├── lib/ # Library entry points
571
+ │ │ ├── VenueCalendar.js
572
+ │ │ └── web-component.js
573
+ │ └── routes/ # SvelteKit routes (for dev)
574
+ ├── dist/ # Built package (generated)
575
+ ├── package.json
576
+ ├── vite.config.lib.js # Library build config
577
+ └── README.md
578
+ ```
579
+
580
+ ## API Reference
581
+
582
+ ### `initVenueCalendar(options)`
583
+
584
+ Initialize a calendar instance.
585
+
586
+ **Parameters:**
587
+ - `options` (Object): Configuration options
588
+
589
+ **Returns:** Svelte component instance
590
+
591
+ **Example:**
592
+ ```javascript
593
+ const calendar = initVenueCalendar({
594
+ target: '#calendar',
595
+ venueId: 'venue-123',
596
+ view: 'calendar',
597
+ });
598
+ ```
599
+
600
+ ### `autoMount()`
601
+
602
+ Automatically mount calendars to all elements with class `micdrop-calendar-container`.
603
+
604
+ **Example:**
605
+ ```javascript
606
+ import { autoMount } from '@getmicdrop/venue-calendar';
607
+ autoMount();
608
+ ```
609
+
610
+ ### Component Events
611
+
612
+ The calendar component emits events that you can listen to:
613
+
614
+ ```javascript
615
+ const calendar = initVenueCalendar({
616
+ target: '#calendar',
617
+ // ... other options
618
+ });
619
+
620
+ // Listen to component events (if using Svelte component directly)
621
+ calendar.$on('eventClick', (event) => {
622
+ console.log('Event clicked:', event.detail);
623
+ });
624
+ ```
625
+
626
+ ## Troubleshooting
627
+
628
+ ### Calendar not appearing
629
+
630
+ 1. **Check the script is loaded**: Open browser console and verify no errors
631
+ 2. **Verify container exists**: Make sure the target element exists in the DOM
632
+ 3. **Check data attributes**: Ensure attributes are correctly formatted with `data-` prefix
633
+
634
+ ### Styles not applying
635
+
636
+ 1. **CSS not loaded**: The styles are bundled in the JS file and auto-injected
637
+ 2. **CSS conflicts**: Check if other styles are overriding the calendar styles
638
+ 3. **CDN issues**: Try using a specific version instead of `@latest`
639
+
640
+ ### Events not showing
641
+
642
+ 1. **Check event data format**: Ensure events match the expected structure
643
+ 2. **Date format**: Use ISO 8601 format for dates (`YYYY-MM-DDTHH:mm:ssZ`)
644
+ 3. **Venue ID**: Verify the venue ID is correct
645
+
646
+ ## Contributing
647
+
648
+ Contributions are welcome! Please feel free to submit a Pull Request.
649
+
650
+ ## License
651
+
652
+ MIT © MicDrop
653
+
654
+ ## Support
655
+
656
+ For issues, questions, or feature requests, please visit:
657
+ https://github.com/get-micdrop/venue-calendar/issues
658
+
659
+ ---
660
+
661
+ Made with ❤️ by the MicDrop team