@coxwave/tap-sdk 0.2.1 → 0.2.2-demo.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.
package/README.md CHANGED
@@ -1,71 +1,32 @@
1
1
  # @coxwave/tap-sdk
2
2
 
3
- TapSDK is a lightweight JavaScript loader (~2-3KB) that dynamically loads the EduTap AI tutor from CDN. It provides the same familiar API for embedding interactive chat into any web property, but with the flexibility of instant updates without requiring npm package updates.
3
+ 간단한 JavaScript API로 애플리케이션에 EduTap AI 튜터를 임베드할 있습니다.
4
4
 
5
- ## Architecture
6
-
7
- This package is a **bootloader** that follows the ChannelTalk pattern:
8
-
9
- 1. **Loader Package** (`@coxwave/tap-sdk`) - Published to npm (~2.3KB)
10
- - Provides the familiar `TapSDK` API
11
- - Dynamically loads the actual SDK from CloudFront CDN
12
- - Handles version management and integrity checks
13
- - Only needs updates when API surface changes
14
-
15
- 2. **Core SDK** (`tap-kit-core`) - Deployed to S3/CloudFront
16
- - Contains the actual implementation (UI, iframe management, etc.)
17
- - Can be updated instantly without npm publishing
18
- - Version controlled with timestamps (YYYYMMDDHHMMSS format)
19
- - URL: `https://files.edutap.ai/tap-sdk/core-{VERSION}.js`
20
-
21
- ### Why This Architecture?
22
-
23
- - **Instant Updates**: Deploy bug fixes and features to all users immediately
24
- - **Smaller npm Package**: ~2-3KB loader vs ~20KB+ full SDK
25
- - **Version Control**: Centralized version management via CDN
26
- - **Integrity Checks**: Subresource Integrity (SRI) ensures security
27
- - **Backward Compatibility**: Same API surface, seamless for existing users
28
-
29
- ## Installation
30
-
31
- ### via npm
5
+ ## 설치
32
6
 
33
7
  ```bash
34
8
  npm install @coxwave/tap-sdk
35
- # or
9
+ # 또는
36
10
  pnpm add @coxwave/tap-sdk
37
- # or
11
+ # 또는
38
12
  yarn add @coxwave/tap-sdk
39
13
  ```
40
14
 
41
- ### Understanding the Loader
42
-
43
- When you install `@coxwave/tap-sdk` from npm, you get a small loader that:
44
-
45
- 1. Imports the package normally: `import TapSDK from '@coxwave/tap-sdk'`
46
- 2. On instantiation, loads the core SDK from `https://files.edutap.ai/tap-sdk/core-{VERSION}.js`
47
- 3. Proxies all API calls to the loaded core SDK
48
- 4. Verifies integrity using SHA-384 hashes
49
-
50
- **No code changes required** - the API is identical to the previous monolithic SDK.
51
-
52
- ## Quick Start
53
-
54
- ### ES Modules (npm)
15
+ ## 빠른 시작
55
16
 
56
17
  ```ts
57
18
  import TapSDK from "@coxwave/tap-sdk";
58
19
 
59
20
  const sdk = new TapSDK({
60
- apiKey: "your-plugin-key",
21
+ apiKey: "your-api-key",
61
22
  });
62
23
 
63
24
  await sdk.init({
64
- buttonId: "tap-button", // ID of the HTML element to attach the toggle button to
25
+ buttonId: "tap-button", // 토글 버튼을 부착할 HTML 요소의 ID
65
26
  course: {
66
27
  userId: "user-123",
67
28
  courseId: "course-456",
68
- clipId: null,
29
+ clipId: "clip-789",
69
30
  },
70
31
  container: {
71
32
  position: { top: "64px", right: "32px" },
@@ -76,66 +37,41 @@ await sdk.init({
76
37
  });
77
38
  ```
78
39
 
79
- ### How It Works
80
-
81
- ```mermaid
82
- sequenceDiagram
83
- participant App as Your App
84
- participant Loader as tap-sdk (npm)
85
- participant CDN as CloudFront CDN
86
- participant Core as Core SDK
87
-
88
- App->>Loader: import TapSDK
89
- App->>Loader: new TapSDK(config)
90
- Loader->>CDN: GET /tap-sdk/core-{VERSION}.js
91
- CDN-->>Loader: JavaScript Bundle
92
- Loader->>Core: Initialize with config
93
- App->>Loader: sdk.init(params)
94
- Loader->>Core: Forward init call
95
- Core-->>App: Chat Interface Ready
96
- ```
97
-
98
- On initialization the SDK:
99
-
100
- - ensures it is running in a browser (guards against SSR)
101
- - injects the chat container into `document.body`
102
- - renders the EduTap iframe and performs a handshake for authentication
103
- - attaches to the element with the provided `buttonId`
104
-
105
- ## Customisation
40
+ ## 커스터마이징
106
41
 
107
- ### Toggle button
42
+ ### 토글 버튼
108
43
 
109
- The SDK will attach alarm badges and click handlers to the element with the provided `buttonId`.
44
+ SDK 제공된 `buttonId`를 가진 요소에 알람 뱃지와 클릭 핸들러를 자동으로 부착합니다.
110
45
 
111
- ### Chat container
46
+ ### 채팅 컨테이너
112
47
 
113
- The chat surface is a fixed-position container. Customize via the `container` option:
48
+ 채팅 화면은 고정 위치 컨테이너입니다. `container` 옵션으로 커스터마이징할 있습니다:
114
49
 
115
- - `position` — partial `{ top/right/bottom/left }` values (strings with units)
116
- - `width` / `height` — strings with CSS units
117
- - `borderRadius` — border radius (e.g., "16px")
50
+ - `position` — `{ top/right/bottom/left }` (단위가 포함된 문자열)
51
+ - `width` / `height` — CSS 단위를 포함한 문자열
52
+ - `borderRadius` — 테두리 반경 (예: "16px")
118
53
 
119
- The container automatically shows/hides when chat opens/closes and expands when EduTap displays embedded PDFs.
54
+ 컨테이너는 채팅이 열리고 닫힐 자동으로 표시/숨김되며, EduTap이 PDF를 표시할 확장됩니다.
120
55
 
121
- ### Alarm notifications & pop-ups
56
+ ### 알람 알림 팝업
122
57
 
123
- EduTap can send rich alarm notifications and HTML pop-ups over the iframe channel. The SDK automatically fades alarms in/out, handles clicks, and renders pop-ups next to the chat container.
58
+ EduTap iframe 채널을 통해 풍부한 알람 알림과 HTML 팝업을 전송할 있습니다. SDK 자동으로 알람을 페이드 인/아웃하고, 클릭을 처리하며, 채팅 컨테이너 옆에 팝업을 렌더링합니다.
124
59
 
125
60
  ## Runtime API
126
61
 
127
62
  ### `init(options)`
128
63
 
129
- Initializes the iframe, performs the handshake, and wires up UI controls.
64
+ iframe 초기화하고, 핸드셰이크를 수행하며, UI 컨트롤을 연결합니다.
130
65
 
131
- **Options:**
132
- - `buttonId` (required) – ID of the HTML element to attach the toggle button to
133
- - `course` (required) – Course context with `userId`, `courseId`, `clipId`
134
- - `container?`Optional UI customization with `position`, `width`, `height`, `borderRadius`
66
+ **옵션:**
67
+
68
+ - `buttonId` (필수) – 토글 버튼을 부착할 HTML 요소의 ID
69
+ - `course` (필수) – `userId`, `courseId`, `clipId`를 포함한 강의 컨텍스트
70
+ - `container?` – `position`, `width`, `height`, `borderRadius`를 포함한 선택적 UI 커스터마이징
135
71
 
136
72
  ### `events.seekTimeline({ clipId, clipPlayHead })`
137
73
 
138
- For VOD integrations you can push timeline updates back to EduTap so that it can stay in sync with the host player.
74
+ VOD 통합을 위해 타임라인 업데이트를 EduTap으로 전송하여 호스트 플레이어와 동기화할 있습니다.
139
75
 
140
76
  ```ts
141
77
  sdk.events.seekTimeline({ clipId: "clip-42", clipPlayHead: 132.4 });
@@ -143,44 +79,44 @@ sdk.events.seekTimeline({ clipId: "clip-42", clipPlayHead: 132.4 });
143
79
 
144
80
  ### `destroy()`
145
81
 
146
- Unhooks all listeners, removes the iframe and toggle button decorations, and resets the internal state. Call this when unmounting a single-page application route.
82
+ 모든 리스너를 해제하고, iframe 토글 버튼 장식을 제거하며, 내부 상태를 초기화합니다. 단일 페이지 애플리케이션 라우트를 언마운트할 호출하세요.
147
83
 
148
- ## Event system
84
+ ## 이벤트 시스템
149
85
 
150
- Events are exposed via the `sdk.events` helper. Every listener returns an unsubscribe function.
86
+ 이벤트는 `sdk.events` 헬퍼를 통해 제공됩니다. 모든 리스너는 구독 해제 함수를 반환합니다.
151
87
 
152
88
  ```ts
153
- // Chat lifecycle events
154
- sdk.events.onChatInitiated(() => console.log("chat initialized"));
155
- sdk.events.onChatOpened(() => console.log("chat opened"));
156
- sdk.events.onChatClosed(() => console.log("chat closed"));
89
+ // 채팅 라이프사이클 이벤트
90
+ sdk.events.onChatInitiated(() => console.log("채팅 초기화됨"));
91
+ sdk.events.onChatOpened(() => console.log("채팅 열림"));
92
+ sdk.events.onChatClosed(() => console.log("채팅 닫힘"));
157
93
 
158
- // Timeline synchronization
94
+ // 타임라인 동기화
159
95
  sdk.events.onTimelineSeek((playHead, clipId) => {
160
- console.log("EduTap requested timeline seek", playHead, clipId);
96
+ console.log("EduTap 타임라인 시크 요청", playHead, clipId);
161
97
  });
162
98
 
163
- // Notifications and overlays
99
+ // 알림 오버레이
164
100
  sdk.events.onAlarmFadeIn((alarm) => {
165
- console.log("Alarm", alarm.message);
101
+ console.log("알람", alarm.message);
166
102
  });
167
103
 
168
104
  sdk.events.onPopUpOpen((popUp) => {
169
- // popUp.html contains the rendered snippet
105
+ // popUp.html 렌더링된 스니펫이 포함됨
170
106
  });
171
107
 
172
- sdk.events.onPdfOpen(() => console.log("PDF overlay opened"));
173
- sdk.events.onPdfClose(() => console.log("PDF overlay closed"));
108
+ sdk.events.onPdfOpen(() => console.log("PDF 오버레이 열림"));
109
+ sdk.events.onPdfClose(() => console.log("PDF 오버레이 닫힘"));
174
110
  ```
175
111
 
176
- ## TypeScript Support
112
+ ## TypeScript 지원
177
113
 
178
- Type definitions are included with the package. Key exports:
114
+ 타입 정의가 패키지에 포함되어 있습니다. 주요 export:
179
115
 
180
116
  ```ts
181
117
  import type {
182
- TapSDKConfig,
183
- TapSDKInitParams,
118
+ TapKitConfig,
119
+ TapKitInitParams,
184
120
  Course,
185
121
  ContainerStyle,
186
122
  PositionType,
@@ -189,48 +125,9 @@ import type {
189
125
  } from "@coxwave/tap-sdk";
190
126
  ```
191
127
 
192
- All iframe message contracts are sourced from `@coxwave/tap-messages` and validated with valibot schemas.
193
-
194
- ## Version Management
195
-
196
- ### How It Works
128
+ ## 보안 고려사항
197
129
 
198
- The npm package (`@coxwave/tap-sdk`) simply loads the CDN loader script:
199
-
200
- ```typescript
201
- const CDN_LOADER_URL = 'https://files.edutap.ai/tap-sdk/loader.js';
202
- ```
203
-
204
- The CDN loader (`tap-kit-core/loader.ts`) handles all version management:
205
- 1. Fetches `versions.json` to get the latest version
206
- 2. Loads the appropriate `tap-kit-{version}.js` with SRI verification
207
- 3. Initializes the actual SDK
208
-
209
- ### Deployment Workflow
210
-
211
- **For SDK updates (most common):**
212
- ```bash
213
- cd packages/tap-kit-core
214
- pnpm build
215
- ./scripts/deploy-s3.sh
216
- ```
217
-
218
- This deploys to CDN and all users automatically get the update.
219
-
220
- **For npm package updates (rare):**
221
- ```bash
222
- cd packages/tap-sdk
223
- pnpm build
224
- pnpm publish:npm
225
- ```
226
-
227
- Only needed when the API surface changes (new methods, types, etc).
228
-
229
- ## Security Considerations
230
-
231
- ### Content Security Policy (CSP)
232
-
233
- If your site uses CSP headers, add these directives:
130
+ 사이트에서 Content Security Policy (CSP) 헤더를 사용하는 경우, 다음 지시문을 추가하세요:
234
131
 
235
132
  ```http
236
133
  Content-Security-Policy:
@@ -240,59 +137,41 @@ Content-Security-Policy:
240
137
  frame-src 'self' https://your-edutap-domain.com;
241
138
  ```
242
139
 
243
- **Important:**
244
- - `script-src` must include `https://files.edutap.ai` for CDN loading
245
- - `style-src 'unsafe-inline'` is required for injected CSS (Vanilla Extract)
246
-
247
- ### Subresource Integrity (SRI)
248
-
249
- The loader verifies CDN files using SHA-384 integrity checks:
250
-
251
- ```typescript
252
- // In loader.ts
253
- script.integrity = CDN_INTEGRITY;
254
- script.crossOrigin = 'anonymous';
255
- ```
256
-
257
- This ensures the loaded SDK hasn't been tampered with, even if CloudFront is compromised.
258
-
259
- ## Browser Support
140
+ ## 브라우저 지원
260
141
 
261
142
  - Chrome 60+
262
143
  - Firefox 60+
263
144
  - Safari 12+
264
145
  - Edge 79+
265
146
 
266
- Requires modern browsers with ES2020 support and `postMessage` API.
267
-
268
- ## License
147
+ ## 라이선스
269
148
 
270
149
  MIT © 2025 Coxwave
271
150
 
272
- ## Properties
151
+ ## 속성
273
152
 
274
153
  ### `isOpen`
275
154
 
276
- Returns `true` if the chat interface is currently open.
155
+ 채팅 인터페이스가 현재 열려 있으면 `true`를 반환합니다.
277
156
 
278
157
  ```ts
279
158
  if (sdk.isOpen) {
280
- console.log("Chat is currently open");
159
+ console.log("채팅이 현재 열려 있습니다");
281
160
  }
282
161
  ```
283
162
 
284
163
  ### `isInitialized`
285
164
 
286
- Returns `true` if the SDK has been successfully initialized.
165
+ SDK 성공적으로 초기화되면 `true`를 반환합니다.
287
166
 
288
167
  ```ts
289
168
  if (sdk.isInitialized) {
290
- console.log("SDK is ready to use");
169
+ console.log("SDK 사용 준비 완료");
291
170
  }
292
171
  ```
293
172
 
294
- ## Deprecated helpers
173
+ ## 이상 사용되지 않는 헬퍼
295
174
 
296
- - `initChat(options)` – use `init(options)` instead; scheduled for removal in v1.0.0
297
- - `postChatInfo({ clipId, clipPlayHead })` – alias for `events.seekTimeline`; scheduled for removal in v1.0.0
298
- - `getTimelineInfo({ callback })` – use `sdk.events.onTimelineSeek` instead; scheduled for removal in v1.0.0
175
+ - `initChat(options)` – `init(options)` 사용 권장; v1.0.0에서 제거 예정
176
+ - `postChatInfo({ clipId, clipPlayHead })` – `events.seekTimeline`의 별칭; v1.0.0에서 제거 예정
177
+ - `getTimelineInfo({ callback })` – `sdk.events.onTimelineSeek` 사용 권장; v1.0.0에서 제거 예정
package/dist/index.d.cts CHANGED
@@ -2,16 +2,16 @@ import { AlarmMessageInstanceType } from '@coxwave/tap-messages';
2
2
  export { AlarmMessageInstanceType, AlarmType } from '@coxwave/tap-messages';
3
3
 
4
4
  /**
5
- * TapSDK Type Definitions
5
+ * TapKit Type Definitions
6
6
  *
7
7
  * Re-exported types for API compatibility with the loader.
8
- * These types match the actual SDK implementation in tap-sdk-cdn.
8
+ * These types match the actual SDK implementation in tap-kit-core.
9
9
  */
10
10
 
11
- type TapSDKConfig = {
11
+ type TapKitConfig = {
12
12
  apiKey: string;
13
13
  };
14
- type TapSDKInitParams = {
14
+ type TapKitInitParams = {
15
15
  buttonId: string;
16
16
  course: Course;
17
17
  container?: ContainerStyle;
@@ -40,21 +40,23 @@ type SeekTimelineParamsType = {
40
40
  };
41
41
 
42
42
  /**
43
- * TapSDK - npm package wrapper
43
+ * TapKit wrapper - npm package wrapper
44
44
  *
45
45
  * Simply loads the CDN loader which handles version management and SDK loading.
46
46
  * This keeps the npm package minimal and allows instant updates via CDN.
47
+ *
48
+ * Demo version: Automatically configures localStorage for demo environment.
47
49
  */
48
50
 
49
- type TapSDKConstructor = new (config: TapSDKConfig) => TapSDKInstance;
51
+ type TapKitConstructor = new (config: TapKitConfig) => TapKitInstance;
50
52
  declare global {
51
53
  interface Window {
52
- TapSDK?: TapSDKConstructor;
53
- __TAP_SDK_LOADER_LOADED__?: boolean;
54
- __TAP_SDK_LOADER_LOADING__?: Promise<void>;
54
+ TapKit?: TapKitConstructor;
55
+ __TAP_KIT_LOADER_LOADED__?: boolean;
56
+ __TAP_KIT_LOADER_LOADING__?: Promise<void>;
55
57
  }
56
58
  }
57
- interface TapSDKInstance {
59
+ interface TapKitInstance {
58
60
  events: {
59
61
  seekTimeline: (params: SeekTimelineParamsType) => void;
60
62
  onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;
@@ -68,10 +70,11 @@ interface TapSDKInstance {
68
70
  };
69
71
  isOpen: boolean;
70
72
  isInitialized: boolean;
71
- init(params: TapSDKInitParams): Promise<void>;
73
+ readyPromise: Promise<void>;
74
+ init(params: TapKitInitParams): Promise<void>;
72
75
  destroy(): void;
73
76
  getVersion(): string;
74
- initChat(params: TapSDKInitParams): Promise<void>;
77
+ initChat(params: TapKitInitParams): Promise<void>;
75
78
  postChatInfo(params: {
76
79
  clipId: string;
77
80
  clipPlayHead: number;
@@ -80,18 +83,20 @@ interface TapSDKInstance {
80
83
  callback: (clipPlayHead: number, clipId: string) => void;
81
84
  }): Promise<void>;
82
85
  }
86
+ declare const SDK_INSTANCE: unique symbol;
87
+ declare const SDK_INSTANCE_LOADING: unique symbol;
83
88
  /**
84
- * TapSDK Wrapper Class
89
+ * TapKit Wrapper Class
85
90
  *
86
91
  * Loads the CDN loader and proxies all calls to the actual SDK
87
92
  */
88
- declare class TapSDK implements TapSDKInstance {
89
- private config;
90
- private sdkInstance?;
91
- private loadPromise;
92
- constructor(config: TapSDKConfig);
93
+ declare class TapKit implements TapKitInstance {
94
+ private [SDK_INSTANCE]?;
95
+ private [SDK_INSTANCE_LOADING];
96
+ constructor(config: TapKitConfig);
93
97
  private loadAndInitialize;
94
98
  private ensureLoaded;
99
+ get readyPromise(): Promise<void>;
95
100
  get events(): {
96
101
  seekTimeline: (params: SeekTimelineParamsType) => void;
97
102
  onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;
@@ -105,10 +110,10 @@ declare class TapSDK implements TapSDKInstance {
105
110
  };
106
111
  get isOpen(): boolean;
107
112
  get isInitialized(): boolean;
108
- init(params: TapSDKInitParams): Promise<void>;
113
+ init(params: TapKitInitParams): Promise<void>;
109
114
  destroy(): void;
110
115
  getVersion(): string;
111
- initChat(params: TapSDKInitParams): Promise<void>;
116
+ initChat(params: TapKitInitParams): Promise<void>;
112
117
  postChatInfo(params: {
113
118
  clipId: string;
114
119
  clipPlayHead: number;
@@ -118,4 +123,4 @@ declare class TapSDK implements TapSDKInstance {
118
123
  }): Promise<void>;
119
124
  }
120
125
 
121
- export { type ContainerStyle, type Course, type PositionType, type SeekTimelineParamsType, type TapSDKInstance as TapSDK, type TapSDKConfig, type TapSDKConstructor, type TapSDKInitParams, type TapSDKInstance, TapSDK as default };
126
+ export { type ContainerStyle, type Course, type PositionType, type SeekTimelineParamsType, type TapKitInstance as TapKit, type TapKitConfig, type TapKitConstructor, type TapKitInitParams, TapKit as default };
package/dist/index.d.ts CHANGED
@@ -2,16 +2,16 @@ import { AlarmMessageInstanceType } from '@coxwave/tap-messages';
2
2
  export { AlarmMessageInstanceType, AlarmType } from '@coxwave/tap-messages';
3
3
 
4
4
  /**
5
- * TapSDK Type Definitions
5
+ * TapKit Type Definitions
6
6
  *
7
7
  * Re-exported types for API compatibility with the loader.
8
- * These types match the actual SDK implementation in tap-sdk-cdn.
8
+ * These types match the actual SDK implementation in tap-kit-core.
9
9
  */
10
10
 
11
- type TapSDKConfig = {
11
+ type TapKitConfig = {
12
12
  apiKey: string;
13
13
  };
14
- type TapSDKInitParams = {
14
+ type TapKitInitParams = {
15
15
  buttonId: string;
16
16
  course: Course;
17
17
  container?: ContainerStyle;
@@ -40,21 +40,23 @@ type SeekTimelineParamsType = {
40
40
  };
41
41
 
42
42
  /**
43
- * TapSDK - npm package wrapper
43
+ * TapKit wrapper - npm package wrapper
44
44
  *
45
45
  * Simply loads the CDN loader which handles version management and SDK loading.
46
46
  * This keeps the npm package minimal and allows instant updates via CDN.
47
+ *
48
+ * Demo version: Automatically configures localStorage for demo environment.
47
49
  */
48
50
 
49
- type TapSDKConstructor = new (config: TapSDKConfig) => TapSDKInstance;
51
+ type TapKitConstructor = new (config: TapKitConfig) => TapKitInstance;
50
52
  declare global {
51
53
  interface Window {
52
- TapSDK?: TapSDKConstructor;
53
- __TAP_SDK_LOADER_LOADED__?: boolean;
54
- __TAP_SDK_LOADER_LOADING__?: Promise<void>;
54
+ TapKit?: TapKitConstructor;
55
+ __TAP_KIT_LOADER_LOADED__?: boolean;
56
+ __TAP_KIT_LOADER_LOADING__?: Promise<void>;
55
57
  }
56
58
  }
57
- interface TapSDKInstance {
59
+ interface TapKitInstance {
58
60
  events: {
59
61
  seekTimeline: (params: SeekTimelineParamsType) => void;
60
62
  onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;
@@ -68,10 +70,11 @@ interface TapSDKInstance {
68
70
  };
69
71
  isOpen: boolean;
70
72
  isInitialized: boolean;
71
- init(params: TapSDKInitParams): Promise<void>;
73
+ readyPromise: Promise<void>;
74
+ init(params: TapKitInitParams): Promise<void>;
72
75
  destroy(): void;
73
76
  getVersion(): string;
74
- initChat(params: TapSDKInitParams): Promise<void>;
77
+ initChat(params: TapKitInitParams): Promise<void>;
75
78
  postChatInfo(params: {
76
79
  clipId: string;
77
80
  clipPlayHead: number;
@@ -80,18 +83,20 @@ interface TapSDKInstance {
80
83
  callback: (clipPlayHead: number, clipId: string) => void;
81
84
  }): Promise<void>;
82
85
  }
86
+ declare const SDK_INSTANCE: unique symbol;
87
+ declare const SDK_INSTANCE_LOADING: unique symbol;
83
88
  /**
84
- * TapSDK Wrapper Class
89
+ * TapKit Wrapper Class
85
90
  *
86
91
  * Loads the CDN loader and proxies all calls to the actual SDK
87
92
  */
88
- declare class TapSDK implements TapSDKInstance {
89
- private config;
90
- private sdkInstance?;
91
- private loadPromise;
92
- constructor(config: TapSDKConfig);
93
+ declare class TapKit implements TapKitInstance {
94
+ private [SDK_INSTANCE]?;
95
+ private [SDK_INSTANCE_LOADING];
96
+ constructor(config: TapKitConfig);
93
97
  private loadAndInitialize;
94
98
  private ensureLoaded;
99
+ get readyPromise(): Promise<void>;
95
100
  get events(): {
96
101
  seekTimeline: (params: SeekTimelineParamsType) => void;
97
102
  onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;
@@ -105,10 +110,10 @@ declare class TapSDK implements TapSDKInstance {
105
110
  };
106
111
  get isOpen(): boolean;
107
112
  get isInitialized(): boolean;
108
- init(params: TapSDKInitParams): Promise<void>;
113
+ init(params: TapKitInitParams): Promise<void>;
109
114
  destroy(): void;
110
115
  getVersion(): string;
111
- initChat(params: TapSDKInitParams): Promise<void>;
116
+ initChat(params: TapKitInitParams): Promise<void>;
112
117
  postChatInfo(params: {
113
118
  clipId: string;
114
119
  clipPlayHead: number;
@@ -118,4 +123,4 @@ declare class TapSDK implements TapSDKInstance {
118
123
  }): Promise<void>;
119
124
  }
120
125
 
121
- export { type ContainerStyle, type Course, type PositionType, type SeekTimelineParamsType, type TapSDKInstance as TapSDK, type TapSDKConfig, type TapSDKConstructor, type TapSDKInitParams, type TapSDKInstance, TapSDK as default };
126
+ export { type ContainerStyle, type Course, type PositionType, type SeekTimelineParamsType, type TapKitInstance as TapKit, type TapKitConfig, type TapKitConstructor, type TapKitInitParams, TapKit as default };
@@ -1,3 +1,3 @@
1
- var TapSDK=(function(){'use strict';var p=Object.defineProperty;var l=(i,e,n)=>e in i?p(i,e,{enumerable:true,configurable:true,writable:true,value:n}):i[e]=n;var t=(i,e,n)=>l(i,typeof e!="symbol"?e+"":e,n);var s="https://files.edutap.ai/tap-sdk/loader.js";function c(){if(window.__TAP_SDK_LOADER_LOADED__&&window.TapSDK)return Promise.resolve();if(window.__TAP_SDK_LOADER_LOADING__)return window.__TAP_SDK_LOADER_LOADING__;let i=new Promise((e,n)=>{if(typeof document>"u"){n(new Error("TapSDK requires browser environment (document is undefined)"));return}let o=document.createElement("script");o.src=s,o.async=true,o.onload=()=>{let a=()=>{window.TapSDK?(window.__TAP_SDK_LOADER_LOADED__=true,window.__TAP_SDK_LOADER_LOADING__=void 0,e()):setTimeout(a,50);};a();},o.onerror=()=>{window.__TAP_SDK_LOADER_LOADING__=void 0,n(new Error(`Failed to load TapSDK CDN loader: ${s}`));};let d=document.querySelector(`script[src="${s}"]`);d?(d.addEventListener("load",()=>{let a=()=>{window.TapSDK?e():setTimeout(a,50);};a();}),d.addEventListener("error",()=>n(new Error(`Failed to load TapSDK CDN loader: ${s}`)))):document.head.appendChild(o);});return window.__TAP_SDK_LOADER_LOADING__=i,i}var r=class{constructor(e){t(this,"config");t(this,"sdkInstance");t(this,"loadPromise");this.config=e,this.loadPromise=this.loadAndInitialize();}async loadAndInitialize(){if(await c(),!window.TapSDK)throw new Error("TapSDK not available after loading CDN loader");this.sdkInstance=new window.TapSDK(this.config);}async ensureLoaded(){if(await this.loadPromise,!this.sdkInstance)throw new Error("TapSDK instance not initialized");return this.sdkInstance}get events(){return {seekTimeline:e=>{this.ensureLoaded().then(n=>n.events.seekTimeline(e));},onTimelineSeek:e=>{this.ensureLoaded().then(n=>n.events.onTimelineSeek(e));},onChatInitiated:e=>{this.ensureLoaded().then(n=>n.events.onChatInitiated(e));},onChatOpened:e=>{this.ensureLoaded().then(n=>n.events.onChatOpened(e));},onChatClosed:e=>{this.ensureLoaded().then(n=>n.events.onChatClosed(e));},onAlarmFadeIn:e=>{this.ensureLoaded().then(n=>n.events.onAlarmFadeIn(e));},onPopUpOpen:e=>{this.ensureLoaded().then(n=>n.events.onPopUpOpen(e));},onPdfOpen:e=>{this.ensureLoaded().then(n=>n.events.onPdfOpen(e));},onPdfClose:e=>{this.ensureLoaded().then(n=>n.events.onPdfClose(e));}}}get isOpen(){return this.sdkInstance?.isOpen??false}get isInitialized(){return this.sdkInstance?.isInitialized??false}async init(e){return (await this.ensureLoaded()).init(e)}destroy(){this.sdkInstance&&this.sdkInstance.destroy();}getVersion(){return this.sdkInstance?.getVersion()??"Not initialized"}async initChat(e){return (await this.ensureLoaded()).initChat(e)}async postChatInfo(e){return (await this.ensureLoaded()).postChatInfo(e)}async getTimelineInfo(e){return (await this.ensureLoaded()).getTimelineInfo(e)}},D=r;
2
- return D;})();//# sourceMappingURL=index.global.js.map
1
+ var TapSDK=(function(){'use strict';var T=Object.defineProperty;var _=(n,e,i)=>e in n?T(n,e,{enumerable:true,configurable:true,writable:true,value:i}):n[e]=i;var r=(n,e,i)=>_(n,typeof e!="symbol"?e+"":e,i);typeof localStorage<"u"&&(localStorage.setItem("tap-url-storage",JSON.stringify({state:{tapUrl:"https://demo-edutap.vercel.app"}})),localStorage.setItem("tap-api-url-storage",JSON.stringify({state:{apiUrl:"https://tapadminstaging.coxwave.link"}})),localStorage.setItem("tap-environment","demo"),console.log("[TapSDK Demo] Environment configured:",{tapUrl:"https://demo-edutap.vercel.app",apiUrl:"https://tapadminstaging.coxwave.link",environment:"demo"}));var s="https://files.edutap.ai/tap-sdk/loader.js";function v(){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let n=new Promise((e,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}let o=document.createElement("script");o.src=s,o.async=true,o.onload=()=>{let a=()=>{window.TapKit?(window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e()):setTimeout(a,50);};a();},o.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${s}`));};let d=document.querySelector(`script[src="${s}"]`);d?(d.addEventListener("load",()=>{let a=()=>{window.TapKit?e():setTimeout(a,50);};a();}),d.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${s}`)))):document.head.appendChild(o);});return window.__TAP_KIT_LOADER_LOADING__=n,n}var t=Symbol("sdkInstance"),l=Symbol("sdkInstanceLoading"),c,m;m=t,c=l;var p=class{constructor(e){r(this,m);r(this,c);this[l]=this.loadAndInitialize(e);}async loadAndInitialize(e){if(console.log("[tap-sdk] Loading CDN loader..."),await v(),console.log("[tap-sdk] CDN loader loaded, window.TapKit:",!!window.TapKit),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");console.log("[tap-sdk] Creating TapKit instance..."),this[t]=new window.TapKit(e),console.log("[tap-sdk] TapKit instance created");}async ensureLoaded(){if(console.log("[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING..."),await this[l],console.log("[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed"),!this[t])throw new Error("TapKit instance not initialized");return console.log("[tap-sdk] ensureLoaded: returning SDK instance"),this[t]}get readyPromise(){return this.ensureLoaded().then(e=>e.readyPromise)}get events(){return {seekTimeline:e=>{this.ensureLoaded().then(i=>i.events.seekTimeline(e));},onTimelineSeek:e=>{this.ensureLoaded().then(i=>i.events.onTimelineSeek(e));},onChatInitiated:e=>{this.ensureLoaded().then(i=>i.events.onChatInitiated(e));},onChatOpened:e=>{this.ensureLoaded().then(i=>i.events.onChatOpened(e));},onChatClosed:e=>{this.ensureLoaded().then(i=>i.events.onChatClosed(e));},onAlarmFadeIn:e=>{this.ensureLoaded().then(i=>i.events.onAlarmFadeIn(e));},onPopUpOpen:e=>{this.ensureLoaded().then(i=>i.events.onPopUpOpen(e));},onPdfOpen:e=>{this.ensureLoaded().then(i=>i.events.onPdfOpen(e));},onPdfClose:e=>{this.ensureLoaded().then(i=>i.events.onPdfClose(e));}}}get isOpen(){return this[t]?.isOpen??false}get isInitialized(){return this[t]?.isInitialized??false}async init(e){return (await this.ensureLoaded()).init(e)}destroy(){this[t]&&this[t].destroy();}getVersion(){return this[t]?.getVersion()??"Not initialized"}async initChat(e){return (await this.ensureLoaded()).initChat(e)}async postChatInfo(e){return (await this.ensureLoaded()).postChatInfo(e)}async getTimelineInfo(e){return (await this.ensureLoaded()).getTimelineInfo(e)}},h=p;
2
+ return h;})();//# sourceMappingURL=index.global.js.map
3
3
  //# sourceMappingURL=index.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"names":["CDN_LOADER_URL","loadCDNLoader","loadingPromise","resolve","reject","script","checkSDK","existingScript","TapSDK","config","__publicField","params","sdk","callback","handler","index_default"],"mappings":"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","file":"index.global.js","sourcesContent":["/**\n * TapSDK - npm package wrapper\n *\n * Simply loads the CDN loader which handles version management and SDK loading.\n * This keeps the npm package minimal and allows instant updates via CDN.\n */\n\nimport type {\n TapSDKConfig,\n TapSDKInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n} from './types';\n\nconst CDN_LOADER_URL = 'https://files.edutap.ai/tap-sdk/loader.js';\n\n// Global namespace for loaded SDK\n// Export type for IIFE bundles loaded via window.TapSDK\nexport type TapSDKConstructor = new (config: TapSDKConfig) => TapSDKInstance;\n\ndeclare global {\n interface Window {\n TapSDK?: TapSDKConstructor;\n __TAP_SDK_LOADER_LOADED__?: boolean;\n __TAP_SDK_LOADER_LOADING__?: Promise<void>;\n }\n}\n\ninterface TapSDKInstance {\n events: {\n seekTimeline: (params: SeekTimelineParamsType) => void;\n onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;\n onChatInitiated: (handler: () => void) => void;\n onChatOpened: (handler: () => void) => void;\n onChatClosed: (handler: () => void) => void;\n onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => void;\n onPopUpOpen: (handler: (popUpInfo: any) => void) => void;\n onPdfOpen: (handler: () => void) => void;\n onPdfClose: (handler: () => void) => void;\n };\n isOpen: boolean;\n isInitialized: boolean;\n init(params: TapSDKInitParams): Promise<void>;\n destroy(): void;\n getVersion(): string;\n // Deprecated methods\n initChat(params: TapSDKInitParams): Promise<void>;\n postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;\n getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void>;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n */\nfunction loadCDNLoader(): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_SDK_LOADER_LOADED__ && window.TapSDK) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_SDK_LOADER_LOADING__) {\n return window.__TAP_SDK_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === 'undefined') {\n reject(new Error('TapSDK requires browser environment (document is undefined)'));\n return;\n }\n\n const script = document.createElement('script');\n script.src = CDN_LOADER_URL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = () => {\n if (window.TapSDK) {\n window.__TAP_SDK_LOADER_LOADED__ = true;\n window.__TAP_SDK_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n // Check again after a short delay\n setTimeout(checkSDK, 50);\n }\n };\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_SDK_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${CDN_LOADER_URL}\"]`);\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener('load', () => {\n const checkSDK = () => {\n if (window.TapSDK) resolve();\n else setTimeout(checkSDK, 50);\n };\n checkSDK();\n });\n existingScript.addEventListener('error', () =>\n reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`))\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_SDK_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n\n/**\n * TapSDK Wrapper Class\n *\n * Loads the CDN loader and proxies all calls to the actual SDK\n */\nclass TapSDK implements TapSDKInstance {\n private config: TapSDKConfig;\n private sdkInstance?: TapSDKInstance;\n private loadPromise: Promise<void>;\n\n constructor(config: TapSDKConfig) {\n this.config = config;\n this.loadPromise = this.loadAndInitialize();\n }\n\n private async loadAndInitialize(): Promise<void> {\n await loadCDNLoader();\n\n if (!window.TapSDK) {\n throw new Error('TapSDK not available after loading CDN loader');\n }\n\n this.sdkInstance = new window.TapSDK(this.config);\n }\n\n private async ensureLoaded(): Promise<TapSDKInstance> {\n await this.loadPromise;\n if (!this.sdkInstance) {\n throw new Error('TapSDK instance not initialized');\n }\n return this.sdkInstance;\n }\n\n // Public API - all methods proxy to the loaded SDK\n get events() {\n return {\n seekTimeline: (params: SeekTimelineParamsType) => {\n this.ensureLoaded().then(sdk => sdk.events.seekTimeline(params));\n },\n onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onTimelineSeek(callback));\n },\n onChatInitiated: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatInitiated(handler));\n },\n onChatOpened: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatOpened(handler));\n },\n onChatClosed: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatClosed(handler));\n },\n onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onAlarmFadeIn(handler));\n },\n onPopUpOpen: (handler: (popUpInfo: any) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPopUpOpen(handler));\n },\n onPdfOpen: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPdfOpen(handler));\n },\n onPdfClose: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPdfClose(handler));\n },\n };\n }\n\n get isOpen(): boolean {\n return this.sdkInstance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.sdkInstance?.isInitialized ?? false;\n }\n\n async init(params: TapSDKInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.init(params);\n }\n\n destroy(): void {\n if (this.sdkInstance) {\n this.sdkInstance.destroy();\n }\n }\n\n getVersion(): string {\n return this.sdkInstance?.getVersion() ?? 'Not initialized';\n }\n\n // Deprecated methods\n async initChat(params: TapSDKInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.initChat(params);\n }\n\n async postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.postChatInfo(params);\n }\n\n async getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.getTimelineInfo(params);\n }\n}\n\n// Export the SDK class as default (for: import TapSDK from '@coxwave/tap-sdk')\nexport default TapSDK;\n\n// Export TapSDK instance type (for: import type { TapSDK } from '@coxwave/tap-sdk')\nexport type { TapSDKInstance as TapSDK };\n\n// Keep TapSDKInstance for backward compatibility\nexport type { TapSDKInstance };\n\n// Re-export types for API compatibility\nexport type {\n TapSDKConfig,\n TapSDKInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n};\n"]}
1
+ {"version":3,"sources":["../index.ts"],"names":["CDN_LOADER_URL","loadCDNLoader","loadingPromise","resolve","reject","script","checkSDK","existingScript","SDK_INSTANCE","SDK_INSTANCE_LOADING","_a","_b","TapKit","config","__publicField","sdk","params","callback","handler","index_default"],"mappings":"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","file":"index.global.js","sourcesContent":["/**\n * TapKit wrapper - npm package wrapper\n *\n * Simply loads the CDN loader which handles version management and SDK loading.\n * This keeps the npm package minimal and allows instant updates via CDN.\n *\n * Demo version: Automatically configures localStorage for demo environment.\n */\n\n// Configure demo environment if this is the demo version\nif (typeof localStorage !== \"undefined\") {\n // Demo edutap FE URL\n localStorage.setItem(\n \"tap-url-storage\",\n JSON.stringify({\n state: { tapUrl: \"https://demo-edutap.vercel.app\" },\n })\n );\n\n // Demo API URL\n localStorage.setItem(\n \"tap-api-url-storage\",\n JSON.stringify({\n state: { apiUrl: \"https://tapadminstaging.coxwave.link\" },\n })\n );\n\n // Demo environment flag (enables console logging)\n localStorage.setItem(\"tap-environment\", \"demo\");\n\n console.log(\"[TapSDK Demo] Environment configured:\", {\n tapUrl: \"https://demo-edutap.vercel.app\",\n apiUrl: \"https://tapadminstaging.coxwave.link\",\n environment: \"demo\",\n });\n}\n\nimport type {\n TapKitConfig,\n TapKitInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n} from \"./types\";\n\nconst CDN_LOADER_URL = \"https://files.edutap.ai/tap-sdk/loader.js\";\n\n// Global namespace for loaded SDK\n// Export type for IIFE bundles loaded via window.TapKit\nexport type TapKitConstructor = new (config: TapKitConfig) => TapKitInstance;\n\ndeclare global {\n interface Window {\n TapKit?: TapKitConstructor;\n __TAP_KIT_LOADER_LOADED__?: boolean;\n __TAP_KIT_LOADER_LOADING__?: Promise<void>;\n }\n}\n\ninterface TapKitInstance {\n events: {\n seekTimeline: (params: SeekTimelineParamsType) => void;\n onTimelineSeek: (\n callback: (clipPlayHead: number, clipId: string) => void\n ) => void;\n onChatInitiated: (handler: () => void) => void;\n onChatOpened: (handler: () => void) => void;\n onChatClosed: (handler: () => void) => void;\n onAlarmFadeIn: (\n handler: (messageInfo: AlarmMessageInstanceType) => void\n ) => void;\n onPopUpOpen: (handler: (popUpInfo: any) => void) => void;\n onPdfOpen: (handler: () => void) => void;\n onPdfClose: (handler: () => void) => void;\n };\n isOpen: boolean;\n isInitialized: boolean;\n readyPromise: Promise<void>;\n init(params: TapKitInitParams): Promise<void>;\n destroy(): void;\n getVersion(): string;\n // Deprecated methods\n initChat(params: TapKitInitParams): Promise<void>;\n postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;\n getTimelineInfo(params: {\n callback: (clipPlayHead: number, clipId: string) => void;\n }): Promise<void>;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n */\nfunction loadCDNLoader(): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\"TapKit requires browser environment (document is undefined)\")\n );\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = CDN_LOADER_URL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = () => {\n if (window.TapKit) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n // Check again after a short delay\n setTimeout(checkSDK, 50);\n }\n };\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(\n `script[src=\"${CDN_LOADER_URL}\"]`\n );\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = () => {\n if (window.TapKit) resolve();\n else setTimeout(checkSDK, 50);\n };\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`))\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n\n// Use Symbol to hide SDK instance from enumeration\nconst SDK_INSTANCE = Symbol(\"sdkInstance\");\nconst SDK_INSTANCE_LOADING = Symbol(\"sdkInstanceLoading\");\n\n/**\n * TapKit Wrapper Class\n *\n * Loads the CDN loader and proxies all calls to the actual SDK\n */\nclass TapKit implements TapKitInstance {\n private [SDK_INSTANCE]?: TapKitInstance;\n private [SDK_INSTANCE_LOADING]: Promise<void>;\n\n constructor(config: TapKitConfig) {\n this[SDK_INSTANCE_LOADING] = this.loadAndInitialize(config);\n }\n\n private async loadAndInitialize(config: TapKitConfig): Promise<void> {\n console.log(\"[tap-sdk] Loading CDN loader...\");\n await loadCDNLoader();\n console.log(\"[tap-sdk] CDN loader loaded, window.TapKit:\", !!window.TapKit);\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n console.log(\"[tap-sdk] Creating TapKit instance...\");\n this[SDK_INSTANCE] = new window.TapKit(config);\n console.log(\"[tap-sdk] TapKit instance created\");\n }\n\n private async ensureLoaded(): Promise<TapKitInstance> {\n console.log(\"[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING...\");\n await this[SDK_INSTANCE_LOADING]; // Wait for SDK instance to be created\n console.log(\"[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed\");\n\n if (!this[SDK_INSTANCE]) {\n throw new Error(\"TapKit instance not initialized\");\n }\n\n console.log(\"[tap-sdk] ensureLoaded: returning SDK instance\");\n return this[SDK_INSTANCE];\n }\n\n // Expose tap-kit-core's readyPromise for advanced users\n // This resolves after init() is called and tap-kit-core is fully initialized\n get readyPromise(): Promise<void> {\n return this.ensureLoaded().then((sdk) => sdk.readyPromise);\n }\n\n // Public API - all methods proxy to the loaded SDK\n get events() {\n return {\n seekTimeline: (params: SeekTimelineParamsType) => {\n this.ensureLoaded().then((sdk) => sdk.events.seekTimeline(params));\n },\n onTimelineSeek: (\n callback: (clipPlayHead: number, clipId: string) => void\n ) => {\n this.ensureLoaded().then((sdk) => sdk.events.onTimelineSeek(callback));\n },\n onChatInitiated: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatInitiated(handler));\n },\n onChatOpened: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatOpened(handler));\n },\n onChatClosed: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatClosed(handler));\n },\n onAlarmFadeIn: (\n handler: (messageInfo: AlarmMessageInstanceType) => void\n ) => {\n this.ensureLoaded().then((sdk) => sdk.events.onAlarmFadeIn(handler));\n },\n onPopUpOpen: (handler: (popUpInfo: any) => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPopUpOpen(handler));\n },\n onPdfOpen: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPdfOpen(handler));\n },\n onPdfClose: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPdfClose(handler));\n },\n };\n }\n\n get isOpen(): boolean {\n return this[SDK_INSTANCE]?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this[SDK_INSTANCE]?.isInitialized ?? false;\n }\n\n async init(params: TapKitInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.init(params);\n }\n\n destroy(): void {\n if (this[SDK_INSTANCE]) {\n this[SDK_INSTANCE].destroy();\n }\n }\n\n getVersion(): string {\n return this[SDK_INSTANCE]?.getVersion() ?? \"Not initialized\";\n }\n\n // Deprecated methods\n async initChat(params: TapKitInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.initChat(params);\n }\n\n async postChatInfo(params: {\n clipId: string;\n clipPlayHead: number;\n }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.postChatInfo(params);\n }\n\n async getTimelineInfo(params: {\n callback: (clipPlayHead: number, clipId: string) => void;\n }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.getTimelineInfo(params);\n }\n}\n\n// Export the SDK class as default (for: import TapKit from '@coxwave/tap-sdk')\nexport default TapKit;\n\n// Export TapKit instance type (for: import type { TapKit } from '@coxwave/tap-sdk')\nexport type { TapKitInstance as TapKit };\n\n// Re-export types for API compatibility\nexport type {\n TapKitConfig,\n TapKitInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n};\n"]}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var p=Object.defineProperty;var l=(i,e,n)=>e in i?p(i,e,{enumerable:true,configurable:true,writable:true,value:n}):i[e]=n;var t=(i,e,n)=>l(i,typeof e!="symbol"?e+"":e,n);var s="https://files.edutap.ai/tap-sdk/loader.js";function c(){if(window.__TAP_SDK_LOADER_LOADED__&&window.TapSDK)return Promise.resolve();if(window.__TAP_SDK_LOADER_LOADING__)return window.__TAP_SDK_LOADER_LOADING__;let i=new Promise((e,n)=>{if(typeof document>"u"){n(new Error("TapSDK requires browser environment (document is undefined)"));return}let o=document.createElement("script");o.src=s,o.async=true,o.onload=()=>{let a=()=>{window.TapSDK?(window.__TAP_SDK_LOADER_LOADED__=true,window.__TAP_SDK_LOADER_LOADING__=void 0,e()):setTimeout(a,50);};a();},o.onerror=()=>{window.__TAP_SDK_LOADER_LOADING__=void 0,n(new Error(`Failed to load TapSDK CDN loader: ${s}`));};let d=document.querySelector(`script[src="${s}"]`);d?(d.addEventListener("load",()=>{let a=()=>{window.TapSDK?e():setTimeout(a,50);};a();}),d.addEventListener("error",()=>n(new Error(`Failed to load TapSDK CDN loader: ${s}`)))):document.head.appendChild(o);});return window.__TAP_SDK_LOADER_LOADING__=i,i}var r=class{constructor(e){t(this,"config");t(this,"sdkInstance");t(this,"loadPromise");this.config=e,this.loadPromise=this.loadAndInitialize();}async loadAndInitialize(){if(await c(),!window.TapSDK)throw new Error("TapSDK not available after loading CDN loader");this.sdkInstance=new window.TapSDK(this.config);}async ensureLoaded(){if(await this.loadPromise,!this.sdkInstance)throw new Error("TapSDK instance not initialized");return this.sdkInstance}get events(){return {seekTimeline:e=>{this.ensureLoaded().then(n=>n.events.seekTimeline(e));},onTimelineSeek:e=>{this.ensureLoaded().then(n=>n.events.onTimelineSeek(e));},onChatInitiated:e=>{this.ensureLoaded().then(n=>n.events.onChatInitiated(e));},onChatOpened:e=>{this.ensureLoaded().then(n=>n.events.onChatOpened(e));},onChatClosed:e=>{this.ensureLoaded().then(n=>n.events.onChatClosed(e));},onAlarmFadeIn:e=>{this.ensureLoaded().then(n=>n.events.onAlarmFadeIn(e));},onPopUpOpen:e=>{this.ensureLoaded().then(n=>n.events.onPopUpOpen(e));},onPdfOpen:e=>{this.ensureLoaded().then(n=>n.events.onPdfOpen(e));},onPdfClose:e=>{this.ensureLoaded().then(n=>n.events.onPdfClose(e));}}}get isOpen(){return this.sdkInstance?.isOpen??false}get isInitialized(){return this.sdkInstance?.isInitialized??false}async init(e){return (await this.ensureLoaded()).init(e)}destroy(){this.sdkInstance&&this.sdkInstance.destroy();}getVersion(){return this.sdkInstance?.getVersion()??"Not initialized"}async initChat(e){return (await this.ensureLoaded()).initChat(e)}async postChatInfo(e){return (await this.ensureLoaded()).postChatInfo(e)}async getTimelineInfo(e){return (await this.ensureLoaded()).getTimelineInfo(e)}},D=r;
2
- module.exports=D;//# sourceMappingURL=index.js.map
1
+ 'use strict';var T=Object.defineProperty;var _=(n,e,i)=>e in n?T(n,e,{enumerable:true,configurable:true,writable:true,value:i}):n[e]=i;var r=(n,e,i)=>_(n,typeof e!="symbol"?e+"":e,i);typeof localStorage<"u"&&(localStorage.setItem("tap-url-storage",JSON.stringify({state:{tapUrl:"https://demo-edutap.vercel.app"}})),localStorage.setItem("tap-api-url-storage",JSON.stringify({state:{apiUrl:"https://tapadminstaging.coxwave.link"}})),localStorage.setItem("tap-environment","demo"),console.log("[TapSDK Demo] Environment configured:",{tapUrl:"https://demo-edutap.vercel.app",apiUrl:"https://tapadminstaging.coxwave.link",environment:"demo"}));var s="https://files.edutap.ai/tap-sdk/loader.js";function v(){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let n=new Promise((e,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}let o=document.createElement("script");o.src=s,o.async=true,o.onload=()=>{let a=()=>{window.TapKit?(window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e()):setTimeout(a,50);};a();},o.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${s}`));};let d=document.querySelector(`script[src="${s}"]`);d?(d.addEventListener("load",()=>{let a=()=>{window.TapKit?e():setTimeout(a,50);};a();}),d.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${s}`)))):document.head.appendChild(o);});return window.__TAP_KIT_LOADER_LOADING__=n,n}var t=Symbol("sdkInstance"),l=Symbol("sdkInstanceLoading"),c,m;m=t,c=l;var p=class{constructor(e){r(this,m);r(this,c);this[l]=this.loadAndInitialize(e);}async loadAndInitialize(e){if(console.log("[tap-sdk] Loading CDN loader..."),await v(),console.log("[tap-sdk] CDN loader loaded, window.TapKit:",!!window.TapKit),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");console.log("[tap-sdk] Creating TapKit instance..."),this[t]=new window.TapKit(e),console.log("[tap-sdk] TapKit instance created");}async ensureLoaded(){if(console.log("[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING..."),await this[l],console.log("[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed"),!this[t])throw new Error("TapKit instance not initialized");return console.log("[tap-sdk] ensureLoaded: returning SDK instance"),this[t]}get readyPromise(){return this.ensureLoaded().then(e=>e.readyPromise)}get events(){return {seekTimeline:e=>{this.ensureLoaded().then(i=>i.events.seekTimeline(e));},onTimelineSeek:e=>{this.ensureLoaded().then(i=>i.events.onTimelineSeek(e));},onChatInitiated:e=>{this.ensureLoaded().then(i=>i.events.onChatInitiated(e));},onChatOpened:e=>{this.ensureLoaded().then(i=>i.events.onChatOpened(e));},onChatClosed:e=>{this.ensureLoaded().then(i=>i.events.onChatClosed(e));},onAlarmFadeIn:e=>{this.ensureLoaded().then(i=>i.events.onAlarmFadeIn(e));},onPopUpOpen:e=>{this.ensureLoaded().then(i=>i.events.onPopUpOpen(e));},onPdfOpen:e=>{this.ensureLoaded().then(i=>i.events.onPdfOpen(e));},onPdfClose:e=>{this.ensureLoaded().then(i=>i.events.onPdfClose(e));}}}get isOpen(){return this[t]?.isOpen??false}get isInitialized(){return this[t]?.isInitialized??false}async init(e){return (await this.ensureLoaded()).init(e)}destroy(){this[t]&&this[t].destroy();}getVersion(){return this[t]?.getVersion()??"Not initialized"}async initChat(e){return (await this.ensureLoaded()).initChat(e)}async postChatInfo(e){return (await this.ensureLoaded()).postChatInfo(e)}async getTimelineInfo(e){return (await this.ensureLoaded()).getTimelineInfo(e)}},h=p;
2
+ module.exports=h;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"names":["CDN_LOADER_URL","loadCDNLoader","loadingPromise","resolve","reject","script","checkSDK","existingScript","TapSDK","config","__publicField","params","sdk","callback","handler","index_default"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * TapSDK - npm package wrapper\n *\n * Simply loads the CDN loader which handles version management and SDK loading.\n * This keeps the npm package minimal and allows instant updates via CDN.\n */\n\nimport type {\n TapSDKConfig,\n TapSDKInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n} from './types';\n\nconst CDN_LOADER_URL = 'https://files.edutap.ai/tap-sdk/loader.js';\n\n// Global namespace for loaded SDK\n// Export type for IIFE bundles loaded via window.TapSDK\nexport type TapSDKConstructor = new (config: TapSDKConfig) => TapSDKInstance;\n\ndeclare global {\n interface Window {\n TapSDK?: TapSDKConstructor;\n __TAP_SDK_LOADER_LOADED__?: boolean;\n __TAP_SDK_LOADER_LOADING__?: Promise<void>;\n }\n}\n\ninterface TapSDKInstance {\n events: {\n seekTimeline: (params: SeekTimelineParamsType) => void;\n onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;\n onChatInitiated: (handler: () => void) => void;\n onChatOpened: (handler: () => void) => void;\n onChatClosed: (handler: () => void) => void;\n onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => void;\n onPopUpOpen: (handler: (popUpInfo: any) => void) => void;\n onPdfOpen: (handler: () => void) => void;\n onPdfClose: (handler: () => void) => void;\n };\n isOpen: boolean;\n isInitialized: boolean;\n init(params: TapSDKInitParams): Promise<void>;\n destroy(): void;\n getVersion(): string;\n // Deprecated methods\n initChat(params: TapSDKInitParams): Promise<void>;\n postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;\n getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void>;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n */\nfunction loadCDNLoader(): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_SDK_LOADER_LOADED__ && window.TapSDK) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_SDK_LOADER_LOADING__) {\n return window.__TAP_SDK_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === 'undefined') {\n reject(new Error('TapSDK requires browser environment (document is undefined)'));\n return;\n }\n\n const script = document.createElement('script');\n script.src = CDN_LOADER_URL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = () => {\n if (window.TapSDK) {\n window.__TAP_SDK_LOADER_LOADED__ = true;\n window.__TAP_SDK_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n // Check again after a short delay\n setTimeout(checkSDK, 50);\n }\n };\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_SDK_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${CDN_LOADER_URL}\"]`);\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener('load', () => {\n const checkSDK = () => {\n if (window.TapSDK) resolve();\n else setTimeout(checkSDK, 50);\n };\n checkSDK();\n });\n existingScript.addEventListener('error', () =>\n reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`))\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_SDK_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n\n/**\n * TapSDK Wrapper Class\n *\n * Loads the CDN loader and proxies all calls to the actual SDK\n */\nclass TapSDK implements TapSDKInstance {\n private config: TapSDKConfig;\n private sdkInstance?: TapSDKInstance;\n private loadPromise: Promise<void>;\n\n constructor(config: TapSDKConfig) {\n this.config = config;\n this.loadPromise = this.loadAndInitialize();\n }\n\n private async loadAndInitialize(): Promise<void> {\n await loadCDNLoader();\n\n if (!window.TapSDK) {\n throw new Error('TapSDK not available after loading CDN loader');\n }\n\n this.sdkInstance = new window.TapSDK(this.config);\n }\n\n private async ensureLoaded(): Promise<TapSDKInstance> {\n await this.loadPromise;\n if (!this.sdkInstance) {\n throw new Error('TapSDK instance not initialized');\n }\n return this.sdkInstance;\n }\n\n // Public API - all methods proxy to the loaded SDK\n get events() {\n return {\n seekTimeline: (params: SeekTimelineParamsType) => {\n this.ensureLoaded().then(sdk => sdk.events.seekTimeline(params));\n },\n onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onTimelineSeek(callback));\n },\n onChatInitiated: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatInitiated(handler));\n },\n onChatOpened: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatOpened(handler));\n },\n onChatClosed: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatClosed(handler));\n },\n onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onAlarmFadeIn(handler));\n },\n onPopUpOpen: (handler: (popUpInfo: any) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPopUpOpen(handler));\n },\n onPdfOpen: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPdfOpen(handler));\n },\n onPdfClose: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPdfClose(handler));\n },\n };\n }\n\n get isOpen(): boolean {\n return this.sdkInstance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.sdkInstance?.isInitialized ?? false;\n }\n\n async init(params: TapSDKInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.init(params);\n }\n\n destroy(): void {\n if (this.sdkInstance) {\n this.sdkInstance.destroy();\n }\n }\n\n getVersion(): string {\n return this.sdkInstance?.getVersion() ?? 'Not initialized';\n }\n\n // Deprecated methods\n async initChat(params: TapSDKInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.initChat(params);\n }\n\n async postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.postChatInfo(params);\n }\n\n async getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.getTimelineInfo(params);\n }\n}\n\n// Export the SDK class as default (for: import TapSDK from '@coxwave/tap-sdk')\nexport default TapSDK;\n\n// Export TapSDK instance type (for: import type { TapSDK } from '@coxwave/tap-sdk')\nexport type { TapSDKInstance as TapSDK };\n\n// Keep TapSDKInstance for backward compatibility\nexport type { TapSDKInstance };\n\n// Re-export types for API compatibility\nexport type {\n TapSDKConfig,\n TapSDKInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n};\n"]}
1
+ {"version":3,"sources":["../index.ts"],"names":["CDN_LOADER_URL","loadCDNLoader","loadingPromise","resolve","reject","script","checkSDK","existingScript","SDK_INSTANCE","SDK_INSTANCE_LOADING","_a","_b","TapKit","config","__publicField","sdk","params","callback","handler","index_default"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * TapKit wrapper - npm package wrapper\n *\n * Simply loads the CDN loader which handles version management and SDK loading.\n * This keeps the npm package minimal and allows instant updates via CDN.\n *\n * Demo version: Automatically configures localStorage for demo environment.\n */\n\n// Configure demo environment if this is the demo version\nif (typeof localStorage !== \"undefined\") {\n // Demo edutap FE URL\n localStorage.setItem(\n \"tap-url-storage\",\n JSON.stringify({\n state: { tapUrl: \"https://demo-edutap.vercel.app\" },\n })\n );\n\n // Demo API URL\n localStorage.setItem(\n \"tap-api-url-storage\",\n JSON.stringify({\n state: { apiUrl: \"https://tapadminstaging.coxwave.link\" },\n })\n );\n\n // Demo environment flag (enables console logging)\n localStorage.setItem(\"tap-environment\", \"demo\");\n\n console.log(\"[TapSDK Demo] Environment configured:\", {\n tapUrl: \"https://demo-edutap.vercel.app\",\n apiUrl: \"https://tapadminstaging.coxwave.link\",\n environment: \"demo\",\n });\n}\n\nimport type {\n TapKitConfig,\n TapKitInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n} from \"./types\";\n\nconst CDN_LOADER_URL = \"https://files.edutap.ai/tap-sdk/loader.js\";\n\n// Global namespace for loaded SDK\n// Export type for IIFE bundles loaded via window.TapKit\nexport type TapKitConstructor = new (config: TapKitConfig) => TapKitInstance;\n\ndeclare global {\n interface Window {\n TapKit?: TapKitConstructor;\n __TAP_KIT_LOADER_LOADED__?: boolean;\n __TAP_KIT_LOADER_LOADING__?: Promise<void>;\n }\n}\n\ninterface TapKitInstance {\n events: {\n seekTimeline: (params: SeekTimelineParamsType) => void;\n onTimelineSeek: (\n callback: (clipPlayHead: number, clipId: string) => void\n ) => void;\n onChatInitiated: (handler: () => void) => void;\n onChatOpened: (handler: () => void) => void;\n onChatClosed: (handler: () => void) => void;\n onAlarmFadeIn: (\n handler: (messageInfo: AlarmMessageInstanceType) => void\n ) => void;\n onPopUpOpen: (handler: (popUpInfo: any) => void) => void;\n onPdfOpen: (handler: () => void) => void;\n onPdfClose: (handler: () => void) => void;\n };\n isOpen: boolean;\n isInitialized: boolean;\n readyPromise: Promise<void>;\n init(params: TapKitInitParams): Promise<void>;\n destroy(): void;\n getVersion(): string;\n // Deprecated methods\n initChat(params: TapKitInitParams): Promise<void>;\n postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;\n getTimelineInfo(params: {\n callback: (clipPlayHead: number, clipId: string) => void;\n }): Promise<void>;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n */\nfunction loadCDNLoader(): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\"TapKit requires browser environment (document is undefined)\")\n );\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = CDN_LOADER_URL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = () => {\n if (window.TapKit) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n // Check again after a short delay\n setTimeout(checkSDK, 50);\n }\n };\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(\n `script[src=\"${CDN_LOADER_URL}\"]`\n );\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = () => {\n if (window.TapKit) resolve();\n else setTimeout(checkSDK, 50);\n };\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`))\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n\n// Use Symbol to hide SDK instance from enumeration\nconst SDK_INSTANCE = Symbol(\"sdkInstance\");\nconst SDK_INSTANCE_LOADING = Symbol(\"sdkInstanceLoading\");\n\n/**\n * TapKit Wrapper Class\n *\n * Loads the CDN loader and proxies all calls to the actual SDK\n */\nclass TapKit implements TapKitInstance {\n private [SDK_INSTANCE]?: TapKitInstance;\n private [SDK_INSTANCE_LOADING]: Promise<void>;\n\n constructor(config: TapKitConfig) {\n this[SDK_INSTANCE_LOADING] = this.loadAndInitialize(config);\n }\n\n private async loadAndInitialize(config: TapKitConfig): Promise<void> {\n console.log(\"[tap-sdk] Loading CDN loader...\");\n await loadCDNLoader();\n console.log(\"[tap-sdk] CDN loader loaded, window.TapKit:\", !!window.TapKit);\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n console.log(\"[tap-sdk] Creating TapKit instance...\");\n this[SDK_INSTANCE] = new window.TapKit(config);\n console.log(\"[tap-sdk] TapKit instance created\");\n }\n\n private async ensureLoaded(): Promise<TapKitInstance> {\n console.log(\"[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING...\");\n await this[SDK_INSTANCE_LOADING]; // Wait for SDK instance to be created\n console.log(\"[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed\");\n\n if (!this[SDK_INSTANCE]) {\n throw new Error(\"TapKit instance not initialized\");\n }\n\n console.log(\"[tap-sdk] ensureLoaded: returning SDK instance\");\n return this[SDK_INSTANCE];\n }\n\n // Expose tap-kit-core's readyPromise for advanced users\n // This resolves after init() is called and tap-kit-core is fully initialized\n get readyPromise(): Promise<void> {\n return this.ensureLoaded().then((sdk) => sdk.readyPromise);\n }\n\n // Public API - all methods proxy to the loaded SDK\n get events() {\n return {\n seekTimeline: (params: SeekTimelineParamsType) => {\n this.ensureLoaded().then((sdk) => sdk.events.seekTimeline(params));\n },\n onTimelineSeek: (\n callback: (clipPlayHead: number, clipId: string) => void\n ) => {\n this.ensureLoaded().then((sdk) => sdk.events.onTimelineSeek(callback));\n },\n onChatInitiated: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatInitiated(handler));\n },\n onChatOpened: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatOpened(handler));\n },\n onChatClosed: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatClosed(handler));\n },\n onAlarmFadeIn: (\n handler: (messageInfo: AlarmMessageInstanceType) => void\n ) => {\n this.ensureLoaded().then((sdk) => sdk.events.onAlarmFadeIn(handler));\n },\n onPopUpOpen: (handler: (popUpInfo: any) => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPopUpOpen(handler));\n },\n onPdfOpen: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPdfOpen(handler));\n },\n onPdfClose: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPdfClose(handler));\n },\n };\n }\n\n get isOpen(): boolean {\n return this[SDK_INSTANCE]?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this[SDK_INSTANCE]?.isInitialized ?? false;\n }\n\n async init(params: TapKitInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.init(params);\n }\n\n destroy(): void {\n if (this[SDK_INSTANCE]) {\n this[SDK_INSTANCE].destroy();\n }\n }\n\n getVersion(): string {\n return this[SDK_INSTANCE]?.getVersion() ?? \"Not initialized\";\n }\n\n // Deprecated methods\n async initChat(params: TapKitInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.initChat(params);\n }\n\n async postChatInfo(params: {\n clipId: string;\n clipPlayHead: number;\n }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.postChatInfo(params);\n }\n\n async getTimelineInfo(params: {\n callback: (clipPlayHead: number, clipId: string) => void;\n }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.getTimelineInfo(params);\n }\n}\n\n// Export the SDK class as default (for: import TapKit from '@coxwave/tap-sdk')\nexport default TapKit;\n\n// Export TapKit instance type (for: import type { TapKit } from '@coxwave/tap-sdk')\nexport type { TapKitInstance as TapKit };\n\n// Re-export types for API compatibility\nexport type {\n TapKitConfig,\n TapKitInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n};\n"]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var p=Object.defineProperty;var l=(i,e,n)=>e in i?p(i,e,{enumerable:true,configurable:true,writable:true,value:n}):i[e]=n;var t=(i,e,n)=>l(i,typeof e!="symbol"?e+"":e,n);var s="https://files.edutap.ai/tap-sdk/loader.js";function c(){if(window.__TAP_SDK_LOADER_LOADED__&&window.TapSDK)return Promise.resolve();if(window.__TAP_SDK_LOADER_LOADING__)return window.__TAP_SDK_LOADER_LOADING__;let i=new Promise((e,n)=>{if(typeof document>"u"){n(new Error("TapSDK requires browser environment (document is undefined)"));return}let o=document.createElement("script");o.src=s,o.async=true,o.onload=()=>{let a=()=>{window.TapSDK?(window.__TAP_SDK_LOADER_LOADED__=true,window.__TAP_SDK_LOADER_LOADING__=void 0,e()):setTimeout(a,50);};a();},o.onerror=()=>{window.__TAP_SDK_LOADER_LOADING__=void 0,n(new Error(`Failed to load TapSDK CDN loader: ${s}`));};let d=document.querySelector(`script[src="${s}"]`);d?(d.addEventListener("load",()=>{let a=()=>{window.TapSDK?e():setTimeout(a,50);};a();}),d.addEventListener("error",()=>n(new Error(`Failed to load TapSDK CDN loader: ${s}`)))):document.head.appendChild(o);});return window.__TAP_SDK_LOADER_LOADING__=i,i}var r=class{constructor(e){t(this,"config");t(this,"sdkInstance");t(this,"loadPromise");this.config=e,this.loadPromise=this.loadAndInitialize();}async loadAndInitialize(){if(await c(),!window.TapSDK)throw new Error("TapSDK not available after loading CDN loader");this.sdkInstance=new window.TapSDK(this.config);}async ensureLoaded(){if(await this.loadPromise,!this.sdkInstance)throw new Error("TapSDK instance not initialized");return this.sdkInstance}get events(){return {seekTimeline:e=>{this.ensureLoaded().then(n=>n.events.seekTimeline(e));},onTimelineSeek:e=>{this.ensureLoaded().then(n=>n.events.onTimelineSeek(e));},onChatInitiated:e=>{this.ensureLoaded().then(n=>n.events.onChatInitiated(e));},onChatOpened:e=>{this.ensureLoaded().then(n=>n.events.onChatOpened(e));},onChatClosed:e=>{this.ensureLoaded().then(n=>n.events.onChatClosed(e));},onAlarmFadeIn:e=>{this.ensureLoaded().then(n=>n.events.onAlarmFadeIn(e));},onPopUpOpen:e=>{this.ensureLoaded().then(n=>n.events.onPopUpOpen(e));},onPdfOpen:e=>{this.ensureLoaded().then(n=>n.events.onPdfOpen(e));},onPdfClose:e=>{this.ensureLoaded().then(n=>n.events.onPdfClose(e));}}}get isOpen(){return this.sdkInstance?.isOpen??false}get isInitialized(){return this.sdkInstance?.isInitialized??false}async init(e){return (await this.ensureLoaded()).init(e)}destroy(){this.sdkInstance&&this.sdkInstance.destroy();}getVersion(){return this.sdkInstance?.getVersion()??"Not initialized"}async initChat(e){return (await this.ensureLoaded()).initChat(e)}async postChatInfo(e){return (await this.ensureLoaded()).postChatInfo(e)}async getTimelineInfo(e){return (await this.ensureLoaded()).getTimelineInfo(e)}},D=r;
2
- export{D as default};//# sourceMappingURL=index.mjs.map
1
+ var T=Object.defineProperty;var _=(n,e,i)=>e in n?T(n,e,{enumerable:true,configurable:true,writable:true,value:i}):n[e]=i;var r=(n,e,i)=>_(n,typeof e!="symbol"?e+"":e,i);typeof localStorage<"u"&&(localStorage.setItem("tap-url-storage",JSON.stringify({state:{tapUrl:"https://demo-edutap.vercel.app"}})),localStorage.setItem("tap-api-url-storage",JSON.stringify({state:{apiUrl:"https://tapadminstaging.coxwave.link"}})),localStorage.setItem("tap-environment","demo"),console.log("[TapSDK Demo] Environment configured:",{tapUrl:"https://demo-edutap.vercel.app",apiUrl:"https://tapadminstaging.coxwave.link",environment:"demo"}));var s="https://files.edutap.ai/tap-sdk/loader.js";function v(){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let n=new Promise((e,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}let o=document.createElement("script");o.src=s,o.async=true,o.onload=()=>{let a=()=>{window.TapKit?(window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e()):setTimeout(a,50);};a();},o.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${s}`));};let d=document.querySelector(`script[src="${s}"]`);d?(d.addEventListener("load",()=>{let a=()=>{window.TapKit?e():setTimeout(a,50);};a();}),d.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${s}`)))):document.head.appendChild(o);});return window.__TAP_KIT_LOADER_LOADING__=n,n}var t=Symbol("sdkInstance"),l=Symbol("sdkInstanceLoading"),c,m;m=t,c=l;var p=class{constructor(e){r(this,m);r(this,c);this[l]=this.loadAndInitialize(e);}async loadAndInitialize(e){if(console.log("[tap-sdk] Loading CDN loader..."),await v(),console.log("[tap-sdk] CDN loader loaded, window.TapKit:",!!window.TapKit),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");console.log("[tap-sdk] Creating TapKit instance..."),this[t]=new window.TapKit(e),console.log("[tap-sdk] TapKit instance created");}async ensureLoaded(){if(console.log("[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING..."),await this[l],console.log("[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed"),!this[t])throw new Error("TapKit instance not initialized");return console.log("[tap-sdk] ensureLoaded: returning SDK instance"),this[t]}get readyPromise(){return this.ensureLoaded().then(e=>e.readyPromise)}get events(){return {seekTimeline:e=>{this.ensureLoaded().then(i=>i.events.seekTimeline(e));},onTimelineSeek:e=>{this.ensureLoaded().then(i=>i.events.onTimelineSeek(e));},onChatInitiated:e=>{this.ensureLoaded().then(i=>i.events.onChatInitiated(e));},onChatOpened:e=>{this.ensureLoaded().then(i=>i.events.onChatOpened(e));},onChatClosed:e=>{this.ensureLoaded().then(i=>i.events.onChatClosed(e));},onAlarmFadeIn:e=>{this.ensureLoaded().then(i=>i.events.onAlarmFadeIn(e));},onPopUpOpen:e=>{this.ensureLoaded().then(i=>i.events.onPopUpOpen(e));},onPdfOpen:e=>{this.ensureLoaded().then(i=>i.events.onPdfOpen(e));},onPdfClose:e=>{this.ensureLoaded().then(i=>i.events.onPdfClose(e));}}}get isOpen(){return this[t]?.isOpen??false}get isInitialized(){return this[t]?.isInitialized??false}async init(e){return (await this.ensureLoaded()).init(e)}destroy(){this[t]&&this[t].destroy();}getVersion(){return this[t]?.getVersion()??"Not initialized"}async initChat(e){return (await this.ensureLoaded()).initChat(e)}async postChatInfo(e){return (await this.ensureLoaded()).postChatInfo(e)}async getTimelineInfo(e){return (await this.ensureLoaded()).getTimelineInfo(e)}},h=p;
2
+ export{h as default};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"names":["CDN_LOADER_URL","loadCDNLoader","loadingPromise","resolve","reject","script","checkSDK","existingScript","TapSDK","config","__publicField","params","sdk","callback","handler","index_default"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * TapSDK - npm package wrapper\n *\n * Simply loads the CDN loader which handles version management and SDK loading.\n * This keeps the npm package minimal and allows instant updates via CDN.\n */\n\nimport type {\n TapSDKConfig,\n TapSDKInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n} from './types';\n\nconst CDN_LOADER_URL = 'https://files.edutap.ai/tap-sdk/loader.js';\n\n// Global namespace for loaded SDK\n// Export type for IIFE bundles loaded via window.TapSDK\nexport type TapSDKConstructor = new (config: TapSDKConfig) => TapSDKInstance;\n\ndeclare global {\n interface Window {\n TapSDK?: TapSDKConstructor;\n __TAP_SDK_LOADER_LOADED__?: boolean;\n __TAP_SDK_LOADER_LOADING__?: Promise<void>;\n }\n}\n\ninterface TapSDKInstance {\n events: {\n seekTimeline: (params: SeekTimelineParamsType) => void;\n onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;\n onChatInitiated: (handler: () => void) => void;\n onChatOpened: (handler: () => void) => void;\n onChatClosed: (handler: () => void) => void;\n onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => void;\n onPopUpOpen: (handler: (popUpInfo: any) => void) => void;\n onPdfOpen: (handler: () => void) => void;\n onPdfClose: (handler: () => void) => void;\n };\n isOpen: boolean;\n isInitialized: boolean;\n init(params: TapSDKInitParams): Promise<void>;\n destroy(): void;\n getVersion(): string;\n // Deprecated methods\n initChat(params: TapSDKInitParams): Promise<void>;\n postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;\n getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void>;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n */\nfunction loadCDNLoader(): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_SDK_LOADER_LOADED__ && window.TapSDK) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_SDK_LOADER_LOADING__) {\n return window.__TAP_SDK_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === 'undefined') {\n reject(new Error('TapSDK requires browser environment (document is undefined)'));\n return;\n }\n\n const script = document.createElement('script');\n script.src = CDN_LOADER_URL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = () => {\n if (window.TapSDK) {\n window.__TAP_SDK_LOADER_LOADED__ = true;\n window.__TAP_SDK_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n // Check again after a short delay\n setTimeout(checkSDK, 50);\n }\n };\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_SDK_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${CDN_LOADER_URL}\"]`);\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener('load', () => {\n const checkSDK = () => {\n if (window.TapSDK) resolve();\n else setTimeout(checkSDK, 50);\n };\n checkSDK();\n });\n existingScript.addEventListener('error', () =>\n reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`))\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_SDK_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n\n/**\n * TapSDK Wrapper Class\n *\n * Loads the CDN loader and proxies all calls to the actual SDK\n */\nclass TapSDK implements TapSDKInstance {\n private config: TapSDKConfig;\n private sdkInstance?: TapSDKInstance;\n private loadPromise: Promise<void>;\n\n constructor(config: TapSDKConfig) {\n this.config = config;\n this.loadPromise = this.loadAndInitialize();\n }\n\n private async loadAndInitialize(): Promise<void> {\n await loadCDNLoader();\n\n if (!window.TapSDK) {\n throw new Error('TapSDK not available after loading CDN loader');\n }\n\n this.sdkInstance = new window.TapSDK(this.config);\n }\n\n private async ensureLoaded(): Promise<TapSDKInstance> {\n await this.loadPromise;\n if (!this.sdkInstance) {\n throw new Error('TapSDK instance not initialized');\n }\n return this.sdkInstance;\n }\n\n // Public API - all methods proxy to the loaded SDK\n get events() {\n return {\n seekTimeline: (params: SeekTimelineParamsType) => {\n this.ensureLoaded().then(sdk => sdk.events.seekTimeline(params));\n },\n onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onTimelineSeek(callback));\n },\n onChatInitiated: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatInitiated(handler));\n },\n onChatOpened: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatOpened(handler));\n },\n onChatClosed: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onChatClosed(handler));\n },\n onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onAlarmFadeIn(handler));\n },\n onPopUpOpen: (handler: (popUpInfo: any) => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPopUpOpen(handler));\n },\n onPdfOpen: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPdfOpen(handler));\n },\n onPdfClose: (handler: () => void) => {\n this.ensureLoaded().then(sdk => sdk.events.onPdfClose(handler));\n },\n };\n }\n\n get isOpen(): boolean {\n return this.sdkInstance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.sdkInstance?.isInitialized ?? false;\n }\n\n async init(params: TapSDKInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.init(params);\n }\n\n destroy(): void {\n if (this.sdkInstance) {\n this.sdkInstance.destroy();\n }\n }\n\n getVersion(): string {\n return this.sdkInstance?.getVersion() ?? 'Not initialized';\n }\n\n // Deprecated methods\n async initChat(params: TapSDKInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.initChat(params);\n }\n\n async postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.postChatInfo(params);\n }\n\n async getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.getTimelineInfo(params);\n }\n}\n\n// Export the SDK class as default (for: import TapSDK from '@coxwave/tap-sdk')\nexport default TapSDK;\n\n// Export TapSDK instance type (for: import type { TapSDK } from '@coxwave/tap-sdk')\nexport type { TapSDKInstance as TapSDK };\n\n// Keep TapSDKInstance for backward compatibility\nexport type { TapSDKInstance };\n\n// Re-export types for API compatibility\nexport type {\n TapSDKConfig,\n TapSDKInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n};\n"]}
1
+ {"version":3,"sources":["../index.ts"],"names":["CDN_LOADER_URL","loadCDNLoader","loadingPromise","resolve","reject","script","checkSDK","existingScript","SDK_INSTANCE","SDK_INSTANCE_LOADING","_a","_b","TapKit","config","__publicField","sdk","params","callback","handler","index_default"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * TapKit wrapper - npm package wrapper\n *\n * Simply loads the CDN loader which handles version management and SDK loading.\n * This keeps the npm package minimal and allows instant updates via CDN.\n *\n * Demo version: Automatically configures localStorage for demo environment.\n */\n\n// Configure demo environment if this is the demo version\nif (typeof localStorage !== \"undefined\") {\n // Demo edutap FE URL\n localStorage.setItem(\n \"tap-url-storage\",\n JSON.stringify({\n state: { tapUrl: \"https://demo-edutap.vercel.app\" },\n })\n );\n\n // Demo API URL\n localStorage.setItem(\n \"tap-api-url-storage\",\n JSON.stringify({\n state: { apiUrl: \"https://tapadminstaging.coxwave.link\" },\n })\n );\n\n // Demo environment flag (enables console logging)\n localStorage.setItem(\"tap-environment\", \"demo\");\n\n console.log(\"[TapSDK Demo] Environment configured:\", {\n tapUrl: \"https://demo-edutap.vercel.app\",\n apiUrl: \"https://tapadminstaging.coxwave.link\",\n environment: \"demo\",\n });\n}\n\nimport type {\n TapKitConfig,\n TapKitInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n} from \"./types\";\n\nconst CDN_LOADER_URL = \"https://files.edutap.ai/tap-sdk/loader.js\";\n\n// Global namespace for loaded SDK\n// Export type for IIFE bundles loaded via window.TapKit\nexport type TapKitConstructor = new (config: TapKitConfig) => TapKitInstance;\n\ndeclare global {\n interface Window {\n TapKit?: TapKitConstructor;\n __TAP_KIT_LOADER_LOADED__?: boolean;\n __TAP_KIT_LOADER_LOADING__?: Promise<void>;\n }\n}\n\ninterface TapKitInstance {\n events: {\n seekTimeline: (params: SeekTimelineParamsType) => void;\n onTimelineSeek: (\n callback: (clipPlayHead: number, clipId: string) => void\n ) => void;\n onChatInitiated: (handler: () => void) => void;\n onChatOpened: (handler: () => void) => void;\n onChatClosed: (handler: () => void) => void;\n onAlarmFadeIn: (\n handler: (messageInfo: AlarmMessageInstanceType) => void\n ) => void;\n onPopUpOpen: (handler: (popUpInfo: any) => void) => void;\n onPdfOpen: (handler: () => void) => void;\n onPdfClose: (handler: () => void) => void;\n };\n isOpen: boolean;\n isInitialized: boolean;\n readyPromise: Promise<void>;\n init(params: TapKitInitParams): Promise<void>;\n destroy(): void;\n getVersion(): string;\n // Deprecated methods\n initChat(params: TapKitInitParams): Promise<void>;\n postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;\n getTimelineInfo(params: {\n callback: (clipPlayHead: number, clipId: string) => void;\n }): Promise<void>;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n */\nfunction loadCDNLoader(): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\"TapKit requires browser environment (document is undefined)\")\n );\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = CDN_LOADER_URL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = () => {\n if (window.TapKit) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n // Check again after a short delay\n setTimeout(checkSDK, 50);\n }\n };\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(\n `script[src=\"${CDN_LOADER_URL}\"]`\n );\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = () => {\n if (window.TapKit) resolve();\n else setTimeout(checkSDK, 50);\n };\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`))\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n\n// Use Symbol to hide SDK instance from enumeration\nconst SDK_INSTANCE = Symbol(\"sdkInstance\");\nconst SDK_INSTANCE_LOADING = Symbol(\"sdkInstanceLoading\");\n\n/**\n * TapKit Wrapper Class\n *\n * Loads the CDN loader and proxies all calls to the actual SDK\n */\nclass TapKit implements TapKitInstance {\n private [SDK_INSTANCE]?: TapKitInstance;\n private [SDK_INSTANCE_LOADING]: Promise<void>;\n\n constructor(config: TapKitConfig) {\n this[SDK_INSTANCE_LOADING] = this.loadAndInitialize(config);\n }\n\n private async loadAndInitialize(config: TapKitConfig): Promise<void> {\n console.log(\"[tap-sdk] Loading CDN loader...\");\n await loadCDNLoader();\n console.log(\"[tap-sdk] CDN loader loaded, window.TapKit:\", !!window.TapKit);\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n console.log(\"[tap-sdk] Creating TapKit instance...\");\n this[SDK_INSTANCE] = new window.TapKit(config);\n console.log(\"[tap-sdk] TapKit instance created\");\n }\n\n private async ensureLoaded(): Promise<TapKitInstance> {\n console.log(\"[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING...\");\n await this[SDK_INSTANCE_LOADING]; // Wait for SDK instance to be created\n console.log(\"[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed\");\n\n if (!this[SDK_INSTANCE]) {\n throw new Error(\"TapKit instance not initialized\");\n }\n\n console.log(\"[tap-sdk] ensureLoaded: returning SDK instance\");\n return this[SDK_INSTANCE];\n }\n\n // Expose tap-kit-core's readyPromise for advanced users\n // This resolves after init() is called and tap-kit-core is fully initialized\n get readyPromise(): Promise<void> {\n return this.ensureLoaded().then((sdk) => sdk.readyPromise);\n }\n\n // Public API - all methods proxy to the loaded SDK\n get events() {\n return {\n seekTimeline: (params: SeekTimelineParamsType) => {\n this.ensureLoaded().then((sdk) => sdk.events.seekTimeline(params));\n },\n onTimelineSeek: (\n callback: (clipPlayHead: number, clipId: string) => void\n ) => {\n this.ensureLoaded().then((sdk) => sdk.events.onTimelineSeek(callback));\n },\n onChatInitiated: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatInitiated(handler));\n },\n onChatOpened: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatOpened(handler));\n },\n onChatClosed: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onChatClosed(handler));\n },\n onAlarmFadeIn: (\n handler: (messageInfo: AlarmMessageInstanceType) => void\n ) => {\n this.ensureLoaded().then((sdk) => sdk.events.onAlarmFadeIn(handler));\n },\n onPopUpOpen: (handler: (popUpInfo: any) => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPopUpOpen(handler));\n },\n onPdfOpen: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPdfOpen(handler));\n },\n onPdfClose: (handler: () => void) => {\n this.ensureLoaded().then((sdk) => sdk.events.onPdfClose(handler));\n },\n };\n }\n\n get isOpen(): boolean {\n return this[SDK_INSTANCE]?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this[SDK_INSTANCE]?.isInitialized ?? false;\n }\n\n async init(params: TapKitInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.init(params);\n }\n\n destroy(): void {\n if (this[SDK_INSTANCE]) {\n this[SDK_INSTANCE].destroy();\n }\n }\n\n getVersion(): string {\n return this[SDK_INSTANCE]?.getVersion() ?? \"Not initialized\";\n }\n\n // Deprecated methods\n async initChat(params: TapKitInitParams): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.initChat(params);\n }\n\n async postChatInfo(params: {\n clipId: string;\n clipPlayHead: number;\n }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.postChatInfo(params);\n }\n\n async getTimelineInfo(params: {\n callback: (clipPlayHead: number, clipId: string) => void;\n }): Promise<void> {\n const sdk = await this.ensureLoaded();\n return sdk.getTimelineInfo(params);\n }\n}\n\n// Export the SDK class as default (for: import TapKit from '@coxwave/tap-sdk')\nexport default TapKit;\n\n// Export TapKit instance type (for: import type { TapKit } from '@coxwave/tap-sdk')\nexport type { TapKitInstance as TapKit };\n\n// Re-export types for API compatibility\nexport type {\n TapKitConfig,\n TapKitInitParams,\n Course,\n ContainerStyle,\n PositionType,\n SeekTimelineParamsType,\n AlarmMessageInstanceType,\n AlarmType,\n};\n"]}
package/index.ts CHANGED
@@ -1,56 +1,93 @@
1
1
  /**
2
- * TapSDK - npm package wrapper
2
+ * TapKit wrapper - npm package wrapper
3
3
  *
4
4
  * Simply loads the CDN loader which handles version management and SDK loading.
5
5
  * This keeps the npm package minimal and allows instant updates via CDN.
6
+ *
7
+ * Demo version: Automatically configures localStorage for demo environment.
6
8
  */
7
9
 
10
+ // Configure demo environment if this is the demo version
11
+ if (typeof localStorage !== "undefined") {
12
+ // Demo edutap FE URL
13
+ localStorage.setItem(
14
+ "tap-url-storage",
15
+ JSON.stringify({
16
+ state: { tapUrl: "https://demo-edutap.vercel.app" },
17
+ })
18
+ );
19
+
20
+ // Demo API URL
21
+ localStorage.setItem(
22
+ "tap-api-url-storage",
23
+ JSON.stringify({
24
+ state: { apiUrl: "https://tapadminstaging.coxwave.link" },
25
+ })
26
+ );
27
+
28
+ // Demo environment flag (enables console logging)
29
+ localStorage.setItem("tap-environment", "demo");
30
+
31
+ console.log("[TapSDK Demo] Environment configured:", {
32
+ tapUrl: "https://demo-edutap.vercel.app",
33
+ apiUrl: "https://tapadminstaging.coxwave.link",
34
+ environment: "demo",
35
+ });
36
+ }
37
+
8
38
  import type {
9
- TapSDKConfig,
10
- TapSDKInitParams,
39
+ TapKitConfig,
40
+ TapKitInitParams,
11
41
  Course,
12
42
  ContainerStyle,
13
43
  PositionType,
14
44
  SeekTimelineParamsType,
15
45
  AlarmMessageInstanceType,
16
46
  AlarmType,
17
- } from './types';
47
+ } from "./types";
18
48
 
19
- const CDN_LOADER_URL = 'https://files.edutap.ai/tap-sdk/loader.js';
49
+ const CDN_LOADER_URL = "https://files.edutap.ai/tap-sdk/loader.js";
20
50
 
21
51
  // Global namespace for loaded SDK
22
- // Export type for IIFE bundles loaded via window.TapSDK
23
- export type TapSDKConstructor = new (config: TapSDKConfig) => TapSDKInstance;
52
+ // Export type for IIFE bundles loaded via window.TapKit
53
+ export type TapKitConstructor = new (config: TapKitConfig) => TapKitInstance;
24
54
 
25
55
  declare global {
26
56
  interface Window {
27
- TapSDK?: TapSDKConstructor;
28
- __TAP_SDK_LOADER_LOADED__?: boolean;
29
- __TAP_SDK_LOADER_LOADING__?: Promise<void>;
57
+ TapKit?: TapKitConstructor;
58
+ __TAP_KIT_LOADER_LOADED__?: boolean;
59
+ __TAP_KIT_LOADER_LOADING__?: Promise<void>;
30
60
  }
31
61
  }
32
62
 
33
- interface TapSDKInstance {
63
+ interface TapKitInstance {
34
64
  events: {
35
65
  seekTimeline: (params: SeekTimelineParamsType) => void;
36
- onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => void;
66
+ onTimelineSeek: (
67
+ callback: (clipPlayHead: number, clipId: string) => void
68
+ ) => void;
37
69
  onChatInitiated: (handler: () => void) => void;
38
70
  onChatOpened: (handler: () => void) => void;
39
71
  onChatClosed: (handler: () => void) => void;
40
- onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => void;
72
+ onAlarmFadeIn: (
73
+ handler: (messageInfo: AlarmMessageInstanceType) => void
74
+ ) => void;
41
75
  onPopUpOpen: (handler: (popUpInfo: any) => void) => void;
42
76
  onPdfOpen: (handler: () => void) => void;
43
77
  onPdfClose: (handler: () => void) => void;
44
78
  };
45
79
  isOpen: boolean;
46
80
  isInitialized: boolean;
47
- init(params: TapSDKInitParams): Promise<void>;
81
+ readyPromise: Promise<void>;
82
+ init(params: TapKitInitParams): Promise<void>;
48
83
  destroy(): void;
49
84
  getVersion(): string;
50
85
  // Deprecated methods
51
- initChat(params: TapSDKInitParams): Promise<void>;
86
+ initChat(params: TapKitInitParams): Promise<void>;
52
87
  postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void>;
53
- getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void>;
88
+ getTimelineInfo(params: {
89
+ callback: (clipPlayHead: number, clipId: string) => void;
90
+ }): Promise<void>;
54
91
  }
55
92
 
56
93
  /**
@@ -59,23 +96,25 @@ interface TapSDKInstance {
59
96
  */
60
97
  function loadCDNLoader(): Promise<void> {
61
98
  // If already loaded, return immediately
62
- if (window.__TAP_SDK_LOADER_LOADED__ && window.TapSDK) {
99
+ if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {
63
100
  return Promise.resolve();
64
101
  }
65
102
 
66
103
  // If currently loading, return the existing promise
67
- if (window.__TAP_SDK_LOADER_LOADING__) {
68
- return window.__TAP_SDK_LOADER_LOADING__;
104
+ if (window.__TAP_KIT_LOADER_LOADING__) {
105
+ return window.__TAP_KIT_LOADER_LOADING__;
69
106
  }
70
107
 
71
108
  // Create loading promise
72
109
  const loadingPromise = new Promise<void>((resolve, reject) => {
73
- if (typeof document === 'undefined') {
74
- reject(new Error('TapSDK requires browser environment (document is undefined)'));
110
+ if (typeof document === "undefined") {
111
+ reject(
112
+ new Error("TapKit requires browser environment (document is undefined)")
113
+ );
75
114
  return;
76
115
  }
77
116
 
78
- const script = document.createElement('script');
117
+ const script = document.createElement("script");
79
118
  script.src = CDN_LOADER_URL;
80
119
  script.async = true;
81
120
 
@@ -83,9 +122,9 @@ function loadCDNLoader(): Promise<void> {
83
122
  // The loader script will load the actual SDK
84
123
  // We need to wait a bit for the loader to fetch and load the SDK
85
124
  const checkSDK = () => {
86
- if (window.TapSDK) {
87
- window.__TAP_SDK_LOADER_LOADED__ = true;
88
- window.__TAP_SDK_LOADER_LOADING__ = undefined;
125
+ if (window.TapKit) {
126
+ window.__TAP_KIT_LOADER_LOADED__ = true;
127
+ window.__TAP_KIT_LOADER_LOADING__ = undefined;
89
128
  resolve();
90
129
  } else {
91
130
  // Check again after a short delay
@@ -96,152 +135,177 @@ function loadCDNLoader(): Promise<void> {
96
135
  };
97
136
 
98
137
  script.onerror = () => {
99
- window.__TAP_SDK_LOADER_LOADING__ = undefined;
100
- reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`));
138
+ window.__TAP_KIT_LOADER_LOADING__ = undefined;
139
+ reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`));
101
140
  };
102
141
 
103
142
  // Check if script already exists
104
- const existingScript = document.querySelector(`script[src="${CDN_LOADER_URL}"]`);
143
+ const existingScript = document.querySelector(
144
+ `script[src="${CDN_LOADER_URL}"]`
145
+ );
105
146
  if (existingScript) {
106
147
  // Script already added but not yet loaded
107
- existingScript.addEventListener('load', () => {
148
+ existingScript.addEventListener("load", () => {
108
149
  const checkSDK = () => {
109
- if (window.TapSDK) resolve();
150
+ if (window.TapKit) resolve();
110
151
  else setTimeout(checkSDK, 50);
111
152
  };
112
153
  checkSDK();
113
154
  });
114
- existingScript.addEventListener('error', () =>
115
- reject(new Error(`Failed to load TapSDK CDN loader: ${CDN_LOADER_URL}`))
155
+ existingScript.addEventListener("error", () =>
156
+ reject(new Error(`Failed to load TapKit CDN loader: ${CDN_LOADER_URL}`))
116
157
  );
117
158
  } else {
118
159
  document.head.appendChild(script);
119
160
  }
120
161
  });
121
162
 
122
- window.__TAP_SDK_LOADER_LOADING__ = loadingPromise;
163
+ window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;
123
164
  return loadingPromise;
124
165
  }
125
166
 
167
+ // Use Symbol to hide SDK instance from enumeration
168
+ const SDK_INSTANCE = Symbol("sdkInstance");
169
+ const SDK_INSTANCE_LOADING = Symbol("sdkInstanceLoading");
170
+
126
171
  /**
127
- * TapSDK Wrapper Class
172
+ * TapKit Wrapper Class
128
173
  *
129
174
  * Loads the CDN loader and proxies all calls to the actual SDK
130
175
  */
131
- class TapSDK implements TapSDKInstance {
132
- private config: TapSDKConfig;
133
- private sdkInstance?: TapSDKInstance;
134
- private loadPromise: Promise<void>;
176
+ class TapKit implements TapKitInstance {
177
+ private [SDK_INSTANCE]?: TapKitInstance;
178
+ private [SDK_INSTANCE_LOADING]: Promise<void>;
135
179
 
136
- constructor(config: TapSDKConfig) {
137
- this.config = config;
138
- this.loadPromise = this.loadAndInitialize();
180
+ constructor(config: TapKitConfig) {
181
+ this[SDK_INSTANCE_LOADING] = this.loadAndInitialize(config);
139
182
  }
140
183
 
141
- private async loadAndInitialize(): Promise<void> {
184
+ private async loadAndInitialize(config: TapKitConfig): Promise<void> {
185
+ console.log("[tap-sdk] Loading CDN loader...");
142
186
  await loadCDNLoader();
187
+ console.log("[tap-sdk] CDN loader loaded, window.TapKit:", !!window.TapKit);
143
188
 
144
- if (!window.TapSDK) {
145
- throw new Error('TapSDK not available after loading CDN loader');
189
+ if (!window.TapKit) {
190
+ throw new Error("TapKit not available after loading CDN loader");
146
191
  }
147
192
 
148
- this.sdkInstance = new window.TapSDK(this.config);
193
+ console.log("[tap-sdk] Creating TapKit instance...");
194
+ this[SDK_INSTANCE] = new window.TapKit(config);
195
+ console.log("[tap-sdk] TapKit instance created");
149
196
  }
150
197
 
151
- private async ensureLoaded(): Promise<TapSDKInstance> {
152
- await this.loadPromise;
153
- if (!this.sdkInstance) {
154
- throw new Error('TapSDK instance not initialized');
198
+ private async ensureLoaded(): Promise<TapKitInstance> {
199
+ console.log("[tap-sdk] ensureLoaded: waiting for SDK_INSTANCE_LOADING...");
200
+ await this[SDK_INSTANCE_LOADING]; // Wait for SDK instance to be created
201
+ console.log("[tap-sdk] ensureLoaded: SDK_INSTANCE_LOADING completed");
202
+
203
+ if (!this[SDK_INSTANCE]) {
204
+ throw new Error("TapKit instance not initialized");
155
205
  }
156
- return this.sdkInstance;
206
+
207
+ console.log("[tap-sdk] ensureLoaded: returning SDK instance");
208
+ return this[SDK_INSTANCE];
209
+ }
210
+
211
+ // Expose tap-kit-core's readyPromise for advanced users
212
+ // This resolves after init() is called and tap-kit-core is fully initialized
213
+ get readyPromise(): Promise<void> {
214
+ return this.ensureLoaded().then((sdk) => sdk.readyPromise);
157
215
  }
158
216
 
159
217
  // Public API - all methods proxy to the loaded SDK
160
218
  get events() {
161
219
  return {
162
220
  seekTimeline: (params: SeekTimelineParamsType) => {
163
- this.ensureLoaded().then(sdk => sdk.events.seekTimeline(params));
221
+ this.ensureLoaded().then((sdk) => sdk.events.seekTimeline(params));
164
222
  },
165
- onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => {
166
- this.ensureLoaded().then(sdk => sdk.events.onTimelineSeek(callback));
223
+ onTimelineSeek: (
224
+ callback: (clipPlayHead: number, clipId: string) => void
225
+ ) => {
226
+ this.ensureLoaded().then((sdk) => sdk.events.onTimelineSeek(callback));
167
227
  },
168
228
  onChatInitiated: (handler: () => void) => {
169
- this.ensureLoaded().then(sdk => sdk.events.onChatInitiated(handler));
229
+ this.ensureLoaded().then((sdk) => sdk.events.onChatInitiated(handler));
170
230
  },
171
231
  onChatOpened: (handler: () => void) => {
172
- this.ensureLoaded().then(sdk => sdk.events.onChatOpened(handler));
232
+ this.ensureLoaded().then((sdk) => sdk.events.onChatOpened(handler));
173
233
  },
174
234
  onChatClosed: (handler: () => void) => {
175
- this.ensureLoaded().then(sdk => sdk.events.onChatClosed(handler));
235
+ this.ensureLoaded().then((sdk) => sdk.events.onChatClosed(handler));
176
236
  },
177
- onAlarmFadeIn: (handler: (messageInfo: AlarmMessageInstanceType) => void) => {
178
- this.ensureLoaded().then(sdk => sdk.events.onAlarmFadeIn(handler));
237
+ onAlarmFadeIn: (
238
+ handler: (messageInfo: AlarmMessageInstanceType) => void
239
+ ) => {
240
+ this.ensureLoaded().then((sdk) => sdk.events.onAlarmFadeIn(handler));
179
241
  },
180
242
  onPopUpOpen: (handler: (popUpInfo: any) => void) => {
181
- this.ensureLoaded().then(sdk => sdk.events.onPopUpOpen(handler));
243
+ this.ensureLoaded().then((sdk) => sdk.events.onPopUpOpen(handler));
182
244
  },
183
245
  onPdfOpen: (handler: () => void) => {
184
- this.ensureLoaded().then(sdk => sdk.events.onPdfOpen(handler));
246
+ this.ensureLoaded().then((sdk) => sdk.events.onPdfOpen(handler));
185
247
  },
186
248
  onPdfClose: (handler: () => void) => {
187
- this.ensureLoaded().then(sdk => sdk.events.onPdfClose(handler));
249
+ this.ensureLoaded().then((sdk) => sdk.events.onPdfClose(handler));
188
250
  },
189
251
  };
190
252
  }
191
253
 
192
254
  get isOpen(): boolean {
193
- return this.sdkInstance?.isOpen ?? false;
255
+ return this[SDK_INSTANCE]?.isOpen ?? false;
194
256
  }
195
257
 
196
258
  get isInitialized(): boolean {
197
- return this.sdkInstance?.isInitialized ?? false;
259
+ return this[SDK_INSTANCE]?.isInitialized ?? false;
198
260
  }
199
261
 
200
- async init(params: TapSDKInitParams): Promise<void> {
262
+ async init(params: TapKitInitParams): Promise<void> {
201
263
  const sdk = await this.ensureLoaded();
202
264
  return sdk.init(params);
203
265
  }
204
266
 
205
267
  destroy(): void {
206
- if (this.sdkInstance) {
207
- this.sdkInstance.destroy();
268
+ if (this[SDK_INSTANCE]) {
269
+ this[SDK_INSTANCE].destroy();
208
270
  }
209
271
  }
210
272
 
211
273
  getVersion(): string {
212
- return this.sdkInstance?.getVersion() ?? 'Not initialized';
274
+ return this[SDK_INSTANCE]?.getVersion() ?? "Not initialized";
213
275
  }
214
276
 
215
277
  // Deprecated methods
216
- async initChat(params: TapSDKInitParams): Promise<void> {
278
+ async initChat(params: TapKitInitParams): Promise<void> {
217
279
  const sdk = await this.ensureLoaded();
218
280
  return sdk.initChat(params);
219
281
  }
220
282
 
221
- async postChatInfo(params: { clipId: string; clipPlayHead: number }): Promise<void> {
283
+ async postChatInfo(params: {
284
+ clipId: string;
285
+ clipPlayHead: number;
286
+ }): Promise<void> {
222
287
  const sdk = await this.ensureLoaded();
223
288
  return sdk.postChatInfo(params);
224
289
  }
225
290
 
226
- async getTimelineInfo(params: { callback: (clipPlayHead: number, clipId: string) => void }): Promise<void> {
291
+ async getTimelineInfo(params: {
292
+ callback: (clipPlayHead: number, clipId: string) => void;
293
+ }): Promise<void> {
227
294
  const sdk = await this.ensureLoaded();
228
295
  return sdk.getTimelineInfo(params);
229
296
  }
230
297
  }
231
298
 
232
- // Export the SDK class as default (for: import TapSDK from '@coxwave/tap-sdk')
233
- export default TapSDK;
234
-
235
- // Export TapSDK instance type (for: import type { TapSDK } from '@coxwave/tap-sdk')
236
- export type { TapSDKInstance as TapSDK };
299
+ // Export the SDK class as default (for: import TapKit from '@coxwave/tap-sdk')
300
+ export default TapKit;
237
301
 
238
- // Keep TapSDKInstance for backward compatibility
239
- export type { TapSDKInstance };
302
+ // Export TapKit instance type (for: import type { TapKit } from '@coxwave/tap-sdk')
303
+ export type { TapKitInstance as TapKit };
240
304
 
241
305
  // Re-export types for API compatibility
242
306
  export type {
243
- TapSDKConfig,
244
- TapSDKInitParams,
307
+ TapKitConfig,
308
+ TapKitInitParams,
245
309
  Course,
246
310
  ContainerStyle,
247
311
  PositionType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coxwave/tap-sdk",
3
- "version": "0.2.1",
3
+ "version": "0.2.2-demo.0",
4
4
  "type": "module",
5
5
  "description": "TapSDK - Minimal wrapper that loads TapSDK from CDN",
6
6
  "main": "dist/index.js",
package/types.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
- * TapSDK Type Definitions
2
+ * TapKit Type Definitions
3
3
  *
4
4
  * Re-exported types for API compatibility with the loader.
5
- * These types match the actual SDK implementation in tap-sdk-cdn.
5
+ * These types match the actual SDK implementation in tap-kit-core.
6
6
  */
7
7
 
8
8
  // Re-export alarm types from tap-messages
@@ -12,12 +12,12 @@ export type {
12
12
  } from '@coxwave/tap-messages';
13
13
 
14
14
  // SDK Configuration
15
- export type TapSDKConfig = {
15
+ export type TapKitConfig = {
16
16
  apiKey: string;
17
17
  };
18
18
 
19
19
  // SDK Initialization Parameters
20
- export type TapSDKInitParams = {
20
+ export type TapKitInitParams = {
21
21
  buttonId: string;
22
22
  course: Course;
23
23
  container?: ContainerStyle;