npm package: @momentco-ai/moment-sdk
Description: Embeddable calendar sync widget for external team websites
Author: Moment Co.
Latest version: 0.1.2

# Moment SDK

Embeddable calendar sync widget for external team websites. Zero runtime dependencies.

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

---

## Installation

Add the SDK via a script tag:

```html
<script src="https://unpkg.com/@momentco-ai/moment-sdk"></script>
```

Or via npm:

```bash
npm install @momentco-ai/moment-sdk
```

---

## Quick Start

```html
<!-- 1. Add trigger buttons with data attributes -->
<button
  class="moment-sync-trigger"
  data-moment-team-slug="your-team-slug"
  data-external-event-id="event-001"
  data-moment-trigger-type="moment"
>
  Add to Calendar
</button>

<!-- 2. Load the SDK and initialize -->
<script src="https://unpkg.com/@momentco-ai/moment-sdk"></script>
<script>
  const sdk = new MomentSdk({
    onSuccess: (result) => console.log('Synced!', result),
    onError: (result) => console.error('Failed', result),
    onClose: (result) => console.log('Closed', result),
  });
</script>
```

That's it — clicking the button opens a modal where users can sync the event to Google Calendar or Outlook.

See [`examples/basic/`](./examples/basic/) for a complete working example.

---

## Init Options

| Option            | Type                | Required | Description                                                        |
| ----------------- | ------------------- | -------- | ------------------------------------------------------------------ |
| `triggerSelector` | `string`            | No       | CSS selector for trigger elements. Default: `.moment-sync-trigger` |
| `onSuccess`       | `(payload) => void` | No       | Called on successful calendar sync                                 |
| `onError`         | `(payload) => void` | No       | Called on sync failure                                             |
| `onClose`         | `(payload) => void` | No       | Called when modal closes (success, error, or cancel)               |
| `onAnalytics`     | `(event) => void`   | No       | Called for every analytics event                                   |

---

## Data Attributes

Place these on any element matching the trigger selector (default: `.moment-sync-trigger`):

| Attribute                  | Required | Description                                                  |
| -------------------------- | -------- | ------------------------------------------------------------ |
| `data-moment-team-slug`    | ✅       | Team/brand slug                                              |
| `data-external-event-id`   | No       | Specific event identifier (resolved to real ID by Moment)    |
| `data-moment-list-slug`    | No       | List slug (resolved to moment IDs by Moment)                 |
| `data-moment-trigger-type` | No       | `moment` (default), `list`, or `schedule`                    |
| `data-moment-ids`          | No       | Comma-separated moment IDs (fallback if slugs don't resolve) |
| `data-moment-game-id`      | No       | Alias for `data-moment-ids`                                  |
| `data-moment-calendar`     | No       | Pre-select provider: `google` or `outlook`                   |

---

## Programmatic API

You can also open the modal programmatically instead of relying on data attributes:

```html
<script>
  const sdk = new MomentSdk({
    /* callbacks */
  });

  // Open modal
  sdk.open({
    teamSlug: 'your-team-slug',
    externalEventId: 'event-123',
    triggerType: 'moment',
    ids: ['moment-id-1'],
    calendar: 'google', // optional: skip provider selection
  });

  // Close modal
  sdk.close();

  // Re-bind triggers after dynamic DOM updates
  sdk.rebind();

  // Destroy instance entirely
  sdk.destroy();
</script>
```

---

## `createMomentButton()`

Programmatically create a styled trigger button:

```html
<script>
  const btn = createMomentButton({
    teamSlug: 'your-team-slug',
    externalEventId: 'event-001',
    triggerType: 'moment',
    label: 'Add to Calendar',
  });

  document.getElementById('container').appendChild(btn);
</script>
```

The button renders with Moment's default styling (stone-900 background, subtle border, rounded corners). Override with CSS or pass a `className` option.

### Styling, fonts, and labels

You can customize trigger button appearance in a few ways:

```html
<style>
  .my-calendar-btn {
    font-family:
      Inter,
      system-ui,
      -apple-system,
      sans-serif;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.01em;
    border-radius: 9999px;
    padding: 10px 18px;
    border: 1px solid #1e3a8a;
    background: #1d4ed8;
    color: #ffffff;
  }

  .my-calendar-btn:hover {
    background: #1e40af;
  }
</style>

<script>
  const primaryBtn = createMomentButton({
    teamSlug: 'your-team-slug',
    externalEventId: 'event-001',
    triggerType: 'moment',
    label: 'Get Tickets + Calendar',
    className: 'my-calendar-btn',
  });

  document.getElementById('container').appendChild(primaryBtn);
</script>
```

You can also create plain HTML triggers and fully own styles/text:

```html
<button
  class="my-calendar-btn moment-sync-trigger"
  data-moment-team-slug="your-team-slug"
  data-external-event-id="event-001"
  data-moment-trigger-type="moment"
>
  Add This Match to My Calendar
</button>

<script src="https://unpkg.com/@momentco-ai/moment-sdk"></script>
<script>
  new MomentSdk();
</script>
```

Note: these customization options apply to trigger buttons. The modal UI itself is hosted in a secure iframe and is not themed by host-page CSS.

---

## Analytics Events

The `onAnalytics` callback receives events with these names:

| Event                 | When                                |
| --------------------- | ----------------------------------- |
| `embed.init`          | SDK initialized                     |
| `embed.trigger.click` | User clicked a trigger button       |
| `embed.open`          | Modal iframe opened                 |
| `oauth.start`         | OAuth popup requested               |
| `oauth.popup.blocked` | Browser blocked the popup           |
| `oauth.popup.closed`  | User closed popup before completing |
| `subscribe.success`   | Calendar sync succeeded             |
| `subscribe.error`     | Calendar sync failed                |
| `embed.close`         | Modal closed                        |

---

## Result Payload

All callbacks (`onSuccess`, `onError`, `onClose`) receive a result payload:

```json
{
  "source": "moment-live-embed",
  "type": "moment.embed.result",
  "result": "success | error | cancelled",
  "provider": "google | outlook",
  "triggerType": "moment | list | schedule",
  "momentIds": ["..."],
  "message": "optional details"
}
```

---

## Examples

See the [`examples/basic/`](./examples/basic/) directory for a complete standalone integration example.

---

## Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.

## Security

See [SECURITY.md](./SECURITY.md) for reporting vulnerabilities.

## License

[MIT](./LICENSE) — Moment Co.