@touchcastllc/napster-companion-api 1.0.0-alpha.8 → 1.0.0

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