# @turbo-player/integration-web-component

## Introduction

`@turbo-player/integration-web-component` exposes a Web Component and types to easily integrate the turbo player.

If you use React, you can install the [@turbo-player/integration-react](https://www.npmjs.com/package/@turbo-player/integration-react) package instead.

## Usage

### Loading & integrating the player (TypeScript)

```ts
import {
  IntegrationEvent,
  createIntegrationClient
} from '@turbo-player/integration-web-component';

// provided by the turbo player team
const MODULE_URL = 'https://player.example.com/integration.js';
// matches the custom element tag name defined in the integration script (MODULE_URL)
const TAG_NAME = 'my-integration';

const client = createIntegrationClient({
  moduleUrl: MODULE_URL,
  tagName: TAG_NAME
});

// Get the container element where the player will be placed
const container = document.getElementById('player-container-on-site');
const integrationId = 'FILL_IN_INTEGRATION_ID';
const playlistId = 'FILL_IN_PLAYLIST_ID';
// It makes sense to load integration css
// as early as possible to reduce layout shifts.
client.loadStyles(integrationId);
// load the integration web component
client.loadComponent();
// create the fully typed integration element
const integration = document.createElement(TAG_NAME);
integration.setAttribute('integration-id', integrationId);
integration.setAttribute('playlist-id', playlistId);
integration.addEventListener(IntegrationEvent.CONTENT_START, () => {
  console.log('content start', integration.content);
});
// attach the integration element
container.appendChild(integration);
// wait until the integration was upgraded to access web component methods
await window.customElements.whenDefined(TAG_NAME);
integration.play();
```

### Implementing a public API script (TypeScript)

```ts
import {
  IntegrationEvent,
  type ConnectIntegration
} from '@turbo-player/integration-web-component';

// with this you get a fully typed integration
export const connectIntegration: ConnectIntegration = (integration) => {
  integration.addEventListener(IntegrationEvent.CONTENT_PLAY, () => {
    console.log('play', integration.content);
  });
};
```

### Host Context

Use `getHostContext()` to provide global application context and provider-specific user tokens to all integration instances on the page.

`getHostContext()` waits for the integration component to be loaded and returns the same singleton instance that the running player uses.

```ts
import { createIntegrationClient } from '@turbo-player/integration-web-component';

// provided by the turbo player team
const MODULE_URL = 'https://player.example.com/integration.js';
// matches the custom element tag name defined in the integration script (MODULE_URL)
const TAG_NAME = 'my-integration';

const client = createIntegrationClient({
  moduleUrl: MODULE_URL,
  tagName: TAG_NAME
});

const hostContext = await client.getHostContext();

hostContext.set({
  // Plain values — used as-is
  appVersion: '2.3.0',
  appName: 'my-app',
  deviceId: { id: '...', name: 'idfa' },

  // Resolver functions — called each time the player needs the value,
  // so they can return fresh data (e.g. after consent changes)
  userIds: {
    // Each key is the ID name; the value is a static definition or a resolver function.
    // Return null to explicitly opt out (e.g. when consent is missing).
    netId: async ({ consent }) => consent ? { id: await cmp.getNetId() } : null,
  },

  // Provider-specific context (tokens, subscription state, ...)
  providers: {
    'my-provider': async () => ({
      token: await myAuth.getToken(),
      subscriptionState: userState
    })
  }
});
```

Calling `set()` multiple times merges incrementally — previously set values are preserved unless overwritten:

```ts
// Initial setup
hostContext.set({ appVersion: '2.3.0', appName: 'my-app' });

// Later — adds providers without removing appVersion/appName
hostContext.set({
  providers: {
    'my-provider': async () => ({ token: await myAuth.getToken() })
  }
});
```
