@getmicdrop/venue-calendar 4.0.86 → 4.0.87

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.
Files changed (69) hide show
  1. package/README.md +740 -740
  2. package/dist/{CartView-e2hG7cOV.js → CartView-DrfUvXHU.js} +370 -370
  3. package/dist/CartView-DrfUvXHU.js.map +1 -0
  4. package/dist/{Checkout-DmnOMwhl.js → Checkout-BIT0aula.js} +3 -3
  5. package/dist/Checkout-BIT0aula.js.map +1 -0
  6. package/dist/{Checkout-BpTUMyLk.js → Checkout-DNwBnmE3.js} +51 -51
  7. package/dist/Checkout-DNwBnmE3.js.map +1 -0
  8. package/dist/{CheckoutTimer-Dv0c-X6O.js → CheckoutTimer-C50Ahi93.js} +4 -4
  9. package/dist/CheckoutTimer-C50Ahi93.js.map +1 -0
  10. package/dist/{CollectionView-CyxK6aI9.js → CollectionView-W4Atllhp.js} +5 -5
  11. package/dist/CollectionView-W4Atllhp.js.map +1 -0
  12. package/dist/{Event-Cw7b9UEd.js → Event-t3hhfFuJ.js} +10 -7
  13. package/dist/{Event-Cw7b9UEd.js.map → Event-t3hhfFuJ.js.map} +1 -1
  14. package/dist/{EventPage-BKtFiZL1.js → EventPage-CEWppTrK.js} +7 -7
  15. package/dist/EventPage-CEWppTrK.js.map +1 -0
  16. package/dist/Heading-DUg5tgzm.js +91 -0
  17. package/dist/Heading-DUg5tgzm.js.map +1 -0
  18. package/dist/{ModalHeader-V5AlK1dt.js → ModalHeader-DEuHuPK2.js} +2 -2
  19. package/dist/{ModalHeader-V5AlK1dt.js.map → ModalHeader-DEuHuPK2.js.map} +1 -1
  20. package/dist/{ScarcityBadge-Co7gZXuW.js → ScarcityBadge-BVM_XAXR.js} +2 -2
  21. package/dist/ScarcityBadge-BVM_XAXR.js.map +1 -0
  22. package/dist/{SeriesPage-USYe3APQ.js → SeriesPage-Bg4oZ2fA.js} +5 -5
  23. package/dist/SeriesPage-Bg4oZ2fA.js.map +1 -0
  24. package/dist/{Success-C387RvIY.js → Success-DwpMMfeZ.js} +19 -19
  25. package/dist/Success-DwpMMfeZ.js.map +1 -0
  26. package/dist/Text-D4lbf8Z6.js +167 -0
  27. package/dist/{Text-ZUPglf_o.js.map → Text-D4lbf8Z6.js.map} +1 -1
  28. package/dist/{VenueCalendar-tmWZSmhT.js → VenueCalendar-DYnha5wZ.js} +97 -100
  29. package/dist/VenueCalendar-DYnha5wZ.js.map +1 -0
  30. package/dist/{ViewTicketsEmbed--091XJJn.js → ViewTicketsEmbed-mrawQhqD.js} +382 -382
  31. package/dist/ViewTicketsEmbed-mrawQhqD.js.map +1 -0
  32. package/dist/api/api.cjs.map +1 -1
  33. package/dist/api/api.mjs +21 -21
  34. package/dist/api/api.mjs.map +1 -1
  35. package/dist/api/transformers/venue.d.ts +17 -7
  36. package/dist/{data-toggle-store.svelte-Bn0h8FT_.js → data-toggle-store.svelte-CgH3EfQF.js} +2 -2
  37. package/dist/data-toggle-store.svelte-CgH3EfQF.js.map +1 -0
  38. package/dist/{labels-C7Znep_T.js → labels-CV4Mq9xD.js} +3 -3
  39. package/dist/labels-CV4Mq9xD.js.map +1 -0
  40. package/dist/seo/seo.cjs.map +1 -1
  41. package/dist/seo/seo.mjs.map +1 -1
  42. package/dist/{transform-BxgTZDAD.js → transform-DrAudcCa.js} +2 -2
  43. package/dist/transform-DrAudcCa.js.map +1 -0
  44. package/dist/types/index.d.ts +442 -442
  45. package/dist/venue-calendar.css +1 -1
  46. package/dist/venue-calendar.es.js +2 -2
  47. package/dist/venue-calendar.iife.js +21 -21
  48. package/dist/venue-calendar.iife.js.map +1 -1
  49. package/dist/venue-calendar.umd.js +11 -11
  50. package/dist/venue-calendar.umd.js.map +1 -1
  51. package/package.json +2 -2
  52. package/src/lib/theme.js +222 -222
  53. package/dist/CartView-e2hG7cOV.js.map +0 -1
  54. package/dist/Checkout-BpTUMyLk.js.map +0 -1
  55. package/dist/Checkout-DmnOMwhl.js.map +0 -1
  56. package/dist/CheckoutTimer-Dv0c-X6O.js.map +0 -1
  57. package/dist/CollectionView-CyxK6aI9.js.map +0 -1
  58. package/dist/EventPage-BKtFiZL1.js.map +0 -1
  59. package/dist/Heading-D0grC8vd.js +0 -81
  60. package/dist/Heading-D0grC8vd.js.map +0 -1
  61. package/dist/ScarcityBadge-Co7gZXuW.js.map +0 -1
  62. package/dist/SeriesPage-USYe3APQ.js.map +0 -1
  63. package/dist/Success-C387RvIY.js.map +0 -1
  64. package/dist/Text-ZUPglf_o.js +0 -158
  65. package/dist/VenueCalendar-tmWZSmhT.js.map +0 -1
  66. package/dist/ViewTicketsEmbed--091XJJn.js.map +0 -1
  67. package/dist/data-toggle-store.svelte-Bn0h8FT_.js.map +0 -1
  68. package/dist/labels-C7Znep_T.js.map +0 -1
  69. package/dist/transform-BxgTZDAD.js.map +0 -1
package/README.md CHANGED
@@ -1,740 +1,740 @@
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
- 🌐 **One script tag**: Self-hosted bundle — paste one `<script>`, no build step
12
- 🎨 **Styles included**: The bundle injects its own CSS — no separate stylesheet to link
13
- ⚡ **Auto-Mount**: Automatically finds and mounts to designated containers
14
- 🎯 **Customizable**: Configure views, navigation, and more
15
- 🌙 **Dark Mode**: Built-in light, dark, and high-contrast themes
16
- ♿ **Accessible**: ARIA labels, keyboard navigation, screen reader support
17
- 🎫 **Event Status**: Visual badges for "On Sale", "Selling Fast", "Sold Out"
18
-
19
- ## Installation
20
-
21
- Add one `<script>` tag pointing at the Micdrop-hosted bundle. The package is
22
- private (not on npm/jsDelivr) — it is delivered from `get-micdrop.com`:
23
-
24
- ```html
25
- <script
26
- defer
27
- src="https://get-micdrop.com/embed/venue-calendar.iife.js"
28
- ></script>
29
- ```
30
-
31
- - **No stylesheet to link.** The bundle injects its own CSS at runtime, so a
32
- plain page with just this `<script>` renders fully styled.
33
- - **Use `defer`** (or `async`) so the bundle never blocks page parse. It is
34
- ~310 KB gzipped.
35
- - **Serve your page over HTTPS.** Checkout stores a `Secure` cart cookie, which
36
- Safari drops on non-secure (`http://`) pages.
37
-
38
- > **Heads-up:** the exact hosted URL is being finalized (Micdrop ticket
39
- > MIC-1130). Confirm the address with Micdrop before going live.
40
-
41
- > The `import { ... } from '@getmicdrop/venue-calendar'` examples further down
42
- > are for **Micdrop-internal apps** that build with a bundler and have registry
43
- > access to the private package. Public sites (comedy clubs, etc.) use the
44
- > `<script>` tag above — not `npm install`.
45
-
46
- ## Quick Start
47
-
48
- ### Method 1: Auto-Mount (Easiest)
49
-
50
- Simply add a div with the class `micdrop-calendar-container` and the calendar will automatically mount:
51
-
52
- ```html
53
- <!DOCTYPE html>
54
- <html>
55
- <head>
56
- <title>My Comedy Club</title>
57
- <!-- Preload the bundle while the page parses. defer keeps the
58
- <script> non-blocking; preload starts the fetch earlier. -->
59
- <link
60
- rel="preload"
61
- as="script"
62
- href="https://get-micdrop.com/embed/venue-calendar.iife.js"
63
- />
64
- <script
65
- defer
66
- src="https://get-micdrop.com/embed/venue-calendar.iife.js"
67
- ></script>
68
- </head>
69
- <body>
70
- <!-- Calendar auto-mounts here. Use data-organization-id to show all of an
71
- organization's shows, or data-venue-id for a single venue. -->
72
- <div
73
- class="micdrop-calendar-container"
74
- data-organization-id="your-organization-id"
75
- data-view="calendar"
76
- data-show-view-options="true"
77
- data-show-month-switcher="true"
78
- data-locale="en-US"
79
- ></div>
80
- </body>
81
- </html>
82
- ```
83
-
84
- ### Method 2: Web Component
85
-
86
- Use the custom `<micdrop-calendar>` element:
87
-
88
- ```html
89
- <!DOCTYPE html>
90
- <html>
91
- <head>
92
- <title>My Comedy Club</title>
93
- <script
94
- defer
95
- src="https://get-micdrop.com/embed/venue-calendar.iife.js"
96
- ></script>
97
- </head>
98
- <body>
99
- <!-- Web Component -->
100
- <micdrop-calendar
101
- venue-id="your-venue-id"
102
- view="calendar"
103
- show-view-options="true"
104
- show-month-switcher="true"
105
- locale="en-US"
106
- >
107
- </micdrop-calendar>
108
- </body>
109
- </html>
110
- ```
111
-
112
- ### Method 3: JavaScript API
113
-
114
- For more control, use the JavaScript API:
115
-
116
- ```html
117
- <!DOCTYPE html>
118
- <html>
119
- <head>
120
- <title>My Comedy Club</title>
121
- </head>
122
- <body>
123
- <div id="my-calendar"></div>
124
-
125
- <!-- Load the bundle, then call the global it exposes. -->
126
- <script
127
- defer
128
- src="https://get-micdrop.com/embed/venue-calendar.iife.js"
129
- ></script>
130
- <script>
131
- window.addEventListener('load', function () {
132
- window.VenueCalendar.initVenueCalendar({
133
- target: '#my-calendar',
134
- organizationId: 'your-organization-id',
135
- view: 'calendar',
136
- showViewOptions: true,
137
- showMonthSwitcher: true,
138
- });
139
- });
140
- </script>
141
- </body>
142
- </html>
143
- ```
144
-
145
- ## Framework Integration
146
-
147
- ### React
148
-
149
- ```jsx
150
- import React, { useEffect, useRef } from 'react';
151
- import { initVenueCalendar, unmount } from '@getmicdrop/venue-calendar';
152
-
153
- function VenueCalendarComponent({ venueId, view = 'calendar' }) {
154
- const calendarRef = useRef(null);
155
- const instanceRef = useRef(null);
156
-
157
- useEffect(() => {
158
- if (!calendarRef.current) return;
159
- instanceRef.current = initVenueCalendar({
160
- target: calendarRef.current,
161
- venueId,
162
- view,
163
- events: [],
164
- showViewOptions: true,
165
- showMonthSwitcher: true,
166
- });
167
-
168
- return () => {
169
- // Svelte 5 — components mounted via `mount()` are destroyed via
170
- // the `unmount` helper, not `.$destroy()` (that was Svelte 4).
171
- if (instanceRef.current) {
172
- try {
173
- unmount(instanceRef.current);
174
- } catch {}
175
- instanceRef.current = null;
176
- }
177
- };
178
- }, [venueId, view]);
179
-
180
- return <div ref={calendarRef}></div>;
181
- }
182
-
183
- export default VenueCalendarComponent;
184
- ```
185
-
186
- ### Error reporting and runtime config
187
-
188
- Wire any errors caught by the widget into your existing monitoring:
189
-
190
- ```js
191
- import { configureVenueCalendar } from '@getmicdrop/venue-calendar';
192
-
193
- configureVenueCalendar({
194
- onError: (err, { source }) => {
195
- Sentry.captureException(err, { tags: { source, micdrop: true } });
196
- },
197
- // Optional overrides for self-hosted backends or regional failover.
198
- // apiBaseUrl: 'https://api.eu.micdrop.com',
199
- // apiTimeout: 15000,
200
- // apiRetries: 2,
201
- });
202
- ```
203
-
204
- For ad-hoc support diagnostics, the widget exposes its version on
205
- `window`:
206
-
207
- ```js
208
- window.__MICDROP_CALENDAR__.version; // e.g. "3.6.23"
209
- ```
210
-
211
- **Usage in React App:**
212
-
213
- ```jsx
214
- import React, { useState } from 'react';
215
- import VenueCalendarComponent from './VenueCalendarComponent';
216
-
217
- function App() {
218
- const [venueId, setVenueId] = useState('comedy-club-123');
219
- const [view, setView] = useState('calendar');
220
-
221
- return (
222
- <div style={{ padding: '20px' }}>
223
- <h1>Event Viewer</h1>
224
-
225
- <div style={{ marginBottom: '20px' }}>
226
- <label>Venue ID:</label>
227
- <input
228
- type="text"
229
- value={venueId}
230
- onChange={e => setVenueId(e.target.value)}
231
- />
232
- </div>
233
-
234
- <div style={{ marginBottom: '20px' }}>
235
- <label>Select View:</label>
236
- <label>
237
- <input
238
- type="radio"
239
- value="list"
240
- checked={view === 'list'}
241
- onChange={e => setView(e.target.value)}
242
- />
243
- List
244
- </label>
245
- <label>
246
- <input
247
- type="radio"
248
- value="gallery"
249
- checked={view === 'gallery'}
250
- onChange={e => setView(e.target.value)}
251
- />
252
- Gallery
253
- </label>
254
- <label>
255
- <input
256
- type="radio"
257
- value="calendar"
258
- checked={view === 'calendar'}
259
- onChange={e => setView(e.target.value)}
260
- />
261
- Calendar
262
- </label>
263
- </div>
264
-
265
- <VenueCalendarComponent venueId={venueId} view={view} />
266
- </div>
267
- );
268
- }
269
-
270
- export default App;
271
- ```
272
-
273
- ### Vue 3
274
-
275
- ```vue
276
- <template>
277
- <div ref="calendarContainer"></div>
278
- </template>
279
-
280
- <script setup>
281
- import { ref, onMounted, onUnmounted, watch } from 'vue';
282
- import { initVenueCalendar } from '@getmicdrop/venue-calendar';
283
-
284
- const props = defineProps({
285
- venueId: String,
286
- view: {
287
- type: String,
288
- default: 'calendar',
289
- },
290
- });
291
-
292
- const calendarContainer = ref(null);
293
- let calendarInstance = null;
294
-
295
- onMounted(() => {
296
- calendarInstance = initVenueCalendar({
297
- target: calendarContainer.value,
298
- venueId: props.venueId,
299
- view: props.view,
300
- events: [],
301
- showViewOptions: true,
302
- showMonthSwitcher: true,
303
- });
304
- });
305
-
306
- onUnmounted(() => {
307
- if (calendarInstance && calendarInstance.$destroy) {
308
- calendarInstance.$destroy();
309
- }
310
- });
311
-
312
- watch(
313
- () => props.venueId,
314
- newId => {
315
- if (calendarInstance) {
316
- calendarInstance.$destroy();
317
- calendarInstance = initVenueCalendar({
318
- target: calendarContainer.value,
319
- venueId: newId,
320
- view: props.view,
321
- events: [],
322
- showViewOptions: true,
323
- showMonthSwitcher: true,
324
- });
325
- }
326
- }
327
- );
328
- </script>
329
- ```
330
-
331
- ### Svelte
332
-
333
- ```svelte
334
- <script>
335
- import { VenueCalendar } from '@getmicdrop/venue-calendar';
336
- import { Calendar, Grid, List } from 'carbon-icons-svelte';
337
- import { writable } from 'svelte/store';
338
-
339
- let venueId = 'your-venue-id';
340
- let currentMonth = writable(new Date().getUTCMonth());
341
- let currentYear = writable(new Date().getUTCFullYear());
342
-
343
- function handleNext() {
344
- currentMonth.update(m => m + 1);
345
- }
346
-
347
- function handlePrev() {
348
- currentMonth.update(m => m - 1);
349
- }
350
- </script>
351
-
352
- <VenueCalendar
353
- showViewOptions={[
354
- { id: 0, text: 'List view', icon: List },
355
- { id: 1, text: 'Gallery view', icon: Grid },
356
- { id: 2, text: 'Calendar view', icon: Calendar },
357
- ]}
358
- showMonthSwitcher={true}
359
- events={[]}
360
- {currentMonth}
361
- {currentYear}
362
- {handleNext}
363
- {handlePrev}
364
- on:eventClick={e => console.log('Event clicked:', e.detail)}
365
- />
366
- ```
367
-
368
- ### Angular
369
-
370
- ```typescript
371
- import {
372
- Component,
373
- OnInit,
374
- OnDestroy,
375
- ElementRef,
376
- ViewChild,
377
- } from '@angular/core';
378
- import { initVenueCalendar } from '@getmicdrop/venue-calendar';
379
-
380
- @Component({
381
- selector: 'app-venue-calendar',
382
- template: '<div #calendarContainer></div>',
383
- })
384
- export class VenueCalendarComponent implements OnInit, OnDestroy {
385
- @ViewChild('calendarContainer', { static: true })
386
- calendarContainer!: ElementRef;
387
- private calendarInstance: any;
388
-
389
- ngOnInit() {
390
- this.calendarInstance = initVenueCalendar({
391
- target: this.calendarContainer.nativeElement,
392
- venueId: 'your-venue-id',
393
- view: 'calendar',
394
- events: [],
395
- showViewOptions: true,
396
- showMonthSwitcher: true,
397
- });
398
- }
399
-
400
- ngOnDestroy() {
401
- if (this.calendarInstance && this.calendarInstance.$destroy) {
402
- this.calendarInstance.$destroy();
403
- }
404
- }
405
- }
406
- ```
407
-
408
- ## Configuration Options
409
-
410
- ### Data Attributes (for auto-mount)
411
-
412
- | Attribute | Type | Default | Description |
413
- | -------------------------- | ------- | ------------ | ---------------------------------------------------- |
414
- | `data-venue-id` | string | `''` | The venue ID to fetch events for |
415
- | `data-view` | string | `'calendar'` | Initial view: `'list'`, `'gallery'`, or `'calendar'` |
416
- | `data-show-view-options` | boolean | `true` | Show view switcher buttons |
417
- | `data-show-month-switcher` | boolean | `true` | Show month navigation controls |
418
-
419
- ### JavaScript API Options
420
-
421
- ```javascript
422
- initVenueCalendar({
423
- target: '.my-calendar', // CSS selector or HTMLElement (required)
424
- venueId: 'venue-123', // Venue ID (optional)
425
- view: 'calendar', // 'list', 'gallery', or 'calendar' (default: 'calendar')
426
- events: [], // Array of event objects (default: [])
427
- showViewOptions: true, // Show view switcher (default: true)
428
- showMonthSwitcher: true, // Show month navigation (default: true)
429
- });
430
- ```
431
-
432
- ### Event Object Structure
433
-
434
- ```javascript
435
- {
436
- id: 'event-123',
437
- name: 'Comedy Night',
438
- date: '2024-10-25T20:00:00Z',
439
- image: 'https://example.com/image.jpg',
440
- status: 'On Sale',
441
- timeline: '8:00 PM - 10:00 PM',
442
- // ... other fields
443
- }
444
- ```
445
-
446
- ## Views
447
-
448
- ### Calendar View
449
-
450
- The default view showing events in a monthly calendar grid. Perfect for venues with regular shows.
451
-
452
- ### List View
453
-
454
- A vertical list layout showing all upcoming events with details. Great for mobile experiences.
455
-
456
- ### Gallery View
457
-
458
- A grid layout displaying event posters in a gallery format. Ideal for showcasing event imagery.
459
-
460
- ## WordPress Integration
461
-
462
- For WordPress sites, you can add this to your page/post HTML:
463
-
464
- ```html
465
- <div
466
- class="micdrop-calendar-container"
467
- data-venue-id="your-venue-id"
468
- data-view="calendar"
469
- ></div>
470
-
471
- <script src="https://get-micdrop.com/embed/venue-calendar.iife.js"></script>
472
- ```
473
-
474
- Or add the script to your theme's footer and use the div anywhere in your content.
475
-
476
- ## Styling
477
-
478
- 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.
479
-
480
- ```css
481
- /* Example: Custom styling */
482
- .micdrop-calendar-container {
483
- max-width: 1200px;
484
- margin: 0 auto;
485
- padding: 20px;
486
- }
487
- ```
488
-
489
- ## Theming
490
-
491
- The calendar supports comprehensive theming via CSS custom properties and JavaScript utilities.
492
-
493
- ### Using CSS Custom Properties
494
-
495
- Override the default theme by setting CSS custom properties:
496
-
497
- ```css
498
- /* Custom brand colors */
499
- .micdrop-calendar-container {
500
- --Brand-Primary: 270 76% 60%; /* Purple */
501
- --Text-Primary: 0 0% 10%;
502
- --BG-Primary: 0 0% 100%;
503
- }
504
-
505
- /* Dark mode */
506
- .dark .micdrop-calendar-container,
507
- [data-theme='dark'] .micdrop-calendar-container {
508
- --Brand-Primary: 270 76% 70%;
509
- --Text-Primary: 0 0% 95%;
510
- --BG-Primary: 0 0% 10%;
511
- }
512
- ```
513
-
514
- ### Available CSS Variables
515
-
516
- | Variable | Description | Default (Light) |
517
- | ---------------------- | ----------------------- | -------------------- |
518
- | `--Brand-Primary` | Primary brand color | `217 91% 60%` (Blue) |
519
- | `--Text-Primary` | Main text color | `0 0% 0%` |
520
- | `--Text-Secondary` | Secondary text | `0 0% 40%` |
521
- | `--BG-Primary` | Main background | `0 0% 100%` |
522
- | `--BG-Secondary` | Secondary background | `0 0% 98%` |
523
- | `--Stroke-Primary` | Border colors | `0 0% 80%` |
524
- | `--Status-OnSale` | "On Sale" badge | `217 91% 60%` |
525
- | `--Status-SellingFast` | "Selling Fast" badge | `38 92% 50%` |
526
- | `--Status-SoldOut` | "Sold Out" badge | `0 84% 60%` |
527
- | `--Today-BG` | Today's date background | `217 91% 97%` |
528
- | `--Focus-Ring` | Keyboard focus ring | `217 91% 60%` |
529
-
530
- ### Using JavaScript Theme Utilities
531
-
532
- ```javascript
533
- import {
534
- applyTheme,
535
- themes,
536
- generateThemeCSS,
537
- } from '@getmicdrop/venue-calendar';
538
-
539
- // Apply a preset theme
540
- applyTheme(themes.dark);
541
-
542
- // Apply to a specific container
543
- const container = document.querySelector('.micdrop-calendar-container');
544
- applyTheme(themes.dark, container);
545
-
546
- // Create a custom theme
547
- const myTheme = {
548
- brandPrimary: '270 76% 60%', // Purple
549
- textPrimary: '0 0% 10%',
550
- bgPrimary: '0 0% 100%',
551
- statusOnSale: '142 71% 45%', // Green for on sale
552
- };
553
- applyTheme(myTheme);
554
-
555
- // Generate CSS string for embedding
556
- const cssString = generateThemeCSS(myTheme);
557
- console.log(cssString);
558
- // Output: :root { --Brand-Primary: 270 76% 60%; ... }
559
- ```
560
-
561
- ### Preset Themes
562
-
563
- Three themes are included out of the box:
564
-
565
- ```javascript
566
- import { themes } from '@getmicdrop/venue-calendar';
567
-
568
- // Light theme (default)
569
- applyTheme(themes.light);
570
-
571
- // Dark theme
572
- applyTheme(themes.dark);
573
-
574
- // High contrast (accessibility)
575
- applyTheme(themes.highContrast);
576
- ```
577
-
578
- ### Automatic Dark Mode
579
-
580
- The calendar automatically respects the user's system preference:
581
-
582
- ```css
583
- /* Automatically applied when user prefers dark mode */
584
- @media (prefers-color-scheme: dark) {
585
- /* Dark theme variables are applied */
586
- }
587
- ```
588
-
589
- You can also manually toggle dark mode:
590
-
591
- ```html
592
- <!-- Add 'dark' class to enable dark theme -->
593
- <div class="dark">
594
- <div class="micdrop-calendar-container" data-venue-id="123"></div>
595
- </div>
596
-
597
- <!-- Or use data-theme attribute -->
598
- <div data-theme="dark">
599
- <div class="micdrop-calendar-container" data-venue-id="123"></div>
600
- </div>
601
- ```
602
-
603
- ## Browser Support
604
-
605
- - Chrome (latest)
606
- - Firefox (latest)
607
- - Safari (latest)
608
- - Edge (latest)
609
- - Mobile browsers (iOS Safari, Chrome Mobile)
610
-
611
- ## Development
612
-
613
- ### Building the Package
614
-
615
- ```bash
616
- # Install dependencies
617
- npm install
618
-
619
- # Build the library
620
- npm run build:lib
621
-
622
- # Development mode (SvelteKit app)
623
- npm run dev
624
-
625
- # Preview production build
626
- npm run preview
627
- ```
628
-
629
- ### Project Structure
630
-
631
- ```
632
- venue-calendar/
633
- ├── src/
634
- │ ├── components/ # Svelte components
635
- │ │ ├── Calendar/
636
- │ │ ├── CalendarContainer/
637
- │ │ └── Button/
638
- │ ├── lib/ # Library entry points
639
- │ │ ├── VenueCalendar.js
640
- │ │ └── web-component.js
641
- │ └── routes/ # SvelteKit routes (for dev)
642
- ├── dist/ # Built package (generated)
643
- ├── package.json
644
- ├── vite.config.lib.js # Library build config
645
- └── README.md
646
- ```
647
-
648
- ### Lockfile policy
649
-
650
- `package-lock.json` is the single canonical lockfile — CI and the publish
651
- workflow install with `npm ci`. Do not commit `yarn.lock` or
652
- `pnpm-lock.yaml` (both gitignored). Local dev machines may use pnpm for the
653
- svelte-components symlink workflow, but dependency changes must land in
654
- `package-lock.json` via npm.
655
-
656
- ## API Reference
657
-
658
- ### `initVenueCalendar(options)`
659
-
660
- Initialize a calendar instance.
661
-
662
- **Parameters:**
663
-
664
- - `options` (Object): Configuration options
665
-
666
- **Returns:** Svelte component instance
667
-
668
- **Example:**
669
-
670
- ```javascript
671
- const calendar = initVenueCalendar({
672
- target: '#calendar',
673
- venueId: 'venue-123',
674
- view: 'calendar',
675
- });
676
- ```
677
-
678
- ### `autoMount()`
679
-
680
- Automatically mount calendars to all elements with class `micdrop-calendar-container`.
681
-
682
- **Example:**
683
-
684
- ```javascript
685
- import { autoMount } from '@getmicdrop/venue-calendar';
686
- autoMount();
687
- ```
688
-
689
- ### Component Events
690
-
691
- The calendar component emits events that you can listen to:
692
-
693
- ```javascript
694
- const calendar = initVenueCalendar({
695
- target: '#calendar',
696
- // ... other options
697
- });
698
-
699
- // Listen to component events (if using Svelte component directly)
700
- calendar.$on('eventClick', event => {
701
- console.log('Event clicked:', event.detail);
702
- });
703
- ```
704
-
705
- ## Troubleshooting
706
-
707
- ### Calendar not appearing
708
-
709
- 1. **Check the script is loaded**: Open browser console and verify no errors
710
- 2. **Verify container exists**: Make sure the target element exists in the DOM
711
- 3. **Check data attributes**: Ensure attributes are correctly formatted with `data-` prefix
712
-
713
- ### Styles not applying
714
-
715
- 1. **CSS not loaded**: The styles are bundled in the JS file and auto-injected — no separate stylesheet needed
716
- 2. **CSS conflicts**: Check if other styles are overriding the calendar styles
717
- 3. **Bundle didn't load**: Confirm the `<script src>` points at the Micdrop-hosted bundle and returns 200 (not 404)
718
-
719
- ### Events not showing
720
-
721
- 1. **Check event data format**: Ensure events match the expected structure
722
- 2. **Date format**: Use ISO 8601 format for dates (`YYYY-MM-DDTHH:mm:ssZ`)
723
- 3. **Venue ID**: Verify the venue ID is correct
724
-
725
- ## Contributing
726
-
727
- Contributions are welcome! Please feel free to submit a Pull Request.
728
-
729
- ## License
730
-
731
- MIT © MicDrop
732
-
733
- ## Support
734
-
735
- For issues, questions, or feature requests, please visit:
736
- https://github.com/get-micdrop/venue-calendar/issues
737
-
738
- ---
739
-
740
- 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
+ 🌐 **One script tag**: Self-hosted bundle — paste one `<script>`, no build step
12
+ 🎨 **Styles included**: The bundle injects its own CSS — no separate stylesheet to link
13
+ ⚡ **Auto-Mount**: Automatically finds and mounts to designated containers
14
+ 🎯 **Customizable**: Configure views, navigation, and more
15
+ 🌙 **Dark Mode**: Built-in light, dark, and high-contrast themes
16
+ ♿ **Accessible**: ARIA labels, keyboard navigation, screen reader support
17
+ 🎫 **Event Status**: Visual badges for "On Sale", "Selling Fast", "Sold Out"
18
+
19
+ ## Installation
20
+
21
+ Add one `<script>` tag pointing at the Micdrop-hosted bundle. The package is
22
+ private (not on npm/jsDelivr) — it is delivered from `get-micdrop.com`:
23
+
24
+ ```html
25
+ <script
26
+ defer
27
+ src="https://get-micdrop.com/embed/venue-calendar.iife.js"
28
+ ></script>
29
+ ```
30
+
31
+ - **No stylesheet to link.** The bundle injects its own CSS at runtime, so a
32
+ plain page with just this `<script>` renders fully styled.
33
+ - **Use `defer`** (or `async`) so the bundle never blocks page parse. It is
34
+ ~310 KB gzipped.
35
+ - **Serve your page over HTTPS.** Checkout stores a `Secure` cart cookie, which
36
+ Safari drops on non-secure (`http://`) pages.
37
+
38
+ > **Heads-up:** the exact hosted URL is being finalized (Micdrop ticket
39
+ > MIC-1130). Confirm the address with Micdrop before going live.
40
+
41
+ > The `import { ... } from '@getmicdrop/venue-calendar'` examples further down
42
+ > are for **Micdrop-internal apps** that build with a bundler and have registry
43
+ > access to the private package. Public sites (comedy clubs, etc.) use the
44
+ > `<script>` tag above — not `npm install`.
45
+
46
+ ## Quick Start
47
+
48
+ ### Method 1: Auto-Mount (Easiest)
49
+
50
+ Simply add a div with the class `micdrop-calendar-container` and the calendar will automatically mount:
51
+
52
+ ```html
53
+ <!DOCTYPE html>
54
+ <html>
55
+ <head>
56
+ <title>My Comedy Club</title>
57
+ <!-- Preload the bundle while the page parses. defer keeps the
58
+ <script> non-blocking; preload starts the fetch earlier. -->
59
+ <link
60
+ rel="preload"
61
+ as="script"
62
+ href="https://get-micdrop.com/embed/venue-calendar.iife.js"
63
+ />
64
+ <script
65
+ defer
66
+ src="https://get-micdrop.com/embed/venue-calendar.iife.js"
67
+ ></script>
68
+ </head>
69
+ <body>
70
+ <!-- Calendar auto-mounts here. Use data-organization-id to show all of an
71
+ organization's shows, or data-venue-id for a single venue. -->
72
+ <div
73
+ class="micdrop-calendar-container"
74
+ data-organization-id="your-organization-id"
75
+ data-view="calendar"
76
+ data-show-view-options="true"
77
+ data-show-month-switcher="true"
78
+ data-locale="en-US"
79
+ ></div>
80
+ </body>
81
+ </html>
82
+ ```
83
+
84
+ ### Method 2: Web Component
85
+
86
+ Use the custom `<micdrop-calendar>` element:
87
+
88
+ ```html
89
+ <!DOCTYPE html>
90
+ <html>
91
+ <head>
92
+ <title>My Comedy Club</title>
93
+ <script
94
+ defer
95
+ src="https://get-micdrop.com/embed/venue-calendar.iife.js"
96
+ ></script>
97
+ </head>
98
+ <body>
99
+ <!-- Web Component -->
100
+ <micdrop-calendar
101
+ venue-id="your-venue-id"
102
+ view="calendar"
103
+ show-view-options="true"
104
+ show-month-switcher="true"
105
+ locale="en-US"
106
+ >
107
+ </micdrop-calendar>
108
+ </body>
109
+ </html>
110
+ ```
111
+
112
+ ### Method 3: JavaScript API
113
+
114
+ For more control, use the JavaScript API:
115
+
116
+ ```html
117
+ <!DOCTYPE html>
118
+ <html>
119
+ <head>
120
+ <title>My Comedy Club</title>
121
+ </head>
122
+ <body>
123
+ <div id="my-calendar"></div>
124
+
125
+ <!-- Load the bundle, then call the global it exposes. -->
126
+ <script
127
+ defer
128
+ src="https://get-micdrop.com/embed/venue-calendar.iife.js"
129
+ ></script>
130
+ <script>
131
+ window.addEventListener('load', function () {
132
+ window.VenueCalendar.initVenueCalendar({
133
+ target: '#my-calendar',
134
+ organizationId: 'your-organization-id',
135
+ view: 'calendar',
136
+ showViewOptions: true,
137
+ showMonthSwitcher: true,
138
+ });
139
+ });
140
+ </script>
141
+ </body>
142
+ </html>
143
+ ```
144
+
145
+ ## Framework Integration
146
+
147
+ ### React
148
+
149
+ ```jsx
150
+ import React, { useEffect, useRef } from 'react';
151
+ import { initVenueCalendar, unmount } from '@getmicdrop/venue-calendar';
152
+
153
+ function VenueCalendarComponent({ venueId, view = 'calendar' }) {
154
+ const calendarRef = useRef(null);
155
+ const instanceRef = useRef(null);
156
+
157
+ useEffect(() => {
158
+ if (!calendarRef.current) return;
159
+ instanceRef.current = initVenueCalendar({
160
+ target: calendarRef.current,
161
+ venueId,
162
+ view,
163
+ events: [],
164
+ showViewOptions: true,
165
+ showMonthSwitcher: true,
166
+ });
167
+
168
+ return () => {
169
+ // Svelte 5 — components mounted via `mount()` are destroyed via
170
+ // the `unmount` helper, not `.$destroy()` (that was Svelte 4).
171
+ if (instanceRef.current) {
172
+ try {
173
+ unmount(instanceRef.current);
174
+ } catch {}
175
+ instanceRef.current = null;
176
+ }
177
+ };
178
+ }, [venueId, view]);
179
+
180
+ return <div ref={calendarRef}></div>;
181
+ }
182
+
183
+ export default VenueCalendarComponent;
184
+ ```
185
+
186
+ ### Error reporting and runtime config
187
+
188
+ Wire any errors caught by the widget into your existing monitoring:
189
+
190
+ ```js
191
+ import { configureVenueCalendar } from '@getmicdrop/venue-calendar';
192
+
193
+ configureVenueCalendar({
194
+ onError: (err, { source }) => {
195
+ Sentry.captureException(err, { tags: { source, micdrop: true } });
196
+ },
197
+ // Optional overrides for self-hosted backends or regional failover.
198
+ // apiBaseUrl: 'https://api.eu.micdrop.com',
199
+ // apiTimeout: 15000,
200
+ // apiRetries: 2,
201
+ });
202
+ ```
203
+
204
+ For ad-hoc support diagnostics, the widget exposes its version on
205
+ `window`:
206
+
207
+ ```js
208
+ window.__MICDROP_CALENDAR__.version; // e.g. "3.6.23"
209
+ ```
210
+
211
+ **Usage in React App:**
212
+
213
+ ```jsx
214
+ import React, { useState } from 'react';
215
+ import VenueCalendarComponent from './VenueCalendarComponent';
216
+
217
+ function App() {
218
+ const [venueId, setVenueId] = useState('comedy-club-123');
219
+ const [view, setView] = useState('calendar');
220
+
221
+ return (
222
+ <div style={{ padding: '20px' }}>
223
+ <h1>Event Viewer</h1>
224
+
225
+ <div style={{ marginBottom: '20px' }}>
226
+ <label>Venue ID:</label>
227
+ <input
228
+ type="text"
229
+ value={venueId}
230
+ onChange={e => setVenueId(e.target.value)}
231
+ />
232
+ </div>
233
+
234
+ <div style={{ marginBottom: '20px' }}>
235
+ <label>Select View:</label>
236
+ <label>
237
+ <input
238
+ type="radio"
239
+ value="list"
240
+ checked={view === 'list'}
241
+ onChange={e => setView(e.target.value)}
242
+ />
243
+ List
244
+ </label>
245
+ <label>
246
+ <input
247
+ type="radio"
248
+ value="gallery"
249
+ checked={view === 'gallery'}
250
+ onChange={e => setView(e.target.value)}
251
+ />
252
+ Gallery
253
+ </label>
254
+ <label>
255
+ <input
256
+ type="radio"
257
+ value="calendar"
258
+ checked={view === 'calendar'}
259
+ onChange={e => setView(e.target.value)}
260
+ />
261
+ Calendar
262
+ </label>
263
+ </div>
264
+
265
+ <VenueCalendarComponent venueId={venueId} view={view} />
266
+ </div>
267
+ );
268
+ }
269
+
270
+ export default App;
271
+ ```
272
+
273
+ ### Vue 3
274
+
275
+ ```vue
276
+ <template>
277
+ <div ref="calendarContainer"></div>
278
+ </template>
279
+
280
+ <script setup>
281
+ import { ref, onMounted, onUnmounted, watch } from 'vue';
282
+ import { initVenueCalendar } from '@getmicdrop/venue-calendar';
283
+
284
+ const props = defineProps({
285
+ venueId: String,
286
+ view: {
287
+ type: String,
288
+ default: 'calendar',
289
+ },
290
+ });
291
+
292
+ const calendarContainer = ref(null);
293
+ let calendarInstance = null;
294
+
295
+ onMounted(() => {
296
+ calendarInstance = initVenueCalendar({
297
+ target: calendarContainer.value,
298
+ venueId: props.venueId,
299
+ view: props.view,
300
+ events: [],
301
+ showViewOptions: true,
302
+ showMonthSwitcher: true,
303
+ });
304
+ });
305
+
306
+ onUnmounted(() => {
307
+ if (calendarInstance && calendarInstance.$destroy) {
308
+ calendarInstance.$destroy();
309
+ }
310
+ });
311
+
312
+ watch(
313
+ () => props.venueId,
314
+ newId => {
315
+ if (calendarInstance) {
316
+ calendarInstance.$destroy();
317
+ calendarInstance = initVenueCalendar({
318
+ target: calendarContainer.value,
319
+ venueId: newId,
320
+ view: props.view,
321
+ events: [],
322
+ showViewOptions: true,
323
+ showMonthSwitcher: true,
324
+ });
325
+ }
326
+ }
327
+ );
328
+ </script>
329
+ ```
330
+
331
+ ### Svelte
332
+
333
+ ```svelte
334
+ <script>
335
+ import { VenueCalendar } from '@getmicdrop/venue-calendar';
336
+ import { Calendar, Grid, List } from 'carbon-icons-svelte';
337
+ import { writable } from 'svelte/store';
338
+
339
+ let venueId = 'your-venue-id';
340
+ let currentMonth = writable(new Date().getUTCMonth());
341
+ let currentYear = writable(new Date().getUTCFullYear());
342
+
343
+ function handleNext() {
344
+ currentMonth.update(m => m + 1);
345
+ }
346
+
347
+ function handlePrev() {
348
+ currentMonth.update(m => m - 1);
349
+ }
350
+ </script>
351
+
352
+ <VenueCalendar
353
+ showViewOptions={[
354
+ { id: 0, text: 'List view', icon: List },
355
+ { id: 1, text: 'Gallery view', icon: Grid },
356
+ { id: 2, text: 'Calendar view', icon: Calendar },
357
+ ]}
358
+ showMonthSwitcher={true}
359
+ events={[]}
360
+ {currentMonth}
361
+ {currentYear}
362
+ {handleNext}
363
+ {handlePrev}
364
+ on:eventClick={e => console.log('Event clicked:', e.detail)}
365
+ />
366
+ ```
367
+
368
+ ### Angular
369
+
370
+ ```typescript
371
+ import {
372
+ Component,
373
+ OnInit,
374
+ OnDestroy,
375
+ ElementRef,
376
+ ViewChild,
377
+ } from '@angular/core';
378
+ import { initVenueCalendar } from '@getmicdrop/venue-calendar';
379
+
380
+ @Component({
381
+ selector: 'app-venue-calendar',
382
+ template: '<div #calendarContainer></div>',
383
+ })
384
+ export class VenueCalendarComponent implements OnInit, OnDestroy {
385
+ @ViewChild('calendarContainer', { static: true })
386
+ calendarContainer!: ElementRef;
387
+ private calendarInstance: any;
388
+
389
+ ngOnInit() {
390
+ this.calendarInstance = initVenueCalendar({
391
+ target: this.calendarContainer.nativeElement,
392
+ venueId: 'your-venue-id',
393
+ view: 'calendar',
394
+ events: [],
395
+ showViewOptions: true,
396
+ showMonthSwitcher: true,
397
+ });
398
+ }
399
+
400
+ ngOnDestroy() {
401
+ if (this.calendarInstance && this.calendarInstance.$destroy) {
402
+ this.calendarInstance.$destroy();
403
+ }
404
+ }
405
+ }
406
+ ```
407
+
408
+ ## Configuration Options
409
+
410
+ ### Data Attributes (for auto-mount)
411
+
412
+ | Attribute | Type | Default | Description |
413
+ | -------------------------- | ------- | ------------ | ---------------------------------------------------- |
414
+ | `data-venue-id` | string | `''` | The venue ID to fetch events for |
415
+ | `data-view` | string | `'calendar'` | Initial view: `'list'`, `'gallery'`, or `'calendar'` |
416
+ | `data-show-view-options` | boolean | `true` | Show view switcher buttons |
417
+ | `data-show-month-switcher` | boolean | `true` | Show month navigation controls |
418
+
419
+ ### JavaScript API Options
420
+
421
+ ```javascript
422
+ initVenueCalendar({
423
+ target: '.my-calendar', // CSS selector or HTMLElement (required)
424
+ venueId: 'venue-123', // Venue ID (optional)
425
+ view: 'calendar', // 'list', 'gallery', or 'calendar' (default: 'calendar')
426
+ events: [], // Array of event objects (default: [])
427
+ showViewOptions: true, // Show view switcher (default: true)
428
+ showMonthSwitcher: true, // Show month navigation (default: true)
429
+ });
430
+ ```
431
+
432
+ ### Event Object Structure
433
+
434
+ ```javascript
435
+ {
436
+ id: 'event-123',
437
+ name: 'Comedy Night',
438
+ date: '2024-10-25T20:00:00Z',
439
+ image: 'https://example.com/image.jpg',
440
+ status: 'On Sale',
441
+ timeline: '8:00 PM - 10:00 PM',
442
+ // ... other fields
443
+ }
444
+ ```
445
+
446
+ ## Views
447
+
448
+ ### Calendar View
449
+
450
+ The default view showing events in a monthly calendar grid. Perfect for venues with regular shows.
451
+
452
+ ### List View
453
+
454
+ A vertical list layout showing all upcoming events with details. Great for mobile experiences.
455
+
456
+ ### Gallery View
457
+
458
+ A grid layout displaying event posters in a gallery format. Ideal for showcasing event imagery.
459
+
460
+ ## WordPress Integration
461
+
462
+ For WordPress sites, you can add this to your page/post HTML:
463
+
464
+ ```html
465
+ <div
466
+ class="micdrop-calendar-container"
467
+ data-venue-id="your-venue-id"
468
+ data-view="calendar"
469
+ ></div>
470
+
471
+ <script src="https://get-micdrop.com/embed/venue-calendar.iife.js"></script>
472
+ ```
473
+
474
+ Or add the script to your theme's footer and use the div anywhere in your content.
475
+
476
+ ## Styling
477
+
478
+ 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.
479
+
480
+ ```css
481
+ /* Example: Custom styling */
482
+ .micdrop-calendar-container {
483
+ max-width: 1200px;
484
+ margin: 0 auto;
485
+ padding: 20px;
486
+ }
487
+ ```
488
+
489
+ ## Theming
490
+
491
+ The calendar supports comprehensive theming via CSS custom properties and JavaScript utilities.
492
+
493
+ ### Using CSS Custom Properties
494
+
495
+ Override the default theme by setting CSS custom properties:
496
+
497
+ ```css
498
+ /* Custom brand colors */
499
+ .micdrop-calendar-container {
500
+ --Brand-Primary: 270 76% 60%; /* Purple */
501
+ --Text-Primary: 0 0% 10%;
502
+ --BG-Primary: 0 0% 100%;
503
+ }
504
+
505
+ /* Dark mode */
506
+ .dark .micdrop-calendar-container,
507
+ [data-theme='dark'] .micdrop-calendar-container {
508
+ --Brand-Primary: 270 76% 70%;
509
+ --Text-Primary: 0 0% 95%;
510
+ --BG-Primary: 0 0% 10%;
511
+ }
512
+ ```
513
+
514
+ ### Available CSS Variables
515
+
516
+ | Variable | Description | Default (Light) |
517
+ | ---------------------- | ----------------------- | -------------------- |
518
+ | `--Brand-Primary` | Primary brand color | `217 91% 60%` (Blue) |
519
+ | `--Text-Primary` | Main text color | `0 0% 0%` |
520
+ | `--Text-Secondary` | Secondary text | `0 0% 40%` |
521
+ | `--BG-Primary` | Main background | `0 0% 100%` |
522
+ | `--BG-Secondary` | Secondary background | `0 0% 98%` |
523
+ | `--Stroke-Primary` | Border colors | `0 0% 80%` |
524
+ | `--Status-OnSale` | "On Sale" badge | `217 91% 60%` |
525
+ | `--Status-SellingFast` | "Selling Fast" badge | `38 92% 50%` |
526
+ | `--Status-SoldOut` | "Sold Out" badge | `0 84% 60%` |
527
+ | `--Today-BG` | Today's date background | `217 91% 97%` |
528
+ | `--Focus-Ring` | Keyboard focus ring | `217 91% 60%` |
529
+
530
+ ### Using JavaScript Theme Utilities
531
+
532
+ ```javascript
533
+ import {
534
+ applyTheme,
535
+ themes,
536
+ generateThemeCSS,
537
+ } from '@getmicdrop/venue-calendar';
538
+
539
+ // Apply a preset theme
540
+ applyTheme(themes.dark);
541
+
542
+ // Apply to a specific container
543
+ const container = document.querySelector('.micdrop-calendar-container');
544
+ applyTheme(themes.dark, container);
545
+
546
+ // Create a custom theme
547
+ const myTheme = {
548
+ brandPrimary: '270 76% 60%', // Purple
549
+ textPrimary: '0 0% 10%',
550
+ bgPrimary: '0 0% 100%',
551
+ statusOnSale: '142 71% 45%', // Green for on sale
552
+ };
553
+ applyTheme(myTheme);
554
+
555
+ // Generate CSS string for embedding
556
+ const cssString = generateThemeCSS(myTheme);
557
+ console.log(cssString);
558
+ // Output: :root { --Brand-Primary: 270 76% 60%; ... }
559
+ ```
560
+
561
+ ### Preset Themes
562
+
563
+ Three themes are included out of the box:
564
+
565
+ ```javascript
566
+ import { themes } from '@getmicdrop/venue-calendar';
567
+
568
+ // Light theme (default)
569
+ applyTheme(themes.light);
570
+
571
+ // Dark theme
572
+ applyTheme(themes.dark);
573
+
574
+ // High contrast (accessibility)
575
+ applyTheme(themes.highContrast);
576
+ ```
577
+
578
+ ### Automatic Dark Mode
579
+
580
+ The calendar automatically respects the user's system preference:
581
+
582
+ ```css
583
+ /* Automatically applied when user prefers dark mode */
584
+ @media (prefers-color-scheme: dark) {
585
+ /* Dark theme variables are applied */
586
+ }
587
+ ```
588
+
589
+ You can also manually toggle dark mode:
590
+
591
+ ```html
592
+ <!-- Add 'dark' class to enable dark theme -->
593
+ <div class="dark">
594
+ <div class="micdrop-calendar-container" data-venue-id="123"></div>
595
+ </div>
596
+
597
+ <!-- Or use data-theme attribute -->
598
+ <div data-theme="dark">
599
+ <div class="micdrop-calendar-container" data-venue-id="123"></div>
600
+ </div>
601
+ ```
602
+
603
+ ## Browser Support
604
+
605
+ - Chrome (latest)
606
+ - Firefox (latest)
607
+ - Safari (latest)
608
+ - Edge (latest)
609
+ - Mobile browsers (iOS Safari, Chrome Mobile)
610
+
611
+ ## Development
612
+
613
+ ### Building the Package
614
+
615
+ ```bash
616
+ # Install dependencies
617
+ npm install
618
+
619
+ # Build the library
620
+ npm run build:lib
621
+
622
+ # Development mode (SvelteKit app)
623
+ npm run dev
624
+
625
+ # Preview production build
626
+ npm run preview
627
+ ```
628
+
629
+ ### Project Structure
630
+
631
+ ```
632
+ venue-calendar/
633
+ ├── src/
634
+ │ ├── components/ # Svelte components
635
+ │ │ ├── Calendar/
636
+ │ │ ├── CalendarContainer/
637
+ │ │ └── Button/
638
+ │ ├── lib/ # Library entry points
639
+ │ │ ├── VenueCalendar.js
640
+ │ │ └── web-component.js
641
+ │ └── routes/ # SvelteKit routes (for dev)
642
+ ├── dist/ # Built package (generated)
643
+ ├── package.json
644
+ ├── vite.config.lib.js # Library build config
645
+ └── README.md
646
+ ```
647
+
648
+ ### Lockfile policy
649
+
650
+ `package-lock.json` is the single canonical lockfile — CI and the publish
651
+ workflow install with `npm ci`. Do not commit `yarn.lock` or
652
+ `pnpm-lock.yaml` (both gitignored). Local dev machines may use pnpm for the
653
+ svelte-components symlink workflow, but dependency changes must land in
654
+ `package-lock.json` via npm.
655
+
656
+ ## API Reference
657
+
658
+ ### `initVenueCalendar(options)`
659
+
660
+ Initialize a calendar instance.
661
+
662
+ **Parameters:**
663
+
664
+ - `options` (Object): Configuration options
665
+
666
+ **Returns:** Svelte component instance
667
+
668
+ **Example:**
669
+
670
+ ```javascript
671
+ const calendar = initVenueCalendar({
672
+ target: '#calendar',
673
+ venueId: 'venue-123',
674
+ view: 'calendar',
675
+ });
676
+ ```
677
+
678
+ ### `autoMount()`
679
+
680
+ Automatically mount calendars to all elements with class `micdrop-calendar-container`.
681
+
682
+ **Example:**
683
+
684
+ ```javascript
685
+ import { autoMount } from '@getmicdrop/venue-calendar';
686
+ autoMount();
687
+ ```
688
+
689
+ ### Component Events
690
+
691
+ The calendar component emits events that you can listen to:
692
+
693
+ ```javascript
694
+ const calendar = initVenueCalendar({
695
+ target: '#calendar',
696
+ // ... other options
697
+ });
698
+
699
+ // Listen to component events (if using Svelte component directly)
700
+ calendar.$on('eventClick', event => {
701
+ console.log('Event clicked:', event.detail);
702
+ });
703
+ ```
704
+
705
+ ## Troubleshooting
706
+
707
+ ### Calendar not appearing
708
+
709
+ 1. **Check the script is loaded**: Open browser console and verify no errors
710
+ 2. **Verify container exists**: Make sure the target element exists in the DOM
711
+ 3. **Check data attributes**: Ensure attributes are correctly formatted with `data-` prefix
712
+
713
+ ### Styles not applying
714
+
715
+ 1. **CSS not loaded**: The styles are bundled in the JS file and auto-injected — no separate stylesheet needed
716
+ 2. **CSS conflicts**: Check if other styles are overriding the calendar styles
717
+ 3. **Bundle didn't load**: Confirm the `<script src>` points at the Micdrop-hosted bundle and returns 200 (not 404)
718
+
719
+ ### Events not showing
720
+
721
+ 1. **Check event data format**: Ensure events match the expected structure
722
+ 2. **Date format**: Use ISO 8601 format for dates (`YYYY-MM-DDTHH:mm:ssZ`)
723
+ 3. **Venue ID**: Verify the venue ID is correct
724
+
725
+ ## Contributing
726
+
727
+ Contributions are welcome! Please feel free to submit a Pull Request.
728
+
729
+ ## License
730
+
731
+ MIT © MicDrop
732
+
733
+ ## Support
734
+
735
+ For issues, questions, or feature requests, please visit:
736
+ https://github.com/get-micdrop/venue-calendar/issues
737
+
738
+ ---
739
+
740
+ Made with ❤️ by the MicDrop team