@getmicdrop/venue-calendar 4.3.138 → 4.3.139
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 +895 -840
- package/dist/AddOnCard-Dlt_4lut.js +475 -0
- package/dist/{Button-B_gbGd63.js → Button-Ch5dRGa2.js} +1 -1
- package/dist/{Button-B1cBhdtC.js → Button-DpeQSoQ7.js} +58 -45
- package/dist/Calendar-CNWS2xiR.js +396 -0
- package/dist/CalendarFoundryView-B5puOxH5.js +16431 -0
- package/dist/{ChartBlock-DcsCXfX8.js → ChartBlock-vihMKVdW.js} +2 -2
- package/dist/Checkout-B2FvX6Af.js +1070 -0
- package/dist/Checkout-y0x-v-XH.js +1995 -0
- package/dist/{ChevronDownOutline-kFgRY2cg.js → CloseOutline-Bh9UO94v.js} +2 -2
- package/dist/{CollectionView-C0vDg5oJ.js → CollectionView-CcLlV-1f.js} +22 -24
- package/dist/{CropImage-BWYeQXXA.js → CropImage-DqLAGy5s.js} +6 -6
- package/dist/{DatePicker-v-4ijT8N.js → DatePicker-D20Te0JY.js} +222 -215
- package/dist/{Event-vlu8IAxh.js → Event-DoIU0o6C.js} +799 -796
- package/dist/{EventCard-puoh3xag.js → EventCard-B8MYLyIW.js} +1 -1
- package/dist/EventPage-DM4tjCcL.js +1298 -0
- package/dist/{FilterChipGroup-DUGvOaRI.js → FilterChipGroup-BCjc7-pE.js} +1 -1
- package/dist/{ImageUploader-CKrf5amy.js → ImageUploader-BzxKIyLN.js} +324 -375
- package/dist/{Input-BQk4itex.js → Input-Bp5EgI1F.js} +5 -3
- package/dist/Modal-C6EXgkuF.js +159 -0
- package/dist/{ModalFooter-gFaDKsfj.js → ModalFooter-C4TD3-zP.js} +1 -1
- package/dist/{ModalTitle-CS5AGwrU.js → ModalTitle-BP4Bm3sA.js} +1 -1
- package/dist/{PasswordInput-C65GqxdF.js → PasswordInput-BlzSrkPs.js} +1 -1
- package/dist/{PhoneInput-Dj1I3bEn.js → PhoneInput-_ByjRGQ0.js} +2 -2
- package/dist/{RecommendationsRail-DC5qX1ei.js → RecommendationsRail-BDNnbL-p.js} +53 -50
- package/dist/{Search-BE64QcmK.js → Search-vhGEpog6.js} +1 -1
- package/dist/SeriesPage-YE8czX1M.js +32 -0
- package/dist/{SkeletonLoader-DfW0N9R3.js → SkeletonLoader-Beh2izdy.js} +1 -1
- package/dist/Spinner-DgubkWKo.js +88 -0
- package/dist/{Success-D3CrUeka.js → Success-CN5HB8gN.js} +164 -166
- package/dist/{TimePicker-HYzPI_Dc.js → TimePicker-BDuy9Ap8.js} +1 -1
- package/dist/{ViewTicketsEmbed-DzUCgtA3.js → ViewTicketsEmbed-DvoMIiKJ.js} +9 -10
- package/dist/{address-field-BwGHcMKY.js → address-field-DOalICpt.js} +2 -2
- package/dist/{allowlist-Bt1BHhNd.js → allowlist-DinkGF2L.js} +77 -68
- package/dist/api/api.cjs +1 -1
- package/dist/api/api.mjs +320 -297
- package/dist/api/client.d.ts +14 -53
- package/dist/api/events.d.ts +15 -1
- package/dist/api/result.d.ts +9 -0
- package/dist/{api-CRHFSJDI.js → api-CsAx0rmV.js} +150 -145
- package/dist/{avatar-picker-field-CSF5okeM.js → avatar-picker-field-CV4vRxTB.js} +14 -14
- package/dist/{checkoutState-BDNjJRMG.js → checkoutState-DSx7g3Vy.js} +12 -21
- package/dist/{client-BIN_q-of.js → client-SaDt6559.js} +18 -12
- package/dist/{constants-DrFV2oht.js → constants-sRRJh0u-.js} +1 -1
- package/dist/{date-field-3tgOYbzF.js → date-field-DylJx0y7.js} +9 -9
- package/dist/{date-range-field-D0Aq9me9.js → date-range-field-BOV1V2ab.js} +7 -7
- package/dist/{de-CUrE_4a4.js → de-CzkX3H3B.js} +1 -0
- package/dist/{defaultLabels-CybwJCNn.js → defaultLabels-DLK6rq4q.js} +1 -0
- package/dist/{defaults-B5wyre5O.js → defaults-Cbuin1WS.js} +2 -3
- package/dist/{es-B2-z2Kft.js → es-BOLzv8eD.js} +1 -0
- package/dist/{event-CEg17hts.js → event-ClsLWtR0.js} +1 -1
- package/dist/{event-transform-DqFigNQg.js → event-transform-Cs63X0hI.js} +42 -42
- package/dist/{eventStatusStream-DK5fWCTB.js → eventStatusStream-BAh5nJP2.js} +1 -1
- package/dist/{field-rules-CKFFB16Q.js → field-rules-Yb2JY1qT.js} +1 -1
- package/dist/{file-field-2mPz4Da-.js → file-field-Dwo80kDg.js} +4 -4
- package/dist/format-CehusdDg.js +1718 -0
- package/dist/{formatters-CzKNRUwz.js → formatters-DUWbI_Eg.js} +25 -35
- package/dist/{fr-CiePVIlj.js → fr-DYTIBBXo.js} +1 -0
- package/dist/{href-DpbLXQ4c.js → href-BXhNawil.js} +1 -1
- package/dist/i18n-BNF6a-QA.js +720 -0
- package/dist/i18n-F_QOaHVh.js +26 -0
- package/dist/{id-Ttw95_7t.js → id-CIyIkGhH.js} +1 -0
- package/dist/{image-field-B8x0WQ2j.js → image-field-DeLzsJlz.js} +2 -2
- package/dist/{it-CBbXcFY1.js → it-CF4Db_nK.js} +1 -0
- package/dist/{ja-B2Tag7J3.js → ja-5-7WNHD1.js} +1 -0
- package/dist/{ko-CcTn4lAi.js → ko-huIzHR3W.js} +1 -0
- package/dist/locales/4.3.139/main/de.js +1 -0
- package/dist/locales/4.3.139/main/es.js +1 -0
- package/dist/locales/4.3.139/main/fr.js +1 -0
- package/dist/locales/4.3.139/main/id.js +1 -0
- package/dist/locales/4.3.139/main/it.js +1 -0
- package/dist/locales/4.3.139/main/ja.js +1 -0
- package/dist/locales/4.3.139/main/ko.js +1 -0
- package/dist/locales/4.3.139/main/nl.js +1 -0
- package/dist/locales/4.3.139/main/pl.js +1 -0
- package/dist/locales/4.3.139/main/pt-br.js +1 -0
- package/dist/locales/4.3.139/main/tr.js +1 -0
- package/dist/locales/4.3.139/main/zh.js +1 -0
- package/dist/look-island.svelte-D87MvHNy.js +1296 -0
- package/dist/{look-names-JI6GE-Zj.js → look-names-B9MywEzX.js} +68 -58
- package/dist/looks/4.3.139/AddOnCard-CKdkGcHH.js +1 -0
- package/dist/looks/4.3.139/Checkout-D7CaFYTE.js +1 -0
- package/dist/looks/4.3.139/Checkout-DuP46PMi.js +3 -0
- package/dist/looks/4.3.139/CollectionView-CWm57JCx.js +1 -0
- package/dist/looks/4.3.139/Event-ePupb4qY.js +8 -0
- package/dist/looks/4.3.139/EventPage-CgexXhEU.js +1 -0
- package/dist/looks/4.3.139/RecommendationsRail-Bz-Mj_r4.js +2 -0
- package/dist/looks/4.3.139/SeriesPage-DI2uFF0Y.js +1 -0
- package/dist/looks/4.3.139/Success-BkMzmgmc.js +3 -0
- package/dist/looks/4.3.139/ViewTicketsEmbed-CbEJwRry.js +1 -0
- package/dist/looks/4.3.139/_vc-foundry-calendar-stub-BVbAFEK2.js +1 -0
- package/dist/looks/4.3.139/buyerEmail-CqCYa9UL.js +1 -0
- package/dist/looks/4.3.139/constants-CU_ZgyQu.js +3 -0
- package/dist/looks/4.3.139/defaults-B46SFFK4.js +2 -0
- package/dist/looks/4.3.139/dist-BWGSqtWN.js +1 -0
- package/dist/looks/4.3.139/eventStatusStream-CW5lJwsa.js +10 -0
- package/dist/looks/4.3.139/first-core-DrYq9wBy.js +151 -0
- package/dist/looks/4.3.139/first-mount.svelte-DFSLaJWm.js +1 -0
- package/dist/looks/4.3.139/first-seo-DvHuCXT6.js +1 -0
- package/dist/looks/4.3.139/first.js +1 -0
- package/dist/looks/4.3.139/full-widget-DDBk3i4U.js +2 -0
- package/dist/looks/4.3.139/gate-password-cache-D4Zls6QM.js +1 -0
- package/dist/looks/4.3.139/i18n-DRaFNYsQ.js +1 -0
- package/dist/looks/4.3.139/listing-BSaRTkxW.js +1 -0
- package/dist/looks/4.3.139/loaders.runtime-BNG8O6-A.js +1 -0
- package/dist/looks/4.3.139/looks.js +1 -0
- package/dist/looks/4.3.139/modalManager.svelte-CqQWYz9Y.js +1 -0
- package/dist/looks/4.3.139/rolldown-runtime-4tVxZq34.js +1 -0
- package/dist/looks/4.3.139/serverTotals-Bu1fAPLB.js +1 -0
- package/dist/looks/4.3.139/showcase-state-options-CpCMAKVD.js +1 -0
- package/dist/looks/4.3.139/utils-pGRhH4A-.js +1 -0
- package/dist/{media-field-HieD0ye0.js → media-field-PW8ye6EL.js} +2 -2
- package/dist/modalManager.svelte-BHE0t9q3.js +79 -0
- package/dist/{multiselect-field-CJ4lUJyS.js → multiselect-field-CmocFs5f.js} +2 -2
- package/dist/navigation-B8rkS2On.js +348 -0
- package/dist/{nl-DeIqgjIs.js → nl-B1dv1lqk.js} +1 -0
- package/dist/{number-field-D5GkkGLB.js → number-field-CUD936Ai.js} +3 -3
- package/dist/{numeric-filter-field-CRWZFu_P.js → numeric-filter-field-BmgSYhOt.js} +3 -3
- package/dist/{password-field-DdOHXEOo.js → password-field-BfvcZUi_.js} +1 -1
- package/dist/{phone-field-BaYmp56f.js → phone-field-DO0U_YZ6.js} +17 -18
- package/dist/{pixels-BXXzmoCb.js → pixels-ipedGW6i.js} +7 -7
- package/dist/{pl-Bm2FcD5y.js → pl-DLlM_IPo.js} +1 -0
- package/dist/{pt-br-XS1Lsa6z.js → pt-br-8V3mf7pu.js} +1 -0
- package/dist/repeating-field-BwtJ6VS1.js +488 -0
- package/dist/{richtext-field-KmUytgBW.js → richtext-field-DvLCxPvq.js} +2 -2
- package/dist/{datetime-BlEsN_-8.js → scarcity-DfQvyhJP.js} +74 -85
- package/dist/{searchable-select-field-DettZRav.js → searchable-select-field-zuIqfoQM.js} +17 -17
- package/dist/{select-field-Wc4gAtou.js → select-field-DNNN-a9q.js} +6 -6
- package/dist/seo/HostSeoController.d.ts +13 -0
- package/dist/seo/seo.cjs +1 -1
- package/dist/seo/seo.mjs +18 -11
- package/dist/{serverTotals-COsx7Mc5.js → serverTotals-BprgDwOw.js} +1 -1
- package/dist/{showcase-state-options-CHGUaZtl.js → showcase-state-options-bKRf48yz.js} +2 -2
- package/dist/{time-field-CnxZcziR.js → time-field-DmPCoppV.js} +2 -2
- package/dist/{to-event-card-props-C9v9dspT.js → to-event-card-props-KVcCJ2JF.js} +34 -34
- package/dist/{tr-zKAbMfgi.js → tr-DiUEV65j.js} +1 -0
- package/dist/{tree-picker-field-aqux58EQ.js → tree-picker-field-BJwSFAqm.js} +8 -8
- package/dist/types/index.d.ts +3 -0
- package/dist/{utils-AIszIHUb.js → utils-x8YXRKvr.js} +12 -12
- package/dist/venue-BjLCg-PW.js +38 -0
- package/dist/venue-calendar.css +1 -1
- package/dist/venue-calendar.es.js +1655 -1539
- package/dist/venue-calendar.iife.js +1 -54
- package/dist/venue-calendar.umd.js +69 -63
- package/dist/{widget-key-context-BrWW0fyM.js → widget-key-context-dHM9FiuJ.js} +8 -37
- package/dist/{zh-DHfgJplH.js → zh-Cej2EPQt.js} +1 -0
- package/package.json +2 -2
- package/src/lib/constants/scarcity.ts +1 -2
- package/dist/AddOnCard-DEAC26HA.js +0 -348
- package/dist/BlockPlaceholder-BKfoE795.js +0 -59
- package/dist/Calendar-9xskvKUf.js +0 -395
- package/dist/CalendarFoundryView-DbxZNmY7.js +0 -16356
- package/dist/CartView-DMINN6bY.js +0 -2200
- package/dist/Checkbox-sObkYRdj.js +0 -60
- package/dist/Checkout-H9RGBU9D.js +0 -1071
- package/dist/Checkout-VnochAZE.js +0 -1967
- package/dist/CheckoutTimer-mjcYR3XU.js +0 -42
- package/dist/EventPage-DycxjX5Z.js +0 -1301
- package/dist/Modal-DOpDiAwN.js +0 -102
- package/dist/ScarcityBadge-BAaV2CIY.js +0 -141
- package/dist/SeriesPage-Cx89s2B6.js +0 -34
- package/dist/Skeleton-B6qB_udJ.js +0 -31
- package/dist/Spinner-Bj4dr9kO.js +0 -19
- package/dist/Textarea-BDcuBI13.js +0 -72
- package/dist/__SKIP_NAVIGATION__-Znm_vYcG.js +0 -5
- package/dist/__SKIP_PATHS__-Bzzrca_a.js +0 -5
- package/dist/calendar-Cdu8fCIt.js +0 -111
- package/dist/cta-qbcIt5Gh.js +0 -116
- package/dist/format-CypC4vWs.js +0 -1587
- package/dist/heic-to-BoLfsr3l.js +0 -70
- package/dist/i18n-B_TWnExv.js +0 -495
- package/dist/i18n-CSaUFnlD.js +0 -26
- package/dist/instant-BkZCSGDm.js +0 -162
- package/dist/labels-D8LN8lY7.js +0 -227
- package/dist/locales/4.3.138/main/de.js +0 -1
- package/dist/locales/4.3.138/main/es.js +0 -1
- package/dist/locales/4.3.138/main/fr.js +0 -1
- package/dist/locales/4.3.138/main/id.js +0 -1
- package/dist/locales/4.3.138/main/it.js +0 -1
- package/dist/locales/4.3.138/main/ja.js +0 -1
- package/dist/locales/4.3.138/main/ko.js +0 -1
- package/dist/locales/4.3.138/main/nl.js +0 -1
- package/dist/locales/4.3.138/main/pl.js +0 -1
- package/dist/locales/4.3.138/main/pt-br.js +0 -1
- package/dist/locales/4.3.138/main/tr.js +0 -1
- package/dist/locales/4.3.138/main/zh.js +0 -1
- package/dist/look-island.svelte-B7UH_QVv.js +0 -1270
- package/dist/looks/4.3.138/looks.js +0 -248
- package/dist/modalManager.svelte-BvyrTI6p.js +0 -51
- package/dist/navigation-DpqP-ahJ.js +0 -241
- package/dist/repeating-field-B4OhsaGB.js +0 -488
- package/dist/venue-DLkL7xdj.js +0 -12
- /package/dist/checkout-libs/{4.3.138 → 4.3.139}/phone.js +0 -0
- /package/dist/checkout-libs/{4.3.138 → 4.3.139}/qrcode.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/de.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/es.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/fr.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/id.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/it.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/ja.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/ko.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/nl.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/pl.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/pt-br.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/tr.js +0 -0
- /package/dist/locales/{4.3.138 → 4.3.139}/flow/zh.js +0 -0
- /package/dist/looks/{4.3.138 → 4.3.139}/micdrop-wordmark-BYMG6vLR.svg +0 -0
- /package/dist/looks/{4.3.138 → 4.3.139}/microphone-Ccv4r-kd.webp +0 -0
- /package/dist/looks/{4.3.138 → 4.3.139}/superuser-CZF6a5gO.webp +0 -0
- /package/dist/looks/{4.3.138 → 4.3.139}/treasury-DUE7lZzT.webp +0 -0
- /package/dist/looks/{4.3.138 → 4.3.139}/user-image-yuS4errP.svg +0 -0
package/README.md
CHANGED
|
@@ -1,840 +1,895 @@
|
|
|
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
|
-
✨ **
|
|
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
|
-
**Venue pixels and visitor consent:**
|
|
212
|
-
|
|
213
|
-
If your organization saved a Meta Pixel or Google Analytics 4 ID, the calendar
|
|
214
|
-
loads it only after the visitor agrees. With no consent signal on the page it
|
|
215
|
-
sends no Meta or Google request at all. Tell it the visitor said yes in any one
|
|
216
|
-
of these ways:
|
|
217
|
-
|
|
218
|
-
```html
|
|
219
|
-
<!-- your consent tool already said yes before the calendar loads -->
|
|
220
|
-
<div data-consent-granted="true" ...></div>
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
```js
|
|
224
|
-
// from your cookie banner's "Accept" callback
|
|
225
|
-
window.__MICDROP_CALENDAR__.setConsentGranted(true);
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
A consent tool that speaks the IAB TCF API (`__tcfapi`) is picked up
|
|
229
|
-
automatically. `data-consent-required="false"` tells the calendar your site does
|
|
230
|
-
not need consent for these pixels; that is your own legal call, and a visitor
|
|
231
|
-
whose browser sends Global Privacy Control still gets no pixels.
|
|
232
|
-
|
|
233
|
-
**Usage in React App:**
|
|
234
|
-
|
|
235
|
-
```jsx
|
|
236
|
-
import React, { useState } from 'react';
|
|
237
|
-
import VenueCalendarComponent from './VenueCalendarComponent';
|
|
238
|
-
|
|
239
|
-
function App() {
|
|
240
|
-
const [venueId, setVenueId] = useState('comedy-club-123');
|
|
241
|
-
const [view, setView] = useState('calendar');
|
|
242
|
-
|
|
243
|
-
return (
|
|
244
|
-
<div style={{ padding: '20px' }}>
|
|
245
|
-
<h1>Event Viewer</h1>
|
|
246
|
-
|
|
247
|
-
<div style={{ marginBottom: '20px' }}>
|
|
248
|
-
<label>Venue ID:</label>
|
|
249
|
-
<input
|
|
250
|
-
type="text"
|
|
251
|
-
value={venueId}
|
|
252
|
-
onChange={e => setVenueId(e.target.value)}
|
|
253
|
-
/>
|
|
254
|
-
</div>
|
|
255
|
-
|
|
256
|
-
<div style={{ marginBottom: '20px' }}>
|
|
257
|
-
<label>Select View:</label>
|
|
258
|
-
<label>
|
|
259
|
-
<input
|
|
260
|
-
type="radio"
|
|
261
|
-
value="list"
|
|
262
|
-
checked={view === 'list'}
|
|
263
|
-
onChange={e => setView(e.target.value)}
|
|
264
|
-
/>
|
|
265
|
-
List
|
|
266
|
-
</label>
|
|
267
|
-
<label>
|
|
268
|
-
<input
|
|
269
|
-
type="radio"
|
|
270
|
-
value="gallery"
|
|
271
|
-
checked={view === 'gallery'}
|
|
272
|
-
onChange={e => setView(e.target.value)}
|
|
273
|
-
/>
|
|
274
|
-
Gallery
|
|
275
|
-
</label>
|
|
276
|
-
<label>
|
|
277
|
-
<input
|
|
278
|
-
type="radio"
|
|
279
|
-
value="calendar"
|
|
280
|
-
checked={view === 'calendar'}
|
|
281
|
-
onChange={e => setView(e.target.value)}
|
|
282
|
-
/>
|
|
283
|
-
Calendar
|
|
284
|
-
</label>
|
|
285
|
-
</div>
|
|
286
|
-
|
|
287
|
-
<VenueCalendarComponent venueId={venueId} view={view} />
|
|
288
|
-
</div>
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
export default App;
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Vue 3
|
|
296
|
-
|
|
297
|
-
```vue
|
|
298
|
-
<template>
|
|
299
|
-
<div ref="calendarContainer"></div>
|
|
300
|
-
</template>
|
|
301
|
-
|
|
302
|
-
<script setup>
|
|
303
|
-
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
|
304
|
-
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
|
|
305
|
-
|
|
306
|
-
const props = defineProps({
|
|
307
|
-
venueId: String,
|
|
308
|
-
view: {
|
|
309
|
-
type: String,
|
|
310
|
-
default: 'calendar',
|
|
311
|
-
},
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
const calendarContainer = ref(null);
|
|
315
|
-
let calendarInstance = null;
|
|
316
|
-
|
|
317
|
-
onMounted(() => {
|
|
318
|
-
calendarInstance = initVenueCalendar({
|
|
319
|
-
target: calendarContainer.value,
|
|
320
|
-
venueId: props.venueId,
|
|
321
|
-
view: props.view,
|
|
322
|
-
events: [],
|
|
323
|
-
showViewOptions: true,
|
|
324
|
-
showMonthSwitcher: true,
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
onUnmounted(() => {
|
|
329
|
-
if (calendarInstance && calendarInstance.$destroy) {
|
|
330
|
-
calendarInstance.$destroy();
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
watch(
|
|
335
|
-
() => props.venueId,
|
|
336
|
-
newId => {
|
|
337
|
-
if (calendarInstance) {
|
|
338
|
-
calendarInstance.$destroy();
|
|
339
|
-
calendarInstance = initVenueCalendar({
|
|
340
|
-
target: calendarContainer.value,
|
|
341
|
-
venueId: newId,
|
|
342
|
-
view: props.view,
|
|
343
|
-
events: [],
|
|
344
|
-
showViewOptions: true,
|
|
345
|
-
showMonthSwitcher: true,
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
);
|
|
350
|
-
</script>
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### Svelte
|
|
354
|
-
|
|
355
|
-
```svelte
|
|
356
|
-
<script>
|
|
357
|
-
import { VenueCalendar } from '@getmicdrop/venue-calendar';
|
|
358
|
-
import { Calendar, Grid, List } from 'carbon-icons-svelte';
|
|
359
|
-
import { writable } from 'svelte/store';
|
|
360
|
-
|
|
361
|
-
let venueId = 'your-venue-id';
|
|
362
|
-
let currentMonth = writable(new Date().getUTCMonth());
|
|
363
|
-
let currentYear = writable(new Date().getUTCFullYear());
|
|
364
|
-
|
|
365
|
-
function handleNext() {
|
|
366
|
-
currentMonth.update(m => m + 1);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function handlePrev() {
|
|
370
|
-
currentMonth.update(m => m - 1);
|
|
371
|
-
}
|
|
372
|
-
</script>
|
|
373
|
-
|
|
374
|
-
<VenueCalendar
|
|
375
|
-
showViewOptions={[
|
|
376
|
-
{ id: 0, text: 'List view', icon: List },
|
|
377
|
-
{ id: 1, text: 'Gallery view', icon: Grid },
|
|
378
|
-
{ id: 2, text: 'Calendar view', icon: Calendar },
|
|
379
|
-
]}
|
|
380
|
-
showMonthSwitcher={true}
|
|
381
|
-
events={[]}
|
|
382
|
-
{currentMonth}
|
|
383
|
-
{currentYear}
|
|
384
|
-
{handleNext}
|
|
385
|
-
{handlePrev}
|
|
386
|
-
on:eventClick={e => console.log('Event clicked:', e.detail)}
|
|
387
|
-
/>
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
Host-page props — for a page that already owns part of what the widget draws.
|
|
391
|
-
Every one defaults to on, so embeds are unchanged:
|
|
392
|
-
|
|
393
|
-
| Prop | Type | Default | Description |
|
|
394
|
-
| ------------------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
395
|
-
| `checkoutProbe` | boolean | `true` | Ask whether this page can sell a ticket and overlay the "Online ticket sales are unavailable here" alert when it cannot. `false` skips the probe and never draws the alert — for a host where no ticket is bought, such as a site builder's design canvas. |
|
|
396
|
-
| `showGiftCardsLink` | boolean | `true` | The footer's "Gift cards" link. `false` for a host page whose own footer already carries it. |
|
|
397
|
-
| `showPoweredBy` | boolean | `true` | The footer's "Powered by Micdrop" mark. `false` for a host page whose own footer already carries it. |
|
|
398
|
-
|
|
399
|
-
### Angular
|
|
400
|
-
|
|
401
|
-
```typescript
|
|
402
|
-
import {
|
|
403
|
-
Component,
|
|
404
|
-
OnInit,
|
|
405
|
-
OnDestroy,
|
|
406
|
-
ElementRef,
|
|
407
|
-
ViewChild,
|
|
408
|
-
} from '@angular/core';
|
|
409
|
-
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
|
|
410
|
-
|
|
411
|
-
@Component({
|
|
412
|
-
selector: 'app-venue-calendar',
|
|
413
|
-
template: '<div #calendarContainer></div>',
|
|
414
|
-
})
|
|
415
|
-
export class VenueCalendarComponent implements OnInit, OnDestroy {
|
|
416
|
-
@ViewChild('calendarContainer', { static: true })
|
|
417
|
-
calendarContainer!: ElementRef;
|
|
418
|
-
private calendarInstance: any;
|
|
419
|
-
|
|
420
|
-
ngOnInit() {
|
|
421
|
-
this.calendarInstance = initVenueCalendar({
|
|
422
|
-
target: this.calendarContainer.nativeElement,
|
|
423
|
-
venueId: 'your-venue-id',
|
|
424
|
-
view: 'calendar',
|
|
425
|
-
events: [],
|
|
426
|
-
showViewOptions: true,
|
|
427
|
-
showMonthSwitcher: true,
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
ngOnDestroy() {
|
|
432
|
-
if (this.calendarInstance && this.calendarInstance.$destroy) {
|
|
433
|
-
this.calendarInstance.$destroy();
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
## Configuration Options
|
|
440
|
-
|
|
441
|
-
###
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
<
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
```
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
###
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
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
|
+
✨ **Six Views**: Calendar, List, Gallery, Carousel, Featured and Tonight, plus eight looks
|
|
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
|
+
**Venue pixels and visitor consent:**
|
|
212
|
+
|
|
213
|
+
If your organization saved a Meta Pixel or Google Analytics 4 ID, the calendar
|
|
214
|
+
loads it only after the visitor agrees. With no consent signal on the page it
|
|
215
|
+
sends no Meta or Google request at all. Tell it the visitor said yes in any one
|
|
216
|
+
of these ways:
|
|
217
|
+
|
|
218
|
+
```html
|
|
219
|
+
<!-- your consent tool already said yes before the calendar loads -->
|
|
220
|
+
<div data-consent-granted="true" ...></div>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
// from your cookie banner's "Accept" callback
|
|
225
|
+
window.__MICDROP_CALENDAR__.setConsentGranted(true);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
A consent tool that speaks the IAB TCF API (`__tcfapi`) is picked up
|
|
229
|
+
automatically. `data-consent-required="false"` tells the calendar your site does
|
|
230
|
+
not need consent for these pixels; that is your own legal call, and a visitor
|
|
231
|
+
whose browser sends Global Privacy Control still gets no pixels.
|
|
232
|
+
|
|
233
|
+
**Usage in React App:**
|
|
234
|
+
|
|
235
|
+
```jsx
|
|
236
|
+
import React, { useState } from 'react';
|
|
237
|
+
import VenueCalendarComponent from './VenueCalendarComponent';
|
|
238
|
+
|
|
239
|
+
function App() {
|
|
240
|
+
const [venueId, setVenueId] = useState('comedy-club-123');
|
|
241
|
+
const [view, setView] = useState('calendar');
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<div style={{ padding: '20px' }}>
|
|
245
|
+
<h1>Event Viewer</h1>
|
|
246
|
+
|
|
247
|
+
<div style={{ marginBottom: '20px' }}>
|
|
248
|
+
<label>Venue ID:</label>
|
|
249
|
+
<input
|
|
250
|
+
type="text"
|
|
251
|
+
value={venueId}
|
|
252
|
+
onChange={e => setVenueId(e.target.value)}
|
|
253
|
+
/>
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
<div style={{ marginBottom: '20px' }}>
|
|
257
|
+
<label>Select View:</label>
|
|
258
|
+
<label>
|
|
259
|
+
<input
|
|
260
|
+
type="radio"
|
|
261
|
+
value="list"
|
|
262
|
+
checked={view === 'list'}
|
|
263
|
+
onChange={e => setView(e.target.value)}
|
|
264
|
+
/>
|
|
265
|
+
List
|
|
266
|
+
</label>
|
|
267
|
+
<label>
|
|
268
|
+
<input
|
|
269
|
+
type="radio"
|
|
270
|
+
value="gallery"
|
|
271
|
+
checked={view === 'gallery'}
|
|
272
|
+
onChange={e => setView(e.target.value)}
|
|
273
|
+
/>
|
|
274
|
+
Gallery
|
|
275
|
+
</label>
|
|
276
|
+
<label>
|
|
277
|
+
<input
|
|
278
|
+
type="radio"
|
|
279
|
+
value="calendar"
|
|
280
|
+
checked={view === 'calendar'}
|
|
281
|
+
onChange={e => setView(e.target.value)}
|
|
282
|
+
/>
|
|
283
|
+
Calendar
|
|
284
|
+
</label>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
<VenueCalendarComponent venueId={venueId} view={view} />
|
|
288
|
+
</div>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export default App;
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Vue 3
|
|
296
|
+
|
|
297
|
+
```vue
|
|
298
|
+
<template>
|
|
299
|
+
<div ref="calendarContainer"></div>
|
|
300
|
+
</template>
|
|
301
|
+
|
|
302
|
+
<script setup>
|
|
303
|
+
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
|
304
|
+
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
|
|
305
|
+
|
|
306
|
+
const props = defineProps({
|
|
307
|
+
venueId: String,
|
|
308
|
+
view: {
|
|
309
|
+
type: String,
|
|
310
|
+
default: 'calendar',
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const calendarContainer = ref(null);
|
|
315
|
+
let calendarInstance = null;
|
|
316
|
+
|
|
317
|
+
onMounted(() => {
|
|
318
|
+
calendarInstance = initVenueCalendar({
|
|
319
|
+
target: calendarContainer.value,
|
|
320
|
+
venueId: props.venueId,
|
|
321
|
+
view: props.view,
|
|
322
|
+
events: [],
|
|
323
|
+
showViewOptions: true,
|
|
324
|
+
showMonthSwitcher: true,
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
onUnmounted(() => {
|
|
329
|
+
if (calendarInstance && calendarInstance.$destroy) {
|
|
330
|
+
calendarInstance.$destroy();
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
watch(
|
|
335
|
+
() => props.venueId,
|
|
336
|
+
newId => {
|
|
337
|
+
if (calendarInstance) {
|
|
338
|
+
calendarInstance.$destroy();
|
|
339
|
+
calendarInstance = initVenueCalendar({
|
|
340
|
+
target: calendarContainer.value,
|
|
341
|
+
venueId: newId,
|
|
342
|
+
view: props.view,
|
|
343
|
+
events: [],
|
|
344
|
+
showViewOptions: true,
|
|
345
|
+
showMonthSwitcher: true,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
</script>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Svelte
|
|
354
|
+
|
|
355
|
+
```svelte
|
|
356
|
+
<script>
|
|
357
|
+
import { VenueCalendar } from '@getmicdrop/venue-calendar';
|
|
358
|
+
import { Calendar, Grid, List } from 'carbon-icons-svelte';
|
|
359
|
+
import { writable } from 'svelte/store';
|
|
360
|
+
|
|
361
|
+
let venueId = 'your-venue-id';
|
|
362
|
+
let currentMonth = writable(new Date().getUTCMonth());
|
|
363
|
+
let currentYear = writable(new Date().getUTCFullYear());
|
|
364
|
+
|
|
365
|
+
function handleNext() {
|
|
366
|
+
currentMonth.update(m => m + 1);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function handlePrev() {
|
|
370
|
+
currentMonth.update(m => m - 1);
|
|
371
|
+
}
|
|
372
|
+
</script>
|
|
373
|
+
|
|
374
|
+
<VenueCalendar
|
|
375
|
+
showViewOptions={[
|
|
376
|
+
{ id: 0, text: 'List view', icon: List },
|
|
377
|
+
{ id: 1, text: 'Gallery view', icon: Grid },
|
|
378
|
+
{ id: 2, text: 'Calendar view', icon: Calendar },
|
|
379
|
+
]}
|
|
380
|
+
showMonthSwitcher={true}
|
|
381
|
+
events={[]}
|
|
382
|
+
{currentMonth}
|
|
383
|
+
{currentYear}
|
|
384
|
+
{handleNext}
|
|
385
|
+
{handlePrev}
|
|
386
|
+
on:eventClick={e => console.log('Event clicked:', e.detail)}
|
|
387
|
+
/>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Host-page props — for a page that already owns part of what the widget draws.
|
|
391
|
+
Every one defaults to on, so embeds are unchanged:
|
|
392
|
+
|
|
393
|
+
| Prop | Type | Default | Description |
|
|
394
|
+
| ------------------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
395
|
+
| `checkoutProbe` | boolean | `true` | Ask whether this page can sell a ticket and overlay the "Online ticket sales are unavailable here" alert when it cannot. `false` skips the probe and never draws the alert — for a host where no ticket is bought, such as a site builder's design canvas. |
|
|
396
|
+
| `showGiftCardsLink` | boolean | `true` | The footer's "Gift cards" link. `false` for a host page whose own footer already carries it. |
|
|
397
|
+
| `showPoweredBy` | boolean | `true` | The footer's "Powered by Micdrop" mark. `false` for a host page whose own footer already carries it. |
|
|
398
|
+
|
|
399
|
+
### Angular
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import {
|
|
403
|
+
Component,
|
|
404
|
+
OnInit,
|
|
405
|
+
OnDestroy,
|
|
406
|
+
ElementRef,
|
|
407
|
+
ViewChild,
|
|
408
|
+
} from '@angular/core';
|
|
409
|
+
import { initVenueCalendar } from '@getmicdrop/venue-calendar';
|
|
410
|
+
|
|
411
|
+
@Component({
|
|
412
|
+
selector: 'app-venue-calendar',
|
|
413
|
+
template: '<div #calendarContainer></div>',
|
|
414
|
+
})
|
|
415
|
+
export class VenueCalendarComponent implements OnInit, OnDestroy {
|
|
416
|
+
@ViewChild('calendarContainer', { static: true })
|
|
417
|
+
calendarContainer!: ElementRef;
|
|
418
|
+
private calendarInstance: any;
|
|
419
|
+
|
|
420
|
+
ngOnInit() {
|
|
421
|
+
this.calendarInstance = initVenueCalendar({
|
|
422
|
+
target: this.calendarContainer.nativeElement,
|
|
423
|
+
venueId: 'your-venue-id',
|
|
424
|
+
view: 'calendar',
|
|
425
|
+
events: [],
|
|
426
|
+
showViewOptions: true,
|
|
427
|
+
showMonthSwitcher: true,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
ngOnDestroy() {
|
|
432
|
+
if (this.calendarInstance && this.calendarInstance.$destroy) {
|
|
433
|
+
this.calendarInstance.$destroy();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Configuration Options
|
|
440
|
+
|
|
441
|
+
### Tag attributes
|
|
442
|
+
|
|
443
|
+
Every attribute below works on `<micdrop-calendar>` as written, and as its `data-` twin
|
|
444
|
+
(`data-view`, `data-venue-id`, …) on `<micdrop-calendar>` or the auto-mount
|
|
445
|
+
`<div class="micdrop-calendar-container">`. The auto-mount `<div>` reads the ones marked
|
|
446
|
+
"div" in the last column; for the rest, use `<micdrop-calendar>` or a saved widget.
|
|
447
|
+
|
|
448
|
+
| Attribute | Values | Default | What it does | div |
|
|
449
|
+
| --------------------- | ----------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------- | --- |
|
|
450
|
+
| `venue-id` | venue ID | none | The venue whose shows draw | ✓ |
|
|
451
|
+
| `organization-id` | organization ID | none | The organization whose shows draw, for an embed across venues | ✓ |
|
|
452
|
+
| `widget-id` | saved widget ID | none | Loads a widget saved in Micdrop: its view, filters, colors and display options; a div takes only its display options | ✓ |
|
|
453
|
+
| `widget-key` | widget key | none | Lets the widget read its shows from a site that is not Micdrop's own | ✓ |
|
|
454
|
+
| `view` | see [Views](#views) | `calendar` | The view the widget opens on | ✓ |
|
|
455
|
+
| `show-view-options` | `true` / `false` | `true` | Draws the view switcher | ✓ |
|
|
456
|
+
| `show-month-switcher` | `true` / `false` | `true` | Draws the month arrows | ✓ |
|
|
457
|
+
| `show-search` | `true` / `false` | with the switcher | Draws the search box; `true` draws it without the view switcher, `false` hides it | |
|
|
458
|
+
| `show-powered-by` | `true` / `false` | `true` | Draws the "Powered by Micdrop" line under the widget | ✓ |
|
|
459
|
+
| `show-background` | `true` / `false` | `true` | Paints the widget's own canvas and outer insets; `false` sits it straight on the page | |
|
|
460
|
+
| `max-items` | a positive whole number | all | How many shows Gallery, List and Carousel draw | |
|
|
461
|
+
| `skip-items` | a whole number | `0` | How many of the first upcoming shows the List looks (`look-list`, `look-board`) leave out | |
|
|
462
|
+
| `event-details` | JSON, e.g. `{"date":false}` | all on | Which card parts draw (`poster`, `date`, `description`); only `false` hides one | |
|
|
463
|
+
| `size` | `S` / `M` / `L` | `M` | How big each view draws its shows | |
|
|
464
|
+
| `heading-level` | `1` / `2` | `1` | Level of the screen-reader heading; `2` when the page already has its own `h1` | ✓ |
|
|
465
|
+
| `poster-fit` | `fit` / `fill` | `fit` | The whole poster, or cropped to cover its box | ✓ |
|
|
466
|
+
| `poster-backdrop` | `blur` / `color` | `blur` | What fills around a `fit` poster | ✓ |
|
|
467
|
+
| `inject-seo` | `true` / `false` | `true` | Opening a show sets the page's title and share preview to the show's, restored when it closes | ✓ |
|
|
468
|
+
| `url-mode` | `pushState` / `none` | `pushState` | `none` keeps the widget from changing the page address (for iframe and Wix embeds) | ✓ |
|
|
469
|
+
| `locale` | a language tag, e.g. `en-US` | browser setting | The language and date format the widget draws in | ✓ |
|
|
470
|
+
| `api-base` | an origin, e.g. `https://get-micdrop.com` | Micdrop's API | Where the widget reads its shows from | ✓ |
|
|
471
|
+
| `public-site-origin` | an origin | `api-base` | Where share links, event pages and gift-card links point | ✓ |
|
|
472
|
+
| `consent-required` | `true` / `false` | auto-detected | For a non-TCF cookie banner: hold tracking until consent is granted | ✓ |
|
|
473
|
+
| `consent-granted` | `true` / `false` | auto-detected | For a non-TCF cookie banner: the visitor has granted consent | ✓ |
|
|
474
|
+
|
|
475
|
+
A `true`/`false` attribute is on when present (`show-search` or `show-search=""`) and off only
|
|
476
|
+
as `="false"`. A value that does not parse is ignored, and the widget keeps its default.
|
|
477
|
+
|
|
478
|
+
### JavaScript API Options
|
|
479
|
+
|
|
480
|
+
```javascript
|
|
481
|
+
initVenueCalendar({
|
|
482
|
+
target: '.my-calendar', // CSS selector or HTMLElement (required)
|
|
483
|
+
venueId: 'venue-123', // Venue ID (optional)
|
|
484
|
+
view: 'calendar', // any view name under Views (default: 'calendar')
|
|
485
|
+
events: [], // Array of event objects (default: [])
|
|
486
|
+
showViewOptions: true, // Show view switcher (default: true)
|
|
487
|
+
showMonthSwitcher: true, // Show month navigation (default: true)
|
|
488
|
+
});
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Event Object Structure
|
|
492
|
+
|
|
493
|
+
```javascript
|
|
494
|
+
{
|
|
495
|
+
id: 'event-123',
|
|
496
|
+
name: 'Comedy Night',
|
|
497
|
+
date: '2024-10-25T20:00:00Z',
|
|
498
|
+
image: 'https://example.com/image.jpg',
|
|
499
|
+
status: 'On Sale',
|
|
500
|
+
timeline: '8:00 PM - 10:00 PM',
|
|
501
|
+
// ... other fields
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
## Views
|
|
506
|
+
|
|
507
|
+
`view` takes one of six view names, or one of eight looks.
|
|
508
|
+
|
|
509
|
+
| View | What it draws |
|
|
510
|
+
| ---------- | -------------------------------------- |
|
|
511
|
+
| `calendar` | The default: a month grid of shows |
|
|
512
|
+
| `list` | Upcoming shows in a vertical list |
|
|
513
|
+
| `gallery` | A grid of show posters |
|
|
514
|
+
| `carousel` | Shows in a row that scrolls sideways |
|
|
515
|
+
| `featured` | One show, large |
|
|
516
|
+
| `tonight` | Today's shows, drawn as the Board look |
|
|
517
|
+
|
|
518
|
+
### Looks
|
|
519
|
+
|
|
520
|
+
A look is a view with its card parts and size set, the starting points of Micdrop's widget builder.
|
|
521
|
+
|
|
522
|
+
| View | Look |
|
|
523
|
+
| --------------- | --------------------------------------- |
|
|
524
|
+
| `look-featured` | Featured: one show as a stacked card |
|
|
525
|
+
| `look-ticket` | Ticket card: one show, the date set big |
|
|
526
|
+
| `look-strip` | Strip: one show per slim row |
|
|
527
|
+
| `look-list` | List: shows grouped under their day |
|
|
528
|
+
| `look-board` | Board: a list led by each show's time |
|
|
529
|
+
| `look-grid` | Grid: show cards in a grid |
|
|
530
|
+
| `look-posters` | Poster wall: posters only |
|
|
531
|
+
| `look-calendar` | Calendar: a month grid |
|
|
532
|
+
|
|
533
|
+
## WordPress Integration
|
|
534
|
+
|
|
535
|
+
For WordPress sites, you can add this to your page/post HTML:
|
|
536
|
+
|
|
537
|
+
```html
|
|
538
|
+
<div
|
|
539
|
+
class="micdrop-calendar-container"
|
|
540
|
+
data-venue-id="your-venue-id"
|
|
541
|
+
data-view="calendar"
|
|
542
|
+
></div>
|
|
543
|
+
|
|
544
|
+
<script src="https://get-micdrop.com/embed/venue-calendar.iife.js"></script>
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Or add the script to your theme's footer and use the div anywhere in your content.
|
|
548
|
+
|
|
549
|
+
## Styling
|
|
550
|
+
|
|
551
|
+
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.
|
|
552
|
+
|
|
553
|
+
```css
|
|
554
|
+
/* Example: Custom styling */
|
|
555
|
+
.micdrop-calendar-container {
|
|
556
|
+
max-width: 1200px;
|
|
557
|
+
margin: 0 auto;
|
|
558
|
+
padding: 20px;
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
**Note:** The mount target must not be a shrink-to-fit box (`display: inline-block`, `float`, `position: absolute`, `display: table-cell`, or an auto-width item in a flex row). The calendar sizes its typography to its own container, which requires the mount target to get its width from its parent — a normal block element (as in every example above) is exactly right. If the calendar detects a shrink-to-fit mount target, it falls back to page-width type scaling and logs a console warning.
|
|
563
|
+
|
|
564
|
+
## Theming
|
|
565
|
+
|
|
566
|
+
The calendar supports comprehensive theming via CSS custom properties and JavaScript utilities.
|
|
567
|
+
|
|
568
|
+
### Using CSS Custom Properties
|
|
569
|
+
|
|
570
|
+
Override the default theme by setting CSS custom properties:
|
|
571
|
+
|
|
572
|
+
```css
|
|
573
|
+
/* Custom brand colors */
|
|
574
|
+
.micdrop-calendar-container {
|
|
575
|
+
--Brand-Primary: 270 76% 60%; /* Purple */
|
|
576
|
+
--Text-Primary: 0 0% 10%;
|
|
577
|
+
--BG-Primary: 0 0% 100%;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/* Dark mode */
|
|
581
|
+
.dark .micdrop-calendar-container,
|
|
582
|
+
[data-theme='dark'] .micdrop-calendar-container {
|
|
583
|
+
--Brand-Primary: 270 76% 70%;
|
|
584
|
+
--Text-Primary: 0 0% 95%;
|
|
585
|
+
--BG-Primary: 0 0% 10%;
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### Available CSS Variables
|
|
590
|
+
|
|
591
|
+
| Variable | Description | Default (Light) |
|
|
592
|
+
| ---------------------- | ----------------------- | -------------------- |
|
|
593
|
+
| `--Brand-Primary` | Primary brand color | `217 91% 60%` (Blue) |
|
|
594
|
+
| `--Text-Primary` | Main text color | `0 0% 0%` |
|
|
595
|
+
| `--Text-Secondary` | Secondary text | `0 0% 40%` |
|
|
596
|
+
| `--BG-Primary` | Main background | `0 0% 100%` |
|
|
597
|
+
| `--BG-Secondary` | Secondary background | `0 0% 98%` |
|
|
598
|
+
| `--Stroke-Primary` | Border colors | `0 0% 80%` |
|
|
599
|
+
| `--Status-OnSale` | "On Sale" badge | `217 91% 60%` |
|
|
600
|
+
| `--Status-SellingFast` | "Selling Fast" badge | `38 92% 50%` |
|
|
601
|
+
| `--Status-SoldOut` | "Sold Out" badge | `0 84% 60%` |
|
|
602
|
+
| `--Today-BG` | Today's date background | `217 91% 97%` |
|
|
603
|
+
| `--Focus-Ring` | Keyboard focus ring | `217 91% 60%` |
|
|
604
|
+
|
|
605
|
+
### Using JavaScript Theme Utilities
|
|
606
|
+
|
|
607
|
+
```javascript
|
|
608
|
+
import {
|
|
609
|
+
applyTheme,
|
|
610
|
+
themes,
|
|
611
|
+
generateThemeCSS,
|
|
612
|
+
} from '@getmicdrop/venue-calendar';
|
|
613
|
+
|
|
614
|
+
// Apply a preset theme
|
|
615
|
+
applyTheme(themes.dark);
|
|
616
|
+
|
|
617
|
+
// Apply to a specific container
|
|
618
|
+
const container = document.querySelector('.micdrop-calendar-container');
|
|
619
|
+
applyTheme(themes.dark, container);
|
|
620
|
+
|
|
621
|
+
// Create a custom theme
|
|
622
|
+
const myTheme = {
|
|
623
|
+
brandPrimary: '270 76% 60%', // Purple
|
|
624
|
+
textPrimary: '0 0% 10%',
|
|
625
|
+
bgPrimary: '0 0% 100%',
|
|
626
|
+
statusOnSale: '142 71% 45%', // Green for on sale
|
|
627
|
+
};
|
|
628
|
+
applyTheme(myTheme);
|
|
629
|
+
|
|
630
|
+
// Generate CSS string for embedding
|
|
631
|
+
const cssString = generateThemeCSS(myTheme);
|
|
632
|
+
console.log(cssString);
|
|
633
|
+
// Output: :root { --Brand-Primary: 270 76% 60%; ... }
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Preset Themes
|
|
637
|
+
|
|
638
|
+
Three themes are included out of the box:
|
|
639
|
+
|
|
640
|
+
```javascript
|
|
641
|
+
import { themes } from '@getmicdrop/venue-calendar';
|
|
642
|
+
|
|
643
|
+
// Light theme (default)
|
|
644
|
+
applyTheme(themes.light);
|
|
645
|
+
|
|
646
|
+
// Dark theme
|
|
647
|
+
applyTheme(themes.dark);
|
|
648
|
+
|
|
649
|
+
// High contrast (accessibility)
|
|
650
|
+
applyTheme(themes.highContrast);
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### Automatic Dark Mode
|
|
654
|
+
|
|
655
|
+
The calendar automatically respects the user's system preference:
|
|
656
|
+
|
|
657
|
+
```css
|
|
658
|
+
/* Automatically applied when user prefers dark mode */
|
|
659
|
+
@media (prefers-color-scheme: dark) {
|
|
660
|
+
/* Dark theme variables are applied */
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
You can also manually toggle dark mode:
|
|
665
|
+
|
|
666
|
+
```html
|
|
667
|
+
<!-- Add 'dark' class to enable dark theme -->
|
|
668
|
+
<div class="dark">
|
|
669
|
+
<div class="micdrop-calendar-container" data-venue-id="123"></div>
|
|
670
|
+
</div>
|
|
671
|
+
|
|
672
|
+
<!-- Or use data-theme attribute -->
|
|
673
|
+
<div data-theme="dark">
|
|
674
|
+
<div class="micdrop-calendar-container" data-venue-id="123"></div>
|
|
675
|
+
</div>
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
## Localization and the CDN bundle
|
|
679
|
+
|
|
680
|
+
The calendar and the checkout speak thirteen languages. English is built into the
|
|
681
|
+
bundle; the other twelve are **fetched at runtime**, one file, only for the
|
|
682
|
+
locale actually in use — so a buyer never downloads twelve languages to read one.
|
|
683
|
+
This is what keeps the CDN bundle at ~594 KB gzipped instead of ~686 KB.
|
|
684
|
+
|
|
685
|
+
For the npm package nothing is required: your bundler code-splits the catalogues
|
|
686
|
+
and addresses them itself.
|
|
687
|
+
|
|
688
|
+
For the `<script>` embed, the bundle works out where to fetch from by looking at
|
|
689
|
+
the URL it was itself served from, and loads a **version-pinned sibling**:
|
|
690
|
+
|
|
691
|
+
```
|
|
692
|
+
https://get-micdrop.com/embed/venue-calendar.iife.js
|
|
693
|
+
https://get-micdrop.com/embed/locales/<version>/main/es.js ← calendar copy
|
|
694
|
+
https://get-micdrop.com/embed/locales/<version>/flow/es.js ← checkout copy
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
The calendar itself loads the same way. `venue-calendar.iife.js` is a small
|
|
698
|
+
loader: it fetches the first piece (enough to draw a saved look's card) and,
|
|
699
|
+
once the card is up, the rest of the widget, all from a version-pinned
|
|
700
|
+
`looks/<version>/` directory beside it. Until the rest has loaded, the
|
|
701
|
+
`window.VenueCalendar` functions return promises that resolve to what the
|
|
702
|
+
function returns; after that they are the functions themselves.
|
|
703
|
+
|
|
704
|
+
If you self-host the bundle, **copy the `dist/locales/`, `dist/looks/` and
|
|
705
|
+
`dist/checkout-libs/` directories alongside it**.
|
|
706
|
+
Version-pinned paths mean new releases only ever add files; they never overwrite
|
|
707
|
+
the catalogue an older pinned bundle is using.
|
|
708
|
+
|
|
709
|
+
### When the fetch cannot happen
|
|
710
|
+
|
|
711
|
+
If the locale file cannot be loaded — a Content-Security-Policy that allowlists
|
|
712
|
+
the exact script file rather than the origin, an offline CDN, or a
|
|
713
|
+
`<script type="module">` embed where the bundle cannot see its own URL — the
|
|
714
|
+
calendar simply stays in English. Nothing errors and nothing breaks; the widget
|
|
715
|
+
renders and sells tickets exactly as it does for an English buyer.
|
|
716
|
+
|
|
717
|
+
The calendar's own files are a different matter: if `looks/<version>/` cannot
|
|
718
|
+
be loaded, nothing draws, and the console names the file that failed. The two
|
|
719
|
+
overrides below fix the URL case; a Content-Security-Policy has to allow the
|
|
720
|
+
`get-micdrop.com/embed/` directory, not one file in it.
|
|
721
|
+
|
|
722
|
+
Two ways to point it at the right place when it cannot work it out:
|
|
723
|
+
|
|
724
|
+
```html
|
|
725
|
+
<!-- Option A: tell it before the bundle loads -->
|
|
726
|
+
<script>
|
|
727
|
+
window.__MICDROP_CALENDAR_ASSET_BASE__ = 'https://get-micdrop.com/embed/';
|
|
728
|
+
</script>
|
|
729
|
+
<script
|
|
730
|
+
defer
|
|
731
|
+
src="https://get-micdrop.com/embed/venue-calendar.iife.js"
|
|
732
|
+
></script>
|
|
733
|
+
|
|
734
|
+
<!-- Option B: put it on the tag -->
|
|
735
|
+
<script
|
|
736
|
+
defer
|
|
737
|
+
src="https://get-micdrop.com/embed/venue-calendar.iife.js"
|
|
738
|
+
data-vc-base="https://get-micdrop.com/embed/"
|
|
739
|
+
></script>
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
`defer` and `async` need no override — a classic script still knows its own URL.
|
|
743
|
+
|
|
744
|
+
### First paint is always English
|
|
745
|
+
|
|
746
|
+
A non-English buyer sees English for a moment on a cold load and the page swaps
|
|
747
|
+
to their language when the catalogue arrives. This is deliberate: the calendar
|
|
748
|
+
paints immediately rather than waiting on a translation file.
|
|
749
|
+
|
|
750
|
+
## Browser Support
|
|
751
|
+
|
|
752
|
+
- Chrome (latest)
|
|
753
|
+
- Firefox (latest)
|
|
754
|
+
- Safari (latest)
|
|
755
|
+
- Edge (latest)
|
|
756
|
+
- Mobile browsers (iOS Safari, Chrome Mobile)
|
|
757
|
+
|
|
758
|
+
## Development
|
|
759
|
+
|
|
760
|
+
### Building the Package
|
|
761
|
+
|
|
762
|
+
```bash
|
|
763
|
+
# Install dependencies
|
|
764
|
+
npm install
|
|
765
|
+
|
|
766
|
+
# Build the library
|
|
767
|
+
npm run build:lib
|
|
768
|
+
|
|
769
|
+
# Development mode (SvelteKit app)
|
|
770
|
+
npm run dev
|
|
771
|
+
|
|
772
|
+
# Preview production build
|
|
773
|
+
npm run preview
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
`build:lib` is three passes and the order matters: the IIFE pass runs first and
|
|
777
|
+
owns the `dist/` wipe, the ES/UMD pass appends to it, and
|
|
778
|
+
`vite.config.locales.js` appends the runtime locale catalogues
|
|
779
|
+
(`dist/locales/<version>/{main,flow}/<tag>.js`) last. `npm run size` fails if the
|
|
780
|
+
bundle and its catalogues do not both come out of that.
|
|
781
|
+
|
|
782
|
+
### Project Structure
|
|
783
|
+
|
|
784
|
+
```
|
|
785
|
+
venue-calendar/
|
|
786
|
+
├── src/
|
|
787
|
+
│ ├── components/ # Svelte components
|
|
788
|
+
│ │ ├── Calendar/
|
|
789
|
+
│ │ ├── CalendarContainer/
|
|
790
|
+
│ │ └── Button/
|
|
791
|
+
│ ├── lib/ # Library entry points
|
|
792
|
+
│ │ ├── VenueCalendar.js
|
|
793
|
+
│ │ └── web-component.js
|
|
794
|
+
│ └── routes/ # SvelteKit routes (for dev)
|
|
795
|
+
├── dist/ # Built package (generated)
|
|
796
|
+
│ └── locales/<version>/ # Runtime locale catalogues for the CDN bundle
|
|
797
|
+
├── package.json
|
|
798
|
+
├── vite.config.lib.js # Library build config (ES/UMD + IIFE passes)
|
|
799
|
+
├── vite.config.locales.js # Emits the runtime locale catalogues
|
|
800
|
+
└── README.md
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
### Lockfile policy
|
|
804
|
+
|
|
805
|
+
`package-lock.json` is the single canonical lockfile — CI and the publish
|
|
806
|
+
workflow install with `npm ci`. Do not commit `yarn.lock` or
|
|
807
|
+
`pnpm-lock.yaml` (both gitignored). Local dev machines may use pnpm for the
|
|
808
|
+
svelte-components symlink workflow, but dependency changes must land in
|
|
809
|
+
`package-lock.json` via npm.
|
|
810
|
+
|
|
811
|
+
## API Reference
|
|
812
|
+
|
|
813
|
+
### `initVenueCalendar(options)`
|
|
814
|
+
|
|
815
|
+
Initialize a calendar instance.
|
|
816
|
+
|
|
817
|
+
**Parameters:**
|
|
818
|
+
|
|
819
|
+
- `options` (Object): Configuration options
|
|
820
|
+
|
|
821
|
+
**Returns:** Svelte component instance
|
|
822
|
+
|
|
823
|
+
**Example:**
|
|
824
|
+
|
|
825
|
+
```javascript
|
|
826
|
+
const calendar = initVenueCalendar({
|
|
827
|
+
target: '#calendar',
|
|
828
|
+
venueId: 'venue-123',
|
|
829
|
+
view: 'calendar',
|
|
830
|
+
});
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
### `autoMount()`
|
|
834
|
+
|
|
835
|
+
Automatically mount calendars to all elements with class `micdrop-calendar-container`.
|
|
836
|
+
|
|
837
|
+
**Example:**
|
|
838
|
+
|
|
839
|
+
```javascript
|
|
840
|
+
import { autoMount } from '@getmicdrop/venue-calendar';
|
|
841
|
+
autoMount();
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Component Events
|
|
845
|
+
|
|
846
|
+
The calendar component emits events that you can listen to:
|
|
847
|
+
|
|
848
|
+
```javascript
|
|
849
|
+
const calendar = initVenueCalendar({
|
|
850
|
+
target: '#calendar',
|
|
851
|
+
// ... other options
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
// Listen to component events (if using Svelte component directly)
|
|
855
|
+
calendar.$on('eventClick', event => {
|
|
856
|
+
console.log('Event clicked:', event.detail);
|
|
857
|
+
});
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
## Troubleshooting
|
|
861
|
+
|
|
862
|
+
### Calendar not appearing
|
|
863
|
+
|
|
864
|
+
1. **Check the script is loaded**: Open browser console and verify no errors
|
|
865
|
+
2. **Verify container exists**: Make sure the target element exists in the DOM
|
|
866
|
+
3. **Check data attributes**: Ensure attributes are correctly formatted with `data-` prefix
|
|
867
|
+
|
|
868
|
+
### Styles not applying
|
|
869
|
+
|
|
870
|
+
1. **CSS not loaded**: The styles are bundled in the JS file and auto-injected — no separate stylesheet needed
|
|
871
|
+
2. **CSS conflicts**: Check if other styles are overriding the calendar styles
|
|
872
|
+
3. **Bundle didn't load**: Confirm the `<script src>` points at the Micdrop-hosted bundle and returns 200 (not 404)
|
|
873
|
+
|
|
874
|
+
### Events not showing
|
|
875
|
+
|
|
876
|
+
1. **Check event data format**: Ensure events match the expected structure
|
|
877
|
+
2. **Date format**: Use ISO 8601 format for dates (`YYYY-MM-DDTHH:mm:ssZ`)
|
|
878
|
+
3. **Venue ID**: Verify the venue ID is correct
|
|
879
|
+
|
|
880
|
+
## Contributing
|
|
881
|
+
|
|
882
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
883
|
+
|
|
884
|
+
## License
|
|
885
|
+
|
|
886
|
+
MIT © MicDrop
|
|
887
|
+
|
|
888
|
+
## Support
|
|
889
|
+
|
|
890
|
+
For issues, questions, or feature requests, please visit:
|
|
891
|
+
https://github.com/get-micdrop/venue-calendar/issues
|
|
892
|
+
|
|
893
|
+
---
|
|
894
|
+
|
|
895
|
+
Made with ❤️ by the MicDrop team
|