@touchcastllc/napster-companion-api 1.0.0-alpha.3 → 1.0.0-alpha.30

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 (118) hide show
  1. package/README.md +527 -731
  2. package/lib/components/Avatar/index.d.ts +31 -2
  3. package/lib/components/Embed/index.d.ts +21 -2
  4. package/lib/components/InactiveOverlay/index.d.ts +15 -2
  5. package/lib/components/Preview/index.d.ts +18 -2
  6. package/lib/components/StyledTooltip/index.d.ts +16 -2
  7. package/lib/components/VolumeControl/index.d.ts +18 -0
  8. package/lib/components/WaveForm/index.d.ts +16 -2
  9. package/lib/components/index.d.ts +2 -7
  10. package/lib/constants/events.d.ts +50 -0
  11. package/lib/constants/greenscreen.d.ts +28 -0
  12. package/lib/constants/index.d.ts +6 -0
  13. package/lib/constants/waveform.d.ts +34 -0
  14. package/lib/index.css +1 -1
  15. package/lib/index.d.ts +20 -14
  16. package/lib/index.esm.js +1 -2
  17. package/lib/index.js +1 -2
  18. package/lib/index.standalone.js +1 -22616
  19. package/lib/services/analytics.d.ts +59 -41
  20. package/lib/services/webrtc.d.ts +27 -0
  21. package/lib/setupTests.d.ts +0 -1
  22. package/lib/stores/index.d.ts +3 -4
  23. package/lib/stores/middleware/featuresUpdateMiddleware.d.ts +0 -1
  24. package/lib/stores/selectors.d.ts +30 -0
  25. package/lib/stores/slices/appSlice.d.ts +2 -2
  26. package/lib/stores/slices/avatarSlice.d.ts +1 -3
  27. package/lib/stores/store.d.ts +4 -5
  28. package/lib/types/abstract-typing.d.ts +35 -0
  29. package/lib/types/analytics.d.ts +95 -0
  30. package/lib/types/errors.d.ts +0 -1
  31. package/lib/types/index.d.ts +120 -39
  32. package/lib/umd.d.ts +0 -1
  33. package/lib/utils/InactiveOverlayManager.d.ts +77 -0
  34. package/lib/utils/classnames.d.ts +49 -0
  35. package/lib/utils/debug.d.ts +84 -0
  36. package/lib/utils/domFactory.d.ts +56 -0
  37. package/lib/utils/greenscreen/GreenScreenProcessor.d.ts +25 -0
  38. package/lib/utils/greenscreen/index.d.ts +1 -0
  39. package/lib/utils/index.d.ts +5 -1
  40. package/lib/utils/sendCommand.d.ts +2 -0
  41. package/lib/utils/svg.d.ts +32 -0
  42. package/package.json +19 -24
  43. package/lib/CompanionApiProvider.d.ts +0 -22
  44. package/lib/CompanionApiProvider.d.ts.map +0 -1
  45. package/lib/assets/fonts/segoe/SegoeUI-Bold.eot +0 -0
  46. package/lib/assets/fonts/segoe/SegoeUI-Bold.svg +0 -1541
  47. package/lib/assets/fonts/segoe/SegoeUI-Bold.ttf +0 -0
  48. package/lib/assets/fonts/segoe/SegoeUI-Bold.woff +0 -0
  49. package/lib/assets/fonts/segoe/SegoeUI-Bold.woff2 +0 -0
  50. package/lib/assets/fonts/segoe/SegoeUI.eot +0 -0
  51. package/lib/assets/fonts/segoe/SegoeUI.svg +0 -1521
  52. package/lib/assets/fonts/segoe/SegoeUI.ttf +0 -0
  53. package/lib/assets/fonts/segoe/SegoeUI.woff +0 -0
  54. package/lib/assets/fonts/segoe/SegoeUI.woff2 +0 -0
  55. package/lib/components/Avatar/Avatar.d.ts +0 -12
  56. package/lib/components/Avatar/Avatar.d.ts.map +0 -1
  57. package/lib/components/Avatar/index.d.ts.map +0 -1
  58. package/lib/components/Embed/Embed.d.ts +0 -17
  59. package/lib/components/Embed/Embed.d.ts.map +0 -1
  60. package/lib/components/Embed/index.d.ts.map +0 -1
  61. package/lib/components/InactiveOverlay/InactiveOverlay.d.ts +0 -12
  62. package/lib/components/InactiveOverlay/InactiveOverlay.d.ts.map +0 -1
  63. package/lib/components/InactiveOverlay/index.d.ts.map +0 -1
  64. package/lib/components/Preview/Preview.d.ts +0 -13
  65. package/lib/components/Preview/Preview.d.ts.map +0 -1
  66. package/lib/components/Preview/index.d.ts.map +0 -1
  67. package/lib/components/StyledTooltip/StyledTooltip.d.ts +0 -12
  68. package/lib/components/StyledTooltip/StyledTooltip.d.ts.map +0 -1
  69. package/lib/components/StyledTooltip/index.d.ts.map +0 -1
  70. package/lib/components/WaveForm/WaveForm.d.ts +0 -16
  71. package/lib/components/WaveForm/WaveForm.d.ts.map +0 -1
  72. package/lib/components/WaveForm/index.d.ts.map +0 -1
  73. package/lib/components/index.d.ts.map +0 -1
  74. package/lib/hooks/index.d.ts +0 -5
  75. package/lib/hooks/index.d.ts.map +0 -1
  76. package/lib/hooks/useApp.d.ts +0 -25
  77. package/lib/hooks/useApp.d.ts.map +0 -1
  78. package/lib/hooks/useAvatar.d.ts +0 -70
  79. package/lib/hooks/useAvatar.d.ts.map +0 -1
  80. package/lib/hooks/useMicrophones.d.ts +0 -8
  81. package/lib/hooks/useMicrophones.d.ts.map +0 -1
  82. package/lib/hooks/useWebRTC.d.ts +0 -22
  83. package/lib/hooks/useWebRTC.d.ts.map +0 -1
  84. package/lib/index-legacy.d.ts +0 -27
  85. package/lib/index-legacy.d.ts.map +0 -1
  86. package/lib/index-legacy.esm.js +0 -2
  87. package/lib/index-legacy.esm.js.map +0 -1
  88. package/lib/index-legacy.js +0 -2
  89. package/lib/index-legacy.js.map +0 -1
  90. package/lib/index.d.ts.map +0 -1
  91. package/lib/index.esm.js.map +0 -1
  92. package/lib/index.js.map +0 -1
  93. package/lib/index.standalone.js.map +0 -1
  94. package/lib/index.standalone.min.js +0 -11
  95. package/lib/index.standalone.min.js.map +0 -1
  96. package/lib/index.umd.js +0 -19945
  97. package/lib/index.umd.js.map +0 -1
  98. package/lib/index.umd.min.js +0 -11
  99. package/lib/index.umd.min.js.map +0 -1
  100. package/lib/sdk-base-CfUSsjvT.js +0 -7
  101. package/lib/sdk-base-CfUSsjvT.js.map +0 -1
  102. package/lib/sdk-base-DYRT4bHm.js +0 -7
  103. package/lib/sdk-base-DYRT4bHm.js.map +0 -1
  104. package/lib/sdk-base.d.ts +0 -69
  105. package/lib/sdk-base.d.ts.map +0 -1
  106. package/lib/services/analytics.d.ts.map +0 -1
  107. package/lib/setupTests.d.ts.map +0 -1
  108. package/lib/stores/hooks.d.ts +0 -8
  109. package/lib/stores/hooks.d.ts.map +0 -1
  110. package/lib/stores/index.d.ts.map +0 -1
  111. package/lib/stores/middleware/featuresUpdateMiddleware.d.ts.map +0 -1
  112. package/lib/stores/slices/appSlice.d.ts.map +0 -1
  113. package/lib/stores/slices/avatarSlice.d.ts.map +0 -1
  114. package/lib/stores/store.d.ts.map +0 -1
  115. package/lib/types/errors.d.ts.map +0 -1
  116. package/lib/types/index.d.ts.map +0 -1
  117. package/lib/umd.d.ts.map +0 -1
  118. package/lib/utils/index.d.ts.map +0 -1
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@touchcastllc/napster-companion-api.svg)](https://www.npmjs.com/package/@touchcastllc/napster-companion-api)
4
4
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
5
 
6
- > A powerful, flexible JavaScript SDK for integrating AI-powered avatar experiences into your web application. Build with **Napster** and deliver engaging, interactive content across all major frameworks and deployment scenarios.
6
+ > Real-time conversational video AI for web applications. Embed AI companions that users can talk to face-to-face via WebRTC. Attaches to any DOM element, handles video streaming and avatar rendering, connects to Azure OpenAI for conversation.
7
7
 
8
8
  **Supported Environments:**
9
9
 
@@ -15,47 +15,37 @@
15
15
 
16
16
  **Key Capabilities:**
17
17
 
18
- - 🎯 **Multiple Build Targets**: Support for ES modules, CommonJS, UMD, and standalone bundles
19
- - 🔄 **React 16-19 Compatible**: Full support from React 16.0 through React 19.x
20
- - 🚪 **Dual Entry Points**: Modern (React 18+) and Legacy (React 16+) versions
21
- - 📦 **Tree-Shakeable**: Only import what you need for optimal bundle sizes
22
- - **Zero External Dependencies** (Standalone): Drop in a script tag and go
23
- - **Advanced Features**: Auto-play, waveform visualization, background removal, inactive timeouts, and more
24
- - 🔧 **TypeScript Support**: Full type definitions for a great developer experience
25
- - 🚀 **Production Ready**: Minified builds with source maps for debugging
18
+ - **WebRTC Video Streaming:** Real-time video with AI avatars
19
+ - **Framework Agnostic:** React, Vue, Angular, or vanilla JS
20
+ - **Zero External Dependencies:** Drop in a script tag and go
21
+ - **TypeScript Support:** Fully typed APIs
22
+ - **Tree-Shakeable:** Import only what you need
23
+ - **Production Ready:** Minified builds with type definitions
26
24
 
27
25
  ---
28
26
 
29
- ## 2. Quick Start
27
+ ## 1. Quick Start
30
28
 
31
29
  Get up and running in minutes. Follow these four steps to integrate the SDK into your project.
32
30
 
33
- ### 2.1 Choose Your Setup
31
+ ### 1.1 Choose Your Setup
34
32
 
35
33
  Pick the integration method that matches your project:
36
34
 
37
- | Build Type | Best For | Import Path | React Included? |
38
- | --------------------------- | ----------------------------------- | -------------------------------------------- | --------------- |
39
- | **React 18+** (Bundler) | Modern React apps with Vite/Webpack | `@touchcastllc/napster-companion-api` | No (peer dep) |
40
- | **React 16/17** (Legacy) | React 16/17 apps with bundlers | `@touchcastllc/napster-companion-api/legacy` | No (peer dep) |
41
- | **UMD** (Script Tag) | Browser, bring your own React 18+ | `lib/index.umd.min.js` | No |
42
- | **Standalone** (Script Tag) | Browser, zero dependencies | `lib/index.standalone.min.js` | Yes |
43
- | **Core** (Headless) | Custom UI, framework-agnostic | `@touchcastllc/napster-companion-api/core` | No |
35
+ | Build Type | Best For | Import Path | Dependencies |
36
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------- |
37
+ | **ESM** | **Recommended for most projects**<br>✅ You use a bundler (Vite, Webpack, Rollup, etc.)<br>✅ You want optimal bundle size (dependencies not bundled)<br>✅ You're using TypeScript or modern JavaScript | `@touchcastllc/napster-companion-api` | Redux Toolkit (peer) |
38
+ | **Standalone** | ✅ You want a `<script>` tag (no bundler, no external dependencies)<br>✅ You want zero external dependencies<br>✅ You don't want to manage dependencies separately<br>✅ You're okay with a slightly larger file (all dependencies included) | `lib/index.standalone.js` | All bundled |
44
39
 
45
- **Quick Links:**
40
+ ---
46
41
 
47
- - [React 18+ Example](#react-18-hooks)
48
- - [React 16/17 Example](#react-1617-class-component)
49
- - [Vue 3 Example](#vue-3)
50
- - [Vue 2 Example](#vue-2)
51
- - [Angular Example](#angular)
52
- - [Vanilla JS Example](#vanilla-js--core-no-build-tools)
42
+ ### 1.2 Installation & Setup
53
43
 
54
- ### 2.2 Installation & Import
44
+ #### 1.2.1 For ESM Build Type (Recommended)
55
45
 
56
- #### For Bundler-Based Projects
46
+ **Step 1: Install the SDK**
57
47
 
58
- **Install the package:**
48
+ Install the package:
59
49
 
60
50
  ```bash
61
51
  npm install @touchcastllc/napster-companion-api
@@ -63,117 +53,150 @@ npm install @touchcastllc/napster-companion-api
63
53
  yarn add @touchcastllc/napster-companion-api
64
54
  ```
65
55
 
66
- **Install peer dependencies:**
56
+ Install peer dependencies:
67
57
 
68
58
  ```bash
69
- # For React 18+
70
- npm install react@^18 react-dom@^18 @reduxjs/toolkit@^2 react-redux@^9
71
-
72
- # For React 16/17
73
- npm install react@^16 react-dom@^16 @reduxjs/toolkit@^2 react-redux@^8
59
+ npm install @reduxjs/toolkit
74
60
  ```
75
61
 
76
- **Import the SDK:**
62
+ **Step 2: Import the SDK**
77
63
 
78
64
  ```typescript
79
- // React 18+
80
65
  import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
81
-
82
- // React 16/17
83
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api/legacy";
84
66
  ```
85
67
 
86
- **Import CSS (required):**
68
+ **Also, import CSS Stylesheet (required):**
69
+
70
+ The SDK comes with a complete stylesheet for all components. Import it in your application:
71
+
72
+ **ESM/TypeScript:**
87
73
 
88
74
  ```typescript
89
- import "@touchcastllc/napster-companion-api/lib/index.css";
75
+ import "@touchcastllc/napster-companion-api/styles";
90
76
  ```
91
77
 
92
- #### For Browser Script Tags
78
+ **CommonJS:**
79
+
80
+ ```js
81
+ require("@touchcastllc/napster-companion-api/styles");
82
+ ```
93
83
 
94
- **Option A: Standalone (Easiest - React Included)**
84
+ **HTML `<link>` Tag:**
95
85
 
96
86
  ```html
97
- <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.min.js"></script>
87
+ <link
88
+ rel="stylesheet"
89
+ href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
90
+ />
98
91
  ```
99
92
 
100
- **Option B: UMD (Smaller - Bring Your Own React)**
93
+ **CSS `@import`:**
94
+
95
+ ```css
96
+ @import url("https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css");
97
+ ```
98
+
99
+ The CSS file (`index.css`) is minified and contains all styles needed for the avatar widget, controls, tooltips, and more.
100
+
101
+ #### 1.2.2 For Standalone Build Type
102
+
103
+ **Step 1: Import the SDK**
101
104
 
102
105
  ```html
103
- <script src="https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js"></script>
104
- <script src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js"></script>
105
- <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.umd.min.js"></script>
106
+ <!-- All dependencies bundled (easier, larger file) -->
107
+ <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
106
108
  ```
107
109
 
108
- ### 2.3 Initialization
110
+ ---
111
+
112
+ ### 1.3 Initialization
113
+
114
+ #### 1.3.1 For ESM Build Type
109
115
 
110
116
  Initialize the SDK by calling `NapsterCompanionApiSdk.init()` with your auth token and configuration options.
111
117
 
118
+ See the [1.4 Authentication](#14-authentication) section for details on generating auth tokens.
119
+
112
120
  **Basic Example:**
113
121
 
114
122
  ```typescript
115
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
116
-
117
123
  const widget = await NapsterCompanionApiSdk.init("YOUR_AUTH_TOKEN", {
118
124
  mountContainer: "#avatar-container",
119
- position: "bottom-right",
120
- features: {
121
- waveform: { enabled: true },
122
- backgroundRemoval: { enabled: false },
123
- inactiveTimeout: { enabled: true, timeoutDuration: 60000 },
124
- },
125
125
  });
126
-
127
- // The returned widget object exposes control methods:
128
- // widget.showAvatar() - Show the avatar
129
- // widget.hideAvatar() - Hide the avatar
130
- // widget.destroy() - Destroy and unmount the widget
131
- // widget.updateStyles({...}) - Update widget styles dynamically
132
- // widget.enableFeature("waveform") - Enable a specific feature
133
- // widget.disableFeature("waveform") - Disable a specific feature
134
- // widget.updateFeatureConfig("waveform", { enabled: false }) - Update feature configuration
135
- // widget.setPosition("top-left") - Update widget position dynamically
136
- // widget.sendQuestion("Your question here") - Send a question to the avatar
137
126
  ```
138
127
 
139
- **What `init()` Returns:**
128
+ #### 1.3.2 For Standalone Build Type
129
+
130
+ Initialize the SDK by calling `window.napsterCompanionApiSDK.init()` with your auth token and configuration options.
140
131
 
141
- The `init()` method returns a widget instance with the following methods:
132
+ See the [1.4 Authentication](#14-authentication) section for details on generating auth tokens.
142
133
 
143
- | Method | Description |
144
- | ----------------------- | --------------------------------------------- |
145
- | `showAvatar()` | Shows the avatar |
146
- | `hideAvatar()` | Hides the avatar |
147
- | `destroy()` | Destroys and unmounts the widget from the DOM |
148
- | `updateStyles()` | Updates widget styles dynamically |
149
- | `enableFeature()` | Enables a specific feature |
150
- | `disableFeature()` | Disables a specific feature |
151
- | `updateFeatureConfig()` | Updates feature configuration |
152
- | `setPosition()` | Updates widget position dynamically |
153
- | `sendQuestion()` | Sends a question to the avatar |
134
+ **Step 1: Add container to your HTML**
135
+
136
+ ```html
137
+ <div id="sdk-container"></div>
138
+ ```
139
+
140
+ **Step 2: Initialize globally**
141
+
142
+ ```html
143
+ <script>
144
+ window.napsterCompanionApiSDK.init("AUTH_TOKEN", {
145
+ mountContainer: "#sdk-container",
146
+ });
147
+ </script>
148
+ ```
154
149
 
155
150
  ---
156
151
 
157
- ### 2.4 Authentication
152
+ ### 1.4 Authentication
158
153
 
159
154
  The SDK requires an **auth token** to connect to the Napster Companion API.
160
155
 
161
156
  **Important:** **Do not generate tokens in client-side code** — use a backend service to keep your API key secure.
162
157
 
163
- #### Step 1: Generate Napster API Key
158
+ #### Step 1: Generate Napster Companion API Key
164
159
 
165
- 1. Visit the [Napster API Keys page](https://app.cogcache.com/organization/keys)
160
+ 1. Visit the [Napster Companion API Keys page](https://companion-api.napster.com/admin/organization/keys)
166
161
  2. Click **Generate API key** and enter your details
167
162
  3. Store your API key securely on your backend server
168
163
 
169
164
  #### Step 2: Create Connection & Get Token (Backend)
170
165
 
171
- Create a backend API call to the Napster API to generate auth tokens:
166
+ Create a backend API call to the Napster Companion API to generate auth tokens:
167
+
168
+ **Request URL:**
172
169
 
173
- ```sh
174
- curl 'https://management-api.cogcache.com/public/connections' \
175
- -H 'accept: */*' \
176
- -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
170
+ ```
171
+ POST https://companion-api.napster.com/public/connections
172
+ ```
173
+
174
+ **Request Headers:**
175
+
176
+ | Header | Value |
177
+ | -------------- | ------------------- |
178
+ | `content-type` | `application/json` |
179
+ | `x-api-key` | `YOUR_API_KEY_HERE` |
180
+
181
+ **Request Body:**
182
+
183
+ | Field | Type | Description |
184
+ | ----------------------------------------------------------- | ------- | ------------------------------------ |
185
+ | `companionId` | string | Your Napster Companion ID |
186
+ | `providerConfig.type` | string | Provider type (e.g., `azureOpenAI`) |
187
+ | `providerConfig.voiceId` | string | Voice identifier (e.g., `alloy`) |
188
+ | `providerConfig.settings.instructions` | string | Custom instructions for the avatar |
189
+ | `providerConfig.settings.turnDetection.threshold` | number | Voice detection threshold |
190
+ | `providerConfig.settings.turnDetection.prefix_padding_ms` | number | Padding before speech detection (ms) |
191
+ | `providerConfig.settings.turnDetection.silence_duration_ms` | number | Silence duration threshold (ms) |
192
+ | `providerConfig.settings.temperature` | number | Response temperature (0-1) |
193
+ | `providerConfig.useGreenVideo` | boolean | Enable green screen background |
194
+ | `disableIdleTimeout` | boolean | Disable idle timeout |
195
+
196
+ **Example Request:**
197
+
198
+ ```bash
199
+ curl 'https://companion-api.napster.com/public/connections' \
177
200
  -H 'content-type: application/json' \
178
201
  -H 'x-api-key: YOUR_API_KEY_HERE' \
179
202
  --data-raw '{
@@ -191,7 +214,8 @@ curl 'https://management-api.cogcache.com/public/connections' \
191
214
  "temperature": 0
192
215
  },
193
216
  "useGreenVideo": true
194
- }
217
+ },
218
+ "disableIdleTimeout": false
195
219
  }'
196
220
  ```
197
221
 
@@ -200,835 +224,607 @@ curl 'https://management-api.cogcache.com/public/connections' \
200
224
  Fetch the token from your backend and pass it to the SDK:
201
225
 
202
226
  ```typescript
203
- // Client-side code
227
+ // Possible client-side code for token retrieval
204
228
  async function initializeAvatar() {
205
229
  // Fetch token from your backend
206
- const response = await fetch("/api/get-napster-token", { method: "POST" });
230
+ const response = await fetch("/your-backend-endpoint", { method: "POST" });
207
231
  const { token } = await response.json();
208
-
209
- // Initialize SDK with the token
210
- const widget = await NapsterCompanionApiSdk.init(token, {
211
- mountContainer: "#avatar-container",
212
- position: "bottom-right",
213
- });
214
232
  }
215
233
  ```
216
234
 
217
235
  ---
218
236
 
219
- ## 3. Feature Configuration
237
+ ## 2. Examples
220
238
 
221
- The SDK supports several configurable features. You can enable/disable them during initialization or update them dynamically at runtime.
239
+ We provide example implementations for popular frameworks and vanilla JavaScript:
222
240
 
223
- ### Available Features
241
+ ### 2.1 React
224
242
 
225
- | Feature | Description | Default Value |
226
- | ------------------- | ------------------------------------------- | -------------------------------------------- |
227
- | `waveform` | Display audio waveform visualization | `{ enabled: false }` |
228
- | `backgroundRemoval` | Remove avatar background for transparency | `{ enabled: false }` |
229
- | `inactiveTimeout` | Auto-hide avatar after period of inactivity | `{ enabled: false, timeoutDuration: 60000 }` |
230
- | `disclaimer` | Show disclaimer text above the avatar | `{ enabled: false, text: "" }` |
243
+ ```tsx
244
+ import React, { useEffect, useRef, useState } from "react";
245
+ import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
246
+ import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
231
247
 
232
- ### Configuration During Initialization
248
+ export function CompanionWidget() {
249
+ const containerRef = useRef<HTMLDivElement>(null);
250
+ const [instance, setInstance] = useState<NapsterCompanionApiInstance | null>(
251
+ null
252
+ );
233
253
 
234
- ```typescript
235
- const widget = await NapsterCompanionApiSdk.init("YOUR_AUTH_TOKEN", {
236
- mountContainer: "#avatar-container",
237
- position: "bottom-right",
238
- features: {
239
- autoplay: { enabled: true },
240
- waveform: { enabled: true },
241
- backgroundRemoval: { enabled: false },
242
- inactiveTimeout: {
243
- enabled: true,
244
- timeoutDuration: 60000, // 60 seconds
245
- },
246
- },
247
- });
248
- ```
254
+ useEffect(() => {
255
+ const initSDK = async () => {
256
+ if (!containerRef.current) return;
249
257
 
250
- ### Dynamic Feature Updates
258
+ const result = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
259
+ mountContainer: containerRef.current,
260
+ position: "bottom-right",
261
+ });
262
+ setInstance(result);
263
+ };
251
264
 
252
- Update feature configuration after initialization:
265
+ initSDK();
253
266
 
254
- ```typescript
255
- // Enable/disable a single feature
256
- widget.enableFeature("waveform");
257
- widget.disableFeature("waveform");
258
-
259
- // Update feature configuration
260
- widget.updateFeatureConfig({
261
- autoplay: { enabled: true },
262
- inactiveTimeout: {
263
- enabled: true,
264
- timeoutDuration: 30000, // 30 seconds
265
- },
266
- });
267
+ return () => {
268
+ instance?.destroy();
269
+ };
270
+ }, []);
271
+
272
+ return <div ref={containerRef} style={{ width: "100%", height: "100%" }} />;
273
+ }
267
274
  ```
268
275
 
269
- ---
276
+ ### 2.2 Vue 3
270
277
 
271
- ## 4. API Reference
278
+ ```html
279
+ <template>
280
+ <div ref="containerRef"></div>
281
+ </template>
272
282
 
273
- ### Initialization
283
+ <script setup lang="ts">
284
+ import { onMounted, onUnmounted, ref } from "vue";
285
+ import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
286
+ import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
274
287
 
275
- #### `NapsterCompanionApiSdk.init(token, options)`
288
+ const containerRef = ref<HTMLElement>();
289
+ let instance: NapsterCompanionApiInstance | null = null;
276
290
 
277
- Initialize and mount the avatar widget.
291
+ onMounted(async () => {
292
+ if (!containerRef.value) return;
278
293
 
279
- **Parameters:**
294
+ instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
295
+ mountContainer: containerRef.value,
296
+ position: "bottom-right",
297
+ });
298
+ });
280
299
 
281
- | Parameter | Type | Required | Description |
282
- | --------- | --------------------------- | -------- | ---------------------------- |
283
- | `token` | `string` | Yes | Auth token from your backend |
284
- | `options` | `NapsterCompanionApiConfig` | Yes | Configuration object |
300
+ onUnmounted(() => {
301
+ instance?.destroy();
302
+ });
303
+ </script>
304
+ ```
285
305
 
286
- **`NapsterCompanionApiConfig` Interface:**
306
+ ### 2.3 Angular
287
307
 
288
308
  ```typescript
289
- interface NapsterCompanionApiConfig {
290
- mountContainer: string | HTMLElement; // CSS selector or DOM element
291
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
292
- features?: {
293
- autoplay?: { enabled: boolean };
294
- waveform?: { enabled: boolean };
295
- backgroundRemoval?: { enabled: boolean };
296
- inactiveTimeout?: { enabled: boolean; timeoutDuration?: number };
297
- };
298
- styles?: {
299
- width?: string;
300
- height?: string;
301
- zIndex?: number;
302
- };
303
- onReady?: () => void;
304
- onError?: (error: Error) => void;
305
- onData?: (data: EventMessage) => void;
306
- onAvatarReady?: () => void;
307
- onDestroy?: () => void;
308
- }
309
- ```
309
+ import {
310
+ Component,
311
+ OnInit,
312
+ OnDestroy,
313
+ ElementRef,
314
+ ViewChild,
315
+ } from "@angular/core";
316
+ import {
317
+ NapsterCompanionApiSdk,
318
+ NapsterCompanionApiInstance,
319
+ } from "@touchcastllc/napster-companion-api";
310
320
 
311
- **Returns:** `Promise<NapsterCompanionApiInstance>`
321
+ @Component({
322
+ selector: "app-companion",
323
+ template: "<div #containerRef></div>",
324
+ })
325
+ export class CompanionComponent implements OnInit, OnDestroy {
326
+ @ViewChild("containerRef") containerRef!: ElementRef<HTMLDivElement>;
327
+ private instance: NapsterCompanionApiInstance | null = null;
312
328
 
313
- **Example:**
329
+ async ngOnInit() {
330
+ this.instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
331
+ mountContainer: this.containerRef.nativeElement,
332
+ position: "bottom-right",
333
+ });
334
+ }
314
335
 
315
- ```typescript
316
- const widget = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
317
- mountContainer: "#avatar-container",
318
- position: "bottom-right",
319
- });
336
+ ngOnDestroy() {
337
+ this.instance?.destroy();
338
+ }
339
+ }
320
340
  ```
321
341
 
322
- ---
323
-
324
- ### Widget Instance Methods
342
+ ### 2.4 Vanilla JavaScript/TypeScript
325
343
 
326
- #### `widget.showAvatar()`
344
+ ```html
345
+ <div id="sdk-container"></div>
346
+ <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
347
+ <script>
348
+ const sdk = window.napsterCompanionApiSDK;
349
+
350
+ sdk
351
+ .init("YOUR_TOKEN", {
352
+ mountContainer: "#sdk-container",
353
+ position: "bottom-right",
354
+ })
355
+ .then(instance => {
356
+ // Control the avatar
357
+ instance.showAvatar();
358
+
359
+ // Hide after 10 seconds
360
+ setTimeout(() => instance.hideAvatar(), 10000);
361
+ });
362
+ </script>
363
+ ```
327
364
 
328
- Shows the avatar widget.
365
+ ### 2.5 Advanced Configuration
329
366
 
330
367
  ```typescript
331
- widget.showAvatar();
332
- ```
333
-
334
- ---
368
+ async function initAdvancedAvatar() {
369
+ const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
370
+ mountContainer: "#avatar-container",
371
+ position: "bottom-right",
335
372
 
336
- #### `widget.hideAvatar()`
373
+ avatarStyle: {
374
+ view: "round", // Options: "round" | "rectangle" | "silhouette"
375
+ },
337
376
 
338
- Hides the avatar widget.
377
+ features: {
378
+ inactiveTimeout: { enabled: true, duration: 120000, countdown: 15 },
379
+ showSDKLoader: { enabled: true, bgColor: "#f0f0f0" },
380
+ },
339
381
 
340
- ```typescript
341
- widget.hideAvatar();
342
- ```
382
+ style: {
383
+ borderRadius: "12px",
384
+ boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
385
+ },
343
386
 
344
- ---
387
+ onReady: () => console.log("Avatar ready!"),
388
+ onError: error => console.error("Error:", error),
389
+ onAvatarReady: ready => console.log("Avatar loaded:", ready),
390
+ });
345
391
 
346
- #### `widget.destroy()`
392
+ return instance;
393
+ }
394
+ ```
347
395
 
348
- Destroys and unmounts the widget from the DOM. Call this during cleanup.
396
+ ### 2.6 Dynamic Feature Control
349
397
 
350
398
  ```typescript
351
- widget.destroy();
352
- ```
399
+ async function controlFeatures() {
400
+ const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
401
+ mountContainer: "#avatar-container",
402
+ });
353
403
 
354
- ---
404
+ // Change position dynamically
405
+ document.getElementById("move-avatar")?.addEventListener("click", () => {
406
+ instance.setPosition("top-left");
407
+ });
355
408
 
356
- #### `widget.updateStyles(styles)`
409
+ return instance;
410
+ }
411
+ ```
357
412
 
358
- Update widget styling dynamically.
413
+ ### 2.7 Custom Styling
359
414
 
360
- **Parameters:**
415
+ #### Inline Styles
361
416
 
362
417
  ```typescript
363
- interface React.CSSProperties {
364
- width?: string;
365
- height?: string;
366
- zIndex?: number;
367
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
368
- }
418
+ const instance = await NapsterCompanionApiSdk.init(token, {
419
+ style: {
420
+ border: "2px solid #00ff00",
421
+ borderRadius: "8px",
422
+ boxShadow: "0 2px 10px rgba(0,0,0,0.2)",
423
+ background: "rgba(255,255,255,0.95)",
424
+ },
425
+ });
369
426
  ```
370
427
 
371
- **Example:**
428
+ #### CSS Classes
372
429
 
373
430
  ```typescript
374
- widget.updateStyles({
375
- width: "400px",
376
- height: "600px",
377
- zIndex: 1000,
378
- position: "top-right",
431
+ const instance = await NapsterCompanionApiSdk.init(token, {
432
+ className: "my-custom-avatar",
379
433
  });
380
434
  ```
381
435
 
382
- ---
436
+ ```css
437
+ .my-custom-avatar {
438
+ border: 2px solid #007acc;
439
+ border-radius: 12px;
440
+ backdrop-filter: blur(10px);
441
+ }
442
+ ```
383
443
 
384
- #### `widget.enableFeature(featureName)`
444
+ #### Dynamic Style Updates
385
445
 
386
- Enable a specific feature.
446
+ ```typescript
447
+ // Update styles after initialization
448
+ instance.updateStyles({
449
+ opacity: "0.9",
450
+ transform: "scale(1.1)",
451
+ transition: "all 0.3s ease",
452
+ });
453
+ ```
387
454
 
388
- **Parameters:**
455
+ ### 2.8 Avatar Style Configuration
389
456
 
390
- - `featureName`: `"autoplay" | "waveform" | "backgroundRemoval" | "inactiveTimeout"`
457
+ Customize the avatar's visual appearance using the `avatarStyle` configuration. Control the avatar's view mode, and other visual properties.
391
458
 
392
- **Example:**
459
+ #### Avatar View Modes
393
460
 
394
461
  ```typescript
395
- widget.enableFeature("waveform");
462
+ const instance = await NapsterCompanionApiSdk.init(token, {
463
+ avatarStyle: {
464
+ view: "round", // Options: "round" | "rectangle" | "silhouette"
465
+ },
466
+ });
396
467
  ```
397
468
 
398
- ---
399
-
400
- #### `widget.disableFeature(featureName)`
401
-
402
- Disable a specific feature.
403
-
404
- **Parameters:**
469
+ **Available View Modes:**
405
470
 
406
- - `featureName`: `"autoplay" | "waveform" | "backgroundRemoval" | "inactiveTimeout"`
471
+ - `"round"` (default) - Circular avatar with rounded appearance
472
+ - `"rectangle"` - Rectangular container, ideal for custom styling
473
+ - `"silhouette"` - Full view without background styling. (**Note: works only with green screen feature enabled in [Create Connection](#step-2-create-connection--get-token-backend) API**)
407
474
 
408
- **Example:**
475
+ #### Avatar Style Example
409
476
 
410
477
  ```typescript
411
- widget.disableFeature("autoplay");
478
+ const instance = await NapsterCompanionApiSdk.init(token, {
479
+ avatarStyle: {
480
+ view: "rectangle",
481
+ },
482
+ style: {
483
+ borderRadius: "16px", // Works well with rectangle
484
+ boxShadow: "0 8px 32px rgba(0,0,0,0.2)",
485
+ },
486
+ });
412
487
  ```
413
488
 
414
489
  ---
415
490
 
416
- #### `widget.updateFeatureConfig(config)`
491
+ ## 3. Feature Configuration
417
492
 
418
- Update multiple feature configurations at once.
493
+ ### 3.1 Core Features
419
494
 
420
- **Parameters:**
495
+ #### Inactivity Timeout
421
496
 
422
- ```typescript
423
- interface FeatureConfig {
424
- autoplay?: { enabled: boolean };
425
- waveform?: { enabled: boolean };
426
- backgroundRemoval?: { enabled: boolean };
427
- inactiveTimeout?: { enabled: boolean; timeoutDuration?: number };
428
- }
429
- ```
430
-
431
- **Example:**
497
+ Automatically disconnect the avatar after a period of user inactivity. Users receive a countdown notification before disconnection.
432
498
 
433
499
  ```typescript
434
- widget.updateFeatureConfig({
435
- autoplay: { enabled: true },
436
- inactiveTimeout: { enabled: true, timeoutDuration: 45000 },
500
+ const instance = await NapsterCompanionApiSdk.init(token, {
501
+ features: {
502
+ inactiveTimeout: {
503
+ enabled: true,
504
+ duration: 60000, // 60 seconds (max: 180000ms)
505
+ countdown: 10, // 10 second countdown (max: 60s)
506
+ },
507
+ },
437
508
  });
438
509
  ```
439
510
 
440
- ---
511
+ #### SDK Loading Screen
441
512
 
442
- ### Type Definitions
513
+ Display a loading screen while the avatar assets are being loaded. Customize the background color to match your application's design.
443
514
 
444
515
  ```typescript
445
- // Main initialization options
446
- interface NapsterCompanionApiConfig {
447
- mountContainer: string | HTMLElement;
448
- position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
449
- features?: FeatureConfig;
450
- styles?: React.CSSProperties;
451
- onReady?: () => void;
452
- onError?: (error: Error) => void;
453
- onData?: (data: EventMessage) => void;
454
- onAvatarReady?: () => void;
455
- onDestroy?: () => void;
456
- }
457
-
458
- // Feature configuration
459
- interface FeatureConfig {
460
- autoplay?: { enabled: boolean };
461
- waveform?: { enabled: boolean };
462
- backgroundRemoval?: { enabled: boolean };
463
- inactiveTimeout?: { enabled: boolean; timeoutDuration?: number };
464
- }
465
-
466
- // Widget instance returned by init()
467
- interface NapsterCompanionApiInstance {
468
- showAvatar(): void;
469
- hideAvatar(): void;
470
- destroy(): void;
471
- updateStyles(styles: React.CSSProperties): void;
472
- enableFeature(feature: string): void;
473
- disableFeature(feature: string): void;
474
- updateFeatureConfig(config: FeatureConfig): void;
475
- }
516
+ const instance = await NapsterCompanionApiSdk.init(token, {
517
+ features: {
518
+ showSDKLoader: {
519
+ enabled: true,
520
+ bgColor: "#ffffff", // Optional background color
521
+ },
522
+ },
523
+ });
476
524
  ```
477
525
 
478
- ---
479
-
480
- ## 5. Usage Examples
526
+ ### 3.2 Position & Layout
481
527
 
482
- Framework-specific, copy-paste-ready snippets demonstrating proper lifecycle management.
528
+ Customize the avatar's position on the screen using predefined positions or custom styles. Also you can override the position using style properties.
483
529
 
484
- ### React 18+ (Hooks)
485
-
486
- ```tsx
487
- import React, { useEffect, useRef, useState } from "react";
488
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
489
-
490
- export function AvatarWidget() {
491
- const containerRef = useRef(null);
492
- const [widget, setWidget] = useState(null);
493
-
494
- useEffect(() => {
495
- let mounted = true;
496
-
497
- async function initialize() {
498
- try {
499
- // Fetch token from your backend
500
- const response = await fetch("/api/get-napster-token", {
501
- method: "POST",
502
- });
503
- const { token } = await response.json();
504
-
505
- // Initialize widget
506
- const instance = await NapsterCompanionApiSdk.init(token, {
507
- mountContainer: containerRef.current,
508
- position: "bottom-right",
509
- features: {
510
- autoplay: { enabled: true },
511
- waveform: { enabled: true },
512
- },
513
- });
514
-
515
- if (mounted) {
516
- setWidget(instance);
517
- }
518
- } catch (error) {
519
- console.error("Failed to initialize avatar:", error);
520
- }
521
- }
522
-
523
- initialize();
524
-
525
- // Cleanup on unmount
526
- return () => {
527
- mounted = false;
528
- widget?.destroy();
529
- };
530
- }, []);
531
-
532
- return <div ref={containerRef} style={{ width: "100%", height: "100%" }} />;
533
- }
530
+ ```typescript
531
+ const instance = await NapsterCompanionApiSdk.init(token, {
532
+ mountContainer: "#my-container", // CSS selector or HTMLElement
533
+ position: "bottom-right", // Predefined positions
534
+ // Apply custom inline styles to override default SDK styles, will be added to root container
535
+ style: {
536
+ top: "20px",
537
+ left: "20px",
538
+ zIndex: "1000",
539
+ },
540
+ // Apply CSS class name to override default SDK styles, will be added to root container
541
+ className: "my-custom-class",
542
+ });
534
543
  ```
535
544
 
536
- ---
537
-
538
- ### React 16/17 (Class Component)
545
+ **Available Positions:**
539
546
 
540
- ```tsx
541
- import React from "react";
542
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api/legacy";
543
-
544
- export class AvatarWidget extends React.Component {
545
- containerRef = React.createRef();
546
- widget = null;
547
-
548
- async componentDidMount() {
549
- try {
550
- // Fetch token from your backend
551
- const response = await fetch("/api/get-napster-token", {
552
- method: "POST",
553
- });
554
- const { token } = await response.json();
547
+ - `"bottom-right"` (default)
548
+ - `"bottom-left"`
549
+ - `"bottom-center"`
550
+ - `"top-right"`
551
+ - `"top-left"`
552
+ - `"top-center"`
553
+ - `"center"`
555
554
 
556
- // Initialize widget
557
- this.widget = await NapsterCompanionApiSdk.init(token, {
558
- mountContainer: this.containerRef.current,
559
- position: "bottom-right",
560
- features: {
561
- autoplay: { enabled: true },
562
- },
563
- });
564
- } catch (error) {
565
- console.error("Failed to initialize avatar:", error);
566
- }
567
- }
555
+ ## 4. Event Handling
568
556
 
569
- componentWillUnmount() {
570
- // Cleanup on unmount
571
- this.widget?.destroy();
572
- }
557
+ The SDK provides several event callbacks for monitoring status and handling errors.
573
558
 
574
- render() {
575
- return (
576
- <div ref={this.containerRef} style={{ width: "100%", height: "100%" }} />
577
- );
578
- }
579
- }
559
+ ```typescript
560
+ const instance = await NapsterCompanionApiSdk.init(token, {
561
+ // Fires when the SDK is initialized and ready to use
562
+ onReady: () => console.log("SDK ready!"),
563
+ // Fires on any SDK error
564
+ onError: error => console.error("SDK error:", error),
565
+ // Fires when the avatar is fully loaded and ready
566
+ onAvatarReady: isReady => console.log("Avatar ready:", isReady),
567
+ // Fires when user inactivity status changes
568
+ onInactivityStatusChange: isInactive => console.log("Inactive:", isInactive),
569
+ // Fires when the SDK is destroyed
570
+ onDestroy: () => console.log("SDK destroyed"),
571
+ // Fires when data is received from the WEBRTC data channel
572
+ onData: data => console.log("Data received:", data),
573
+ });
580
574
  ```
581
575
 
582
576
  ---
583
577
 
584
- ### Vue 3
578
+ ## 5. API Reference
585
579
 
586
- ```html
587
- <template>
588
- <div ref="containerRef" style="width: 100%; height: 100%;"></div>
589
- </template>
580
+ ### 5.1 Core Methods
590
581
 
591
- <script setup>
592
- import { ref, onMounted, onBeforeUnmount } from "vue";
593
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
594
- import "@touchcastllc/napster-companion-api/lib/index.css";
595
-
596
- const containerRef = ref(null);
597
- let widget = null;
582
+ #### `init(token: string, config?: NapsterCompanionApiConfig): Promise<NapsterCompanionApiInstance>`
598
583
 
599
- onMounted(async () => {
600
- try {
601
- // Fetch token from your backend
602
- const response = await fetch("/api/get-napster-token", {
603
- method: "POST",
604
- });
605
- const { token } = await response.json();
584
+ Initialize the SDK with authentication token and configuration.
606
585
 
607
- // Initialize widget
608
- widget = await NapsterCompanionApiSdk.init(token, {
609
- mountContainer: containerRef.value,
610
- position: "bottom-right",
611
- features: {
612
- autoplay: { enabled: true },
613
- waveform: { enabled: true },
614
- },
615
- });
616
- } catch (error) {
617
- console.error("Failed to initialize avatar:", error);
618
- }
619
- });
620
-
621
- onBeforeUnmount(() => {
622
- // Cleanup on unmount
623
- widget?.destroy();
624
- });
625
- </script>
586
+ ```typescript
587
+ const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
588
+ mountContainer: "#avatar-container",
589
+ position: "bottom-right",
590
+ });
626
591
  ```
627
592
 
628
- ---
629
-
630
- ### Vue 2
593
+ #### `showAvatar(): void`
631
594
 
632
- ```html
633
- <template>
634
- <div ref="container" style="width: 100%; height: 100%;"></div>
635
- </template>
595
+ Make the avatar visible on screen.
636
596
 
637
- <script>
638
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
639
- import "@touchcastllc/napster-companion-api/lib/index.css";
640
-
641
- export default {
642
- name: "AvatarWidget",
643
- data() {
644
- return {
645
- widget: null,
646
- };
647
- },
648
- async mounted() {
649
- try {
650
- // Fetch token from your backend
651
- const response = await fetch("/api/get-napster-token", {
652
- method: "POST",
653
- });
654
- const { token } = await response.json();
655
-
656
- // Initialize widget
657
- this.widget = await NapsterCompanionApiSdk.init(token, {
658
- mountContainer: this.$refs.container,
659
- position: "bottom-right",
660
- features: {
661
- autoplay: { enabled: true },
662
- },
663
- });
664
- } catch (error) {
665
- console.error("Failed to initialize avatar:", error);
666
- }
667
- },
668
- beforeDestroy() {
669
- // Cleanup on unmount
670
- this.widget?.destroy();
671
- },
672
- };
673
- </script>
597
+ ```typescript
598
+ instance.showAvatar();
674
599
  ```
675
600
 
676
- ---
601
+ #### `hideAvatar(): void`
677
602
 
678
- ### Angular
603
+ Hide the avatar from screen.
679
604
 
680
605
  ```typescript
681
- import {
682
- Component,
683
- OnInit,
684
- OnDestroy,
685
- ElementRef,
686
- ViewChild,
687
- } from "@angular/core";
688
- import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
689
-
690
- @Component({
691
- selector: "app-avatar-widget",
692
- template: ` <div #container style="width: 100%; height: 100%;"></div> `,
693
- styles: [
694
- `
695
- @import "@touchcastllc/napster-companion-api/lib/index.css";
696
- `,
697
- ],
698
- })
699
- export class AvatarWidgetComponent implements OnInit, OnDestroy {
700
- @ViewChild("container", { static: true }) container!: ElementRef;
701
- private widget: any = null;
702
-
703
- async ngOnInit() {
704
- try {
705
- // Fetch token from your backend
706
- const response = await fetch("/api/get-napster-token", {
707
- method: "POST",
708
- });
709
- const { token } = await response.json();
710
-
711
- // Initialize widget
712
- this.widget = await NapsterCompanionApiSdk.init(token, {
713
- mountContainer: this.container.nativeElement,
714
- position: "bottom-right",
715
- features: {
716
- autoplay: { enabled: true },
717
- waveform: { enabled: true },
718
- },
719
- });
720
- } catch (error) {
721
- console.error("Failed to initialize avatar:", error);
722
- }
723
- }
724
-
725
- ngOnDestroy() {
726
- // Cleanup on unmount
727
- this.widget?.destroy();
728
- }
729
- }
606
+ instance.hideAvatar();
730
607
  ```
731
608
 
732
- ---
609
+ #### `avatarIsVisible(): boolean`
733
610
 
734
- ### Vanilla JS / Core (No Build Tools)
611
+ Check if the avatar is currently visible.
735
612
 
736
- ```html
737
- <!DOCTYPE html>
738
- <html lang="en">
739
- <head>
740
- <meta charset="UTF-8" />
741
- <title>Napster Avatar SDK</title>
742
- </head>
743
- <body>
744
- <div id="avatar-container"></div>
745
-
746
- <script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.min.js"></script>
747
- <script>
748
- (async function () {
749
- try {
750
- // Fetch token from your backend
751
- const response = await fetch("/api/get-napster-token", {
752
- method: "POST",
753
- });
754
- const { token } = await response.json();
755
-
756
- // Initialize widget
757
- const widget = await window.CompanionApiSDK.init(token, {
758
- mountContainer: "#avatar-container",
759
- position: "bottom-right",
760
- features: {
761
- autoplay: { enabled: true },
762
- waveform: { enabled: true },
763
- },
764
- });
765
-
766
- // Widget controls
767
- // widget.showAvatar();
768
- // widget.hideAvatar();
769
- // widget.destroy();
770
- } catch (error) {
771
- console.error("Failed to initialize avatar:", error);
772
- }
773
- })();
774
- </script>
775
- </body>
776
- </html>
613
+ ```typescript
614
+ if (instance.avatarIsVisible()) {
615
+ console.log("Avatar is visible");
616
+ }
777
617
  ```
778
618
 
779
- ---
780
-
781
- ## 6. Styling & Customization
782
-
783
- ### CSS Import Path
619
+ #### `destroy(): void`
784
620
 
785
- Always import the SDK's CSS file to ensure proper styling:
786
-
787
- **For Bundler Projects:**
621
+ Cleanup and remove the SDK completely.
788
622
 
789
623
  ```typescript
790
- import "@touchcastllc/napster-companion-api/lib/index.css";
624
+ instance.destroy();
791
625
  ```
792
626
 
793
- **For Browser Script Tags:**
794
-
795
- ```html
796
- <link
797
- rel="stylesheet"
798
- href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
799
- />
800
- ```
627
+ ### 5.2 Styling & Position Methods
801
628
 
802
- ### Custom Container Styling
629
+ #### `updateStyles(styles: StyleObject): void`
803
630
 
804
- You can customize the avatar container's size, position, and z-index:
631
+ Update container styles dynamically.
805
632
 
806
633
  ```typescript
807
- const widget = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
808
- mountContainer: "#avatar-container",
809
- position: "bottom-right",
810
- styles: {
811
- width: "400px",
812
- height: "600px",
813
- zIndex: 9999,
814
- },
815
- });
816
-
817
- // Update styles dynamically
818
- widget.updateStyles({
819
- width: "500px",
820
- height: "700px",
821
- position: "top-right",
634
+ instance.updateStyles({
635
+ top: "50px",
636
+ left: "50px",
637
+ opacity: "0.8",
822
638
  });
823
639
  ```
824
640
 
825
- ---
826
-
827
- ## 7. Troubleshooting
828
-
829
- Common integration errors and their quick resolutions.
830
-
831
- ### React Version Mismatch
832
-
833
- **Error:** `Error: Invalid hook call` or `React version mismatch`
834
-
835
- **Cause:** Using the wrong SDK entry point for your React version.
836
-
837
- **Solution:**
641
+ #### `setPosition(position: Position): void`
838
642
 
839
- - For React 18+, use: `import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";`
840
- - For React 16/17, use: `import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api/legacy";`
643
+ Change avatar position on screen.
841
644
 
842
- ```bash
843
- # Check your React version
844
- npm list react
645
+ ```typescript
646
+ instance.setPosition("top-left");
647
+ // or using enum
648
+ import { Position } from "@touchcastllc/napster-companion-api";
649
+ instance.setPosition(Position.TOP_LEFT);
845
650
  ```
846
651
 
847
- ---
848
-
849
- ### Missing CSS Styles
850
-
851
- **Error:** Widget appears unstyled or invisible
852
-
853
- **Cause:** CSS file not imported.
652
+ #### `clearPosition(): void`
854
653
 
855
- **Solution:**
856
-
857
- Add the CSS import:
654
+ Reset position to default/configured value.
858
655
 
859
656
  ```typescript
860
- import "@touchcastllc/napster-companion-api/lib/index.css";
861
- ```
862
-
863
- For HTML script tags:
864
-
865
- ```html
866
- <link
867
- rel="stylesheet"
868
- href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
869
- />
657
+ instance.clearPosition();
870
658
  ```
871
659
 
872
- ---
873
-
874
- ### CORS Errors
875
-
876
- **Error:** `Cross-Origin Request Blocked` when fetching token
660
+ ### 5.3 Feature Control Methods
877
661
 
878
- **Cause:** Making token generation API calls from the browser.
662
+ #### `enableFeature(feature: string): void`
879
663
 
880
- **Solution:**
664
+ Enable a specific feature.
881
665
 
882
- **Never generate tokens in client-side code.** Create a backend endpoint:
883
-
884
- ```javascript
885
- // Backend (Node.js/Express)
886
- app.post("/api/get-napster-token", async (req, res) => {
887
- const response = await fetch(
888
- "https://management-api.cogcache.com/public/connections",
889
- {
890
- method: "POST",
891
- headers: {
892
- "Content-Type": "application/json",
893
- "x-api-key": process.env.NAPSTER_API_KEY,
894
- },
895
- body: JSON.stringify({
896
- companionId: process.env.COMPANION_ID,
897
- providerConfig: {
898
- /* your config */
899
- },
900
- }),
901
- }
902
- );
903
- const data = await response.json();
904
- res.json({ token: data.token });
905
- });
666
+ ```typescript
667
+ instance.enableFeature("disclaimer");
906
668
  ```
907
669
 
908
- Then fetch from your backend in the client:
670
+ #### `disableFeature(feature: string): void`
671
+
672
+ Disable a specific feature.
909
673
 
910
674
  ```typescript
911
- const response = await fetch("/api/get-napster-token", { method: "POST" });
912
- const { token } = await response.json();
675
+ instance.disableFeature("disclaimer");
913
676
  ```
914
677
 
915
- ---
916
-
917
- ### Authentication / Token Issues
918
-
919
- **Error:** `401 Unauthorized` or `Invalid token`
678
+ #### `isFeatureEnabled(feature: string): boolean`
920
679
 
921
- **Possible Causes:**
680
+ Check if a feature is currently enabled.
922
681
 
923
- 1. Token expired
924
- 2. Invalid API key
925
- 3. Incorrect companion ID
682
+ ```typescript
683
+ if (instance.isFeatureEnabled("disclaimer")) {
684
+ console.log("Disclaimer is enabled");
685
+ }
686
+ ```
926
687
 
927
- **Solution:**
688
+ ### 5.4 Communication Methods
928
689
 
929
- 1. **Verify your API key** at [Napster API Keys page](https://app.cogcache.com/organization/keys)
930
- 2. **Check token expiration** - generate a fresh token
931
- 3. **Verify companion ID** matches your configuration
932
- 4. **Ensure backend endpoint** is working:
690
+ #### `sendCommand(command: { type: string; data?: object }): void`
933
691
 
934
- ---
692
+ Send a command to the avatar via the data channel.
935
693
 
936
- ### Widget Not Mounting
694
+ ```typescript
695
+ // Send a message to the avatar
696
+ instance.sendCommand({ type: "send_message", data: { text: "Hello, how are you?" } });
937
697
 
938
- **Error:** Container element not found or widget doesn't appear
698
+ // Cancel the current response
699
+ instance.sendCommand({ type: "cancel" });
700
+ ```
939
701
 
940
- **Possible Causes:**
702
+ ## 6. Configuration Interface
941
703
 
942
- 1. Container element doesn't exist
943
- 2. Invalid CSS selector
944
- 3. Container rendered after initialization
704
+ ```typescript
705
+ interface NapsterCompanionApiConfig {
706
+ // Container mounting
707
+ mountContainer?: HTMLElement | string | null;
708
+
709
+ // Positioning
710
+ position?:
711
+ | "bottom-right"
712
+ | "bottom-left"
713
+ | "bottom-center"
714
+ | "top-right"
715
+ | "top-left"
716
+ | "top-center"
717
+ | "center";
718
+
719
+ // Styling
720
+ style?: StyleObject;
721
+ className?: string;
722
+ avatarStyle?: {
723
+ view: "round" | "rectangle" | "silhouette";
724
+ borderWidth?: string;
725
+ borderColor?: string;
726
+ borderStyle?: string;
727
+ };
945
728
 
946
- **Solution:**
729
+ // Features
730
+ features?: {
731
+ backgroundRemoval?: { enabled: boolean };
732
+ inactiveTimeout?: {
733
+ enabled: boolean;
734
+ duration?: number; // max: 180000ms
735
+ countdown?: number; // max: 60s
736
+ };
737
+ disclaimer?: { enabled: boolean; text?: string };
738
+ showSDKLoader?: { enabled: boolean; bgColor?: string };
739
+ };
947
740
 
948
- ```typescript
949
- // ✅ Good: Wait for DOM element
950
- useEffect(() => {
951
- const container = document.querySelector("#avatar-container");
952
- if (container) {
953
- NapsterCompanionApiSdk.init(token, {
954
- mountContainer: container, // Use DOM element directly
955
- });
956
- }
957
- }, []);
741
+ // Configuration
742
+ debug?: boolean;
958
743
 
959
- // Bad: Container may not exist yet
960
- const widget = NapsterCompanionApiSdk.init(token, {
961
- mountContainer: "#avatar-container",
962
- });
744
+ // Event callbacks
745
+ onReady?: () => void;
746
+ onError?: (error: Error) => void;
747
+ onData?: (data: EventMessage) => void;
748
+ onAvatarReady?: (isReady?: boolean) => void;
749
+ onInactivityStatusChange?: (isInactive: boolean) => void;
750
+ onDestroy?: () => void;
751
+ onFeaturesUpdate?: (features: FeatureConfig) => void;
752
+ }
963
753
  ```
964
754
 
965
755
  ---
966
756
 
967
- ### Module Not Found
968
-
969
- **Error:** `Cannot find module '@touchcastllc/napster-companion-api'`
757
+ ## 7. Troubleshooting
970
758
 
971
- **Cause:** Package not installed.
759
+ ### 7.1 Common Issues
972
760
 
761
+ **Problem: "Module not found" Error**
973
762
  **Solution:**
974
763
 
975
764
  ```bash
765
+ # Ensure package is installed
976
766
  npm install @touchcastllc/napster-companion-api
977
- # or
978
- yarn add @touchcastllc/napster-companion-api
979
- ```
980
767
 
981
- ---
982
-
983
- ### Peer Dependency Warnings
768
+ # Install peer dependencies
769
+ npm install @reduxjs/toolkit
770
+ ```
984
771
 
985
- **Warning:** `ERESOLVE unable to resolve dependency tree`
772
+ **Problem: Invalid or expired token**
773
+ **Solution:**
986
774
 
987
- **Cause:** Missing or incompatible peer dependencies.
775
+ - Generate new token from backend API
776
+ - Ensure token is passed correctly to `init()`
988
777
 
778
+ **Problem: Avatar appears unstyled**
989
779
  **Solution:**
990
780
 
991
- Install all required peer dependencies:
781
+ See the style import guide from [1.2.1 Installation & Setup](#121-for-esm-build-type-recommended)
992
782
 
993
- ```bash
994
- # For React 18+
995
- npm install react@^18 react-dom@^18 @reduxjs/toolkit@^2 react-redux@^9
783
+ **Problem:** `mountContainer` element doesn't exist
784
+ **Solution:**
996
785
 
997
- # For React 16/17
998
- npm install react@^16 react-dom@^16 @reduxjs/toolkit@^2 react-redux@^8
786
+ ```typescript
787
+ // Wait for DOM to load
788
+ document.addEventListener("DOMContentLoaded", async () => {
789
+ const instance = await NapsterCompanionApiSdk.init(token, {
790
+ mountContainer: "#avatar-container", // Ensure element exists
791
+ });
792
+ });
999
793
  ```
1000
794
 
1001
- ---
1002
-
1003
- ### TypeScript Errors
1004
-
1005
- **Error:** `Cannot find type definitions`
795
+ ### 7.2 Debug Mode
1006
796
 
1007
- **Cause:** TypeScript can't locate type definitions.
797
+ Enable debug logging:
1008
798
 
1009
- **Solution:**
799
+ ```typescript
800
+ const instance = await NapsterCompanionApiSdk.init(token, {
801
+ debug: true, // Enable debug logs
802
+ onError: error => console.error("SDK Error:", error),
803
+ onData: data => console.log("SDK Data:", data),
804
+ });
805
+ ```
1010
806
 
1011
- The SDK includes TypeScript definitions. Ensure your `tsconfig.json` includes:
807
+ ### 7.3 Performance Issues
1012
808
 
1013
- ```json
1014
- {
1015
- "compilerOptions": {
1016
- "moduleResolution": "node",
1017
- "esModuleInterop": true,
1018
- "skipLibCheck": true
1019
- }
1020
- }
1021
- ```
809
+ #### Large Bundle Size
1022
810
 
1023
- ---
811
+ - Use ESM build instead of standalone
812
+ - Import only needed features
813
+ - Enable tree-shaking in bundler
1024
814
 
1025
- ## 📚 Additional Resources
815
+ #### Memory Leaks
1026
816
 
1027
- - **API Keys**: [Generate API Keys](https://app.cogcache.com/organization/keys)
1028
- - **npm**: [@touchcastllc/napster-companion-api](https://www.npmjs.com/package/@touchcastllc/napster-companion-api)
817
+ ```typescript
818
+ // Always cleanup when done
819
+ useEffect(() => {
820
+ return () => {
821
+ instance?.destroy();
822
+ };
823
+ }, [instance]);
824
+ ```
1029
825
 
1030
826
  ---
1031
827
 
1032
- ## 📝 License
828
+ ## License
1033
829
 
1034
- MIT License. See [LICENSE](LICENSE) file for details.
830
+ This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details.