@coxwave/tap-sdk 0.0.7 → 0.0.8

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,162 +1,131 @@
1
1
  # @coxwave/tap-sdk
2
2
 
3
- A vanilla JavaScript SDK for embedding AI chat widgets into web applications with seamless iframe communication.
3
+ TapSDK is a lightweight JavaScript SDK for embedding the EduTap AI tutor inside any web property. It renders the toggle button, manages the iframe chat surface, and provides a structured messaging layer for bi-directional communication with the host page.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install @coxwave/tap-sdk
9
+ # or
10
+ pnpm add @coxwave/tap-sdk
11
+ # or
12
+ yarn add @coxwave/tap-sdk
9
13
  ```
10
14
 
11
15
  ## Quick Start
12
16
 
13
- ```javascript
17
+ ```ts
14
18
  import TapSDK from "@coxwave/tap-sdk";
15
19
 
16
20
  const sdk = new TapSDK({
17
21
  apiKey: "your-plugin-key",
18
- isProd: true,
19
22
  });
20
23
 
21
- await sdk.initChat({
22
- chatApiParams: {
24
+ await sdk.init({
25
+ course: {
23
26
  userId: "user-123",
24
27
  courseId: "course-456",
25
- courseName: "JavaScript Fundamentals",
26
- courseCategory: "Programming",
27
- courseSubCategory: "Frontend",
28
28
  clipId: null,
29
- clipPlayHead: null,
29
+ // clipPlayHead can be provided if it exists in your integration contract
30
+ },
31
+ buttonId: "tap-button",
32
+ customStyles: {
33
+ chatBody: {
34
+ position: { top: "64px", right: "32px" },
35
+ width: "360px",
36
+ height: "calc(100% - 128px)",
37
+ borderRadius: "18px",
38
+ },
30
39
  },
31
40
  });
32
41
  ```
33
42
 
34
- ## Features
43
+ On initialization the SDK:
35
44
 
36
- - 🎯 **Iframe Communication** - Secure cross-origin messaging with handshake protocol
37
- - 🎨 **Customizable UI** - Floating button, chat body, and popup styling
38
- - 📊 **Event System** - Timeline sync, chat events, alarms, and PDF integration
39
- - 🔔 **Smart Notifications** - Auto-fading alarm system with custom styling
40
- - 📱 **Responsive Design** - Mobile-friendly with automatic positioning
41
- - 🚀 **Zero Dependencies** - Self-contained with tree-shaking optimization
45
+ - ensures it is running in a browser (guards against SSR)
46
+ - injects the chat container into `document.body`
47
+ - renders the EduTap iframe and performs a handshake for authentication
48
+ - attaches to the element with the provided `buttonId`
42
49
 
43
- ## API Reference
50
+ ## Customisation
44
51
 
45
- ### Constructor
52
+ ### Toggle button
46
53
 
47
- ```javascript
48
- new TapSDK(options);
49
- ```
54
+ The SDK will attach alarm badges and click handlers to the element with the provided `buttonId`.
50
55
 
51
- **Options:**
56
+ ### Chat body
52
57
 
53
- - `apiKey` (string) - Your unique plugin identifier
54
- - `isProd` (boolean) - Production mode flag (default: false)
55
- - `isLocal` (boolean) - Local development flag (default: false)
58
+ The chat surface is a fixed container (`#cw-chat-body`). You can override:
56
59
 
57
- ### Methods
60
+ - `position` — partial `{ top/right/bottom/left }` values (strings with units)
61
+ - `width` / `height` — strings with CSS units
62
+ - `borderRadius`
58
63
 
59
- #### `initChat(config)`
64
+ The container gracefully hides itself when the chat closes and expands when EduTap opens embedded PDFs.
60
65
 
61
- ```javascript
62
- await sdk.initChat({
63
- chatApiParams: {
64
- userId: string,
65
- courseId: string | null,
66
- courseName: string,
67
- courseCategory: string,
68
- courseSubCategory: string,
69
- clipId: string | null,
70
- clipPlayHead: number | null
71
- },
72
- customStyles?: {
73
- floatingButton?: {
74
- isInElement?: boolean,
75
- parentElementId?: string,
76
- style?: Partial<CSSStyleDeclaration>
77
- },
78
- chatBody?: {
79
- position?: { top?: string, right?: string, left?: string, bottom?: string },
80
- width?: string,
81
- height?: string,
82
- borderRadius?: string
83
- }
84
- }
85
- });
86
- ```
66
+ ### Alarm notifications & pop-ups
87
67
 
88
- #### `seekTimeline(params)`
68
+ EduTap can send rich alarm notifications and HTML pop-ups over the iframe channel. The SDK fades alarms in/out, handles clicks, and renders pop-ups next to the chat container while inheriting relevant sizing from `chatBody` styles.
89
69
 
90
- ```javascript
91
- sdk.seekTimeline({
92
- clipId: "clip-123",
93
- clipPlayHead: 150.5,
94
- });
95
- ```
70
+ ## Runtime API
96
71
 
97
- #### `removeChat()`
72
+ ### `init(options)`
98
73
 
99
- ```javascript
100
- sdk.removeChat();
101
- ```
74
+ Initializes the iframe, performs the handshake, and wires up UI controls. Required options:
102
75
 
103
- ### Event Listeners
76
+ - `course` – minimal course context (`userId`, `courseId`, `clipId`, optionally `clipPlayHead`)
77
+ - `customStyles?` – `{ chatBody? }`
78
+ - `buttonId` – string (required)
104
79
 
105
- ```javascript
106
- // Timeline seek events
107
- sdk.events.onTimelineSeek((clipPlayHead, clipId) => {
108
- console.log(`Seek to ${clipPlayHead}s in ${clipId}`);
109
- });
80
+ ### `events.seekTimeline({ clipId, clipPlayHead })`
110
81
 
111
- // Chat state events
112
- sdk.events.onChatOpened(() => console.log("Chat opened"));
113
- sdk.events.onChatClosed(() => console.log("Chat closed"));
82
+ For VOD integrations you can push timeline updates back to EduTap so that it can stay in sync with the host player.
114
83
 
115
- // Notification events
116
- sdk.events.onAlarmFadeIn((messageInfo) => {
117
- console.log("Alarm notification:", messageInfo);
118
- });
84
+ ```ts
85
+ sdk.events.seekTimeline({ clipId: "clip-42", clipPlayHead: 132.4 });
119
86
  ```
120
87
 
121
- ## Framework Integration
88
+ ### `destroy()`
122
89
 
123
- ### React
90
+ Unhooks all listeners, removes the iframe and toggle button decorations, and resets the internal state. Call this when unmounting a single-page application route.
124
91
 
125
- ```jsx
126
- import { useEffect, useRef } from "react";
127
- import TapSDK from "@coxwave/tap-sdk";
92
+ ## Event system
128
93
 
129
- function ChatWidget({ userId, courseId }) {
130
- const sdkRef = useRef(null);
94
+ Events are exposed via the `sdk.events` helper. Every listener returns an unsubscribe function.
131
95
 
132
- useEffect(() => {
133
- const initSDK = async () => {
134
- sdkRef.current = new TapSDK({
135
- apiKey: process.env.REACT_APP_TAP_PLUGIN_KEY,
136
- isProd: process.env.NODE_ENV === "production",
137
- });
96
+ ```ts
97
+ sdk.events.onChatOpened(() => console.log("chat opened"));
98
+ sdk.events.onChatClosed(() => console.log("chat closed"));
99
+ sdk.events.onTimelineSeek((playHead, clipId) => {
100
+ console.log("EduTap requested timeline seek", playHead, clipId);
101
+ });
138
102
 
139
- await sdkRef.current.initChat({
140
- chatApiParams: { userId, courseId /* ... */ },
141
- });
142
- };
103
+ sdk.events.onAlarmFadeIn((alarm) => {
104
+ console.log("Alarm", alarm.message);
105
+ });
143
106
 
144
- initSDK();
145
- return () => sdkRef.current?.removeChat();
146
- }, [userId, courseId]);
107
+ sdk.events.onPopUpOpen((popUp) => {
108
+ // popUp.html contains the rendered snippet
109
+ });
147
110
 
148
- return <div id="chat-container" />;
149
- }
111
+ sdk.events.onPdfOpen(() => console.log("PDF overlay opened"));
112
+ sdk.events.onPdfClose(() => console.log("PDF overlay closed"));
150
113
  ```
151
114
 
152
- ## Build Formats
115
+ ## TypeScript support
116
+
117
+ Type definitions ship with the package. Notable exports:
153
118
 
154
- - **ESM**: `dist/index.mjs` - Modern ES modules
155
- - **CJS**: `dist/index.js` - CommonJS for Node.js
156
- - **IIFE**: `dist/index.global.js` - Browser global variable
157
- - **Types**: `dist/index.d.ts` - TypeScript declarations
119
+ - `TapSDKConfig`
120
+ - `Course`
121
+ - `CustomStyles`
122
+ - `ChatBodyStyle`
123
+ - `SeekTimelineParamsType`
124
+ - `AlarmMessageInstanceType`
158
125
 
159
- ## Browser Support
126
+ All message contracts are sourced from `@coxwave/tap-messages` and validated with `valibot` during the iframe handshake.
127
+
128
+ ## Browser support
160
129
 
161
130
  - Chrome 60+
162
131
  - Firefox 60+
@@ -165,6 +134,9 @@ function ChatWidget({ userId, courseId }) {
165
134
 
166
135
  ## License
167
136
 
168
- MIT
137
+ MIT © 2025 Coxwave
138
+
139
+ ## Deprecated helpers
169
140
 
170
- Copyright (c) 2025-present, Coxwave
141
+ - `postChatInfo({ clipId, clipPlayHead })` – alias for `events.seekTimeline`; scheduled for removal in v1.0.0
142
+ - `getTimelineInfo({ callback })` – use `sdk.events.onTimelineSeek` instead
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- @keyframes _1mlv4me0{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}@keyframes _1mlv4me1{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(30px);display:none}}._1mlv4me2{opacity:0;transform:translateY(30px);transition:opacity .4s ease,transform .4s ease;pointer-events:none;display:none}._1mlv4me3{animation:_1mlv4me0 .4s ease forwards;pointer-events:auto}._1mlv4me4{animation:_1mlv4me1 .4s ease forwards;pointer-events:none}._1mlv4me5{border:none!important}@keyframes _6j1ub50{0%{opacity:1;pointer-events:auto}50%{opacity:1}to{opacity:0}}._6j1ub51{pointer-events:none;opacity:0;display:flex;position:absolute;width:max-content;top:calc(100% + 5px);right:0;flex-direction:column;justify-content:center;align-items:flex-end;padding-top:2px;cursor:pointer;z-index:999;transition:opacity .3s ease}._6j1ub52{pointer-events:auto;animation:_6j1ub50 18s forwards}._6j1ub53{opacity:0;pointer-events:none;animation:none}._6j1ub54{display:flex;justify-content:flex-end;border-radius:var(--Radius-radiusSM, 8px);width:max-content;gap:5px}._6j1ub55{display:flex;padding:8px 12px 6px;justify-content:flex-end;align-items:center;border-radius:var(--Radius-radiusSM, 8px);max-width:340px}._6j1ub56{background-color:#171b1f}._6j1ub57{background-color:#fa6b4b}._6j1ub58{color:#fff;text-align:right;font-family:Pretendard;font-size:14px;font-style:normal;font-weight:400;line-height:20px;white-space:pre-wrap;word-break:keep-all;overflow-wrap:break-word}._6j1ub59{display:flex;padding:0 23px;align-items:flex-start;gap:10px}._6j1ub5a{width:15px}._6j1ub5b{color:#171b1f}._6j1ub5c{color:#fa6b4b}._6j1ub5d{cursor:pointer;justify-content:center;align-items:center;width:20px;height:20px;border-radius:100px;z-index:999;transition:all .2s ease}._6j1ub5d:hover{width:63px;left:-72px}._6j1ub54:hover ._6j1ub5d{display:flex}._6j1ub5e,._6j1ub5f{display:none;background-color:#171b1f}._6j1ub5g{color:#fff}._6j1ub5d:hover ._6j1ub5g{display:none}._6j1ub5h{color:#fff;text-align:center;font-family:Pretendard;font-size:12px;font-style:normal;font-weight:400;line-height:20px;display:none}._6j1ub5d:hover ._6j1ub5h{display:block}.wu2gm60{width:100%;min-width:max-content;table-layout:auto;border-collapse:separate;border-spacing:0;border:.4px solid rgba(118,118,128,.12);border-radius:8px;overflow:auto;background-color:#fff;cursor:pointer}.wu2gm61{border:.4px solid rgba(118,118,128,.12);padding:10px;background-color:#f2f2f2;text-align:left;font-family:Pretendard;color:#090909;font-size:12px;font-weight:500;white-space:normal;overflow-wrap:break-word;word-break:break-word}.wu2gm62{border:.4px solid rgba(118,118,128,.12);padding:10px;color:#090909;font-family:Pretendard;font-size:12px;font-weight:400;width:fit-content;max-width:400px;white-space:normal;overflow-wrap:break-word;word-break:break-word}.wu2gm63{position:relative;background-color:#fafafa;border-radius:8px;padding:8px;overflow-y:auto}.wu2gm64{display:flex;align-items:center;justify-content:space-between;padding-bottom:4px}.wu2gm65{color:#4a5568;padding:2px 6px;font-size:12px;border-radius:4px;z-index:10;font-family:Pretendard}.wu2gm66{z-index:10;cursor:pointer;display:flex;align-items:center;width:max-content;color:#4a5568;padding:2px 6px;font-size:12px;border:none;font-family:Pretendard}.wu2gm67{white-space:nowrap}.wu2gm68{display:flex;width:12px;height:12px;margin-bottom:4px;color:#4a5568;flex-shrink:0}
1
+ @keyframes _1mlv4me0{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}@keyframes _1mlv4me1{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(30px);display:none}}._1mlv4me2{opacity:0;transform:translateY(30px);transition:opacity .4s ease,transform .4s ease;pointer-events:none;display:none}._1mlv4me3{animation:_1mlv4me0 .4s ease forwards;pointer-events:auto}._1mlv4me4{animation:_1mlv4me1 .4s ease forwards;pointer-events:none}._1mlv4me5{border:none!important}@keyframes wtjce00{0%{opacity:1;pointer-events:auto}50%{opacity:1}to{opacity:0}}.wtjce01{pointer-events:none;opacity:0;display:flex;position:absolute;width:max-content;top:calc(100% + 5px);right:0;flex-direction:column;justify-content:center;align-items:flex-end;padding-top:2px;cursor:pointer;z-index:999;transition:opacity .3s ease}.wtjce02{pointer-events:auto;animation:wtjce00 18s forwards}.wtjce03{opacity:0;pointer-events:none;animation:none}.wtjce04{display:flex;justify-content:flex-end;border-radius:var(--Radius-radiusSM, 8px);width:max-content;gap:5px}.wtjce05{display:flex;padding:8px 12px 6px;justify-content:flex-end;align-items:center;border-radius:var(--Radius-radiusSM, 8px);max-width:340px}.wtjce06{background-color:#171b1f}.wtjce07{background-color:#fa6b4b}.wtjce08{color:#fff;text-align:right;font-family:Pretendard;font-size:14px;font-style:normal;font-weight:400;line-height:20px;white-space:pre-wrap;word-break:keep-all;overflow-wrap:break-word}.wtjce09{display:flex;padding:0 23px;align-items:flex-start;gap:10px}.wtjce0a{width:15px}.wtjce0b{color:#171b1f}.wtjce0c{color:#fa6b4b}.wtjce0d{cursor:pointer;justify-content:center;align-items:center;width:20px;height:20px;border-radius:100px;z-index:999;transition:all .2s ease}.wtjce0d:hover{width:63px;left:-72px}.wtjce04:hover .wtjce0d{display:flex}.wtjce0e,.wtjce0f{display:none;background-color:#171b1f}.wtjce0g{color:#fff}.wtjce0d:hover .wtjce0g{display:none}.wtjce0h{color:#fff;text-align:center;font-family:Pretendard;font-size:12px;font-style:normal;font-weight:400;line-height:20px;display:none}.wtjce0d:hover .wtjce0h{display:block}.wu2gm60{width:100%;min-width:max-content;table-layout:auto;border-collapse:separate;border-spacing:0;border:.4px solid rgba(118,118,128,.12);border-radius:8px;overflow:auto;background-color:#fff;cursor:pointer}.wu2gm61{border:.4px solid rgba(118,118,128,.12);padding:10px;background-color:#f2f2f2;text-align:left;font-family:Pretendard;color:#090909;font-size:12px;font-weight:500;white-space:normal;overflow-wrap:break-word;word-break:break-word}.wu2gm62{border:.4px solid rgba(118,118,128,.12);padding:10px;color:#090909;font-family:Pretendard;font-size:12px;font-weight:400;width:fit-content;max-width:400px;white-space:normal;overflow-wrap:break-word;word-break:break-word}.wu2gm63{position:relative;background-color:#fafafa;border-radius:8px;padding:8px;overflow-y:auto}.wu2gm64{display:flex;align-items:center;justify-content:space-between;padding-bottom:4px}.wu2gm65{color:#4a5568;padding:2px 6px;font-size:12px;border-radius:4px;z-index:10;font-family:Pretendard}.wu2gm66{z-index:10;cursor:pointer;display:flex;align-items:center;width:max-content;color:#4a5568;padding:2px 6px;font-size:12px;border:none;font-family:Pretendard}.wu2gm67{white-space:nowrap}.wu2gm68{display:flex;width:12px;height:12px;margin-bottom:4px;color:#4a5568;flex-shrink:0}
2
2
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["vanilla-extract-css-ns:chatBody/chatBody.css.ts.vanilla.css?source=QGtleWZyYW1lcyBfMW1sdjRtZTAgewogIGZyb20gewogICAgb3BhY2l0eTogMDsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgzMHB4KTsKICB9CiAgdG8gewogICAgb3BhY2l0eTogMTsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwKTsKICB9Cn0KQGtleWZyYW1lcyBfMW1sdjRtZTEgewogIGZyb20gewogICAgb3BhY2l0eTogMTsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwKTsKICB9CiAgdG8gewogICAgb3BhY2l0eTogMDsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgzMHB4KTsKICAgIGRpc3BsYXk6IG5vbmU7CiAgfQp9Ci5fMW1sdjRtZTIgewogIG9wYWNpdHk6IDA7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDMwcHgpOwogIHRyYW5zaXRpb246IG9wYWNpdHkgMC40cyBlYXNlLCB0cmFuc2Zvcm0gMC40cyBlYXNlOwogIHBvaW50ZXItZXZlbnRzOiBub25lOwogIGRpc3BsYXk6IG5vbmU7Cn0KLl8xbWx2NG1lMyB7CiAgYW5pbWF0aW9uOiBfMW1sdjRtZTAgMC40cyBlYXNlIGZvcndhcmRzOwogIHBvaW50ZXItZXZlbnRzOiBhdXRvOwp9Ci5fMW1sdjRtZTQgewogIGFuaW1hdGlvbjogXzFtbHY0bWUxIDAuNHMgZWFzZSBmb3J3YXJkczsKICBwb2ludGVyLWV2ZW50czogbm9uZTsKfQouXzFtbHY0bWU1IHsKICBib3JkZXI6IG5vbmUgIWltcG9ydGFudDsKfQ==","vanilla-extract-css-ns:floatingButton/alarm/styles/alarm.css.ts.vanilla.css?source=#H4sIAAAAAAAAE61Uy27bMBC8+ysWKAqkaBlI8iMxfWlzyK1A0X5AQYsrizFNCiQVyyny7wUpOtbDblK0J1s7u8vZmSU/b/FQGLZDCz8XD2m9nifwawKQvA8/ALpiuXAHCukqfFdaKIeG4CMqZymw2mmPPE8A5heqPJYmYzBpwefJdTw7DRnDI5RW6DP7dVzYSrIDhUJiswplVjihFQW2tlrWLhTtBXclhR1rSK6VQ+V81OmKQs5kfhV4fYR51XzwgBGb0sUTfGPChcG8bZtrWe+URx5q60RxOHakkKNn7CEmxUYR4XBnW2oEFQ/0GOdCbUg4OqsC5bw2Vht6nNiHnohQHBsKy+UyMDVMHeeKAkByPbWAzOKqo112VrujPUyJHWu7vPic3lootNkzw2230zR06qt9yZNO3zZ0ajMLbUY2jbTrirTWhqMhhnFRWwqPzFwR8j18xeCPr5/gNpp13tsNq6j3s8tlfp5L9IT6jpBmVQOL+OdVpj2fT/b/3QCeeRxiOkv6lBeB8prl243RteIk19Lvyrv0Jr1L77upN5dS778s7mZ33dTbkHrEi6IIO4aNI2Eg2l6AsP1aOVKwnZAHCt8MOlScGf4CWfGEFNJZq1UbcgeJfhHMjsmX6B7bOzVLwiZJoZCUMZYlbfm+FA6JrViOFCqDZG9YFQBtOFkbZFsKW8SKMBk660c0hdT7kEghZBCf3B12+YrrSdVANm0ZjO+tdcycFiod2MNC72heOli3dU/lsWF5Dx+7xFt8/Dq89eE5hSPDo9BD4Qf7miYx/qdniEkJyXU2foI4Lb0vXWUWUV6JhaNAbrK+ULNY0R984NgpHfvw8RF60yUp/qF20/Ur7Oq5sfvZg5NO6eVrV/Bk3hvvYPZf7uBFwsP5yv58a6nz7Wry/Bv1tBtfSwgAAA==","vanilla-extract-css-ns:popUpImage/popUpImage.css.ts.vanilla.css?source=#H4sIAAAAAAAAE7VU7Y7bIBD8n6dYqap0lUKEXSd1uZfoK2B77dBgQIDPzlX37hX4o07qXq9qK0tY7AIzOztw6Lu0aU8Uvu0AelH5M4OE0vePO4BWKDKFWj6QUiuPyoeM54VEIvlVd54B77wO0ULbCi0ptZTcOGTg0HDLPa6SzvBSqIYB/RFkQA+ZGcBpKSqwTcEfkiTfwzik+R7oIUk/rE6xvBKdY5CbIUT1E9pa6n5FhZeXxupOVYGOtgze1XUdMmVnXZgbLZRH+7h72R1GDZKowR9TMryqYkUJHdlsYafhi8rh4AmXolEMJNZRzVorT2reCnll8MWiR1VxW0W20wH0c/iWxU48I4MkHQFjqEfRnD2DI43K9mfhMaqNDJS2LZdrpUhvuWFQWOQX0usRLPxJDN1mFoXSf6TQL6raluB3BWdTwaNRa+HXRg2+nTIZndD/izQfozRGO+GFVgwsSu7FE24bwjbFQ3qke5iHV8y9qHdndnKd7b6QyCKJSjgj+ZVBLTHuiHYjwmPrGJQ42h7ga+e8qK+zXAyiJKRA3yOqFTQptPe6ZZAFBgvaMaLNvcz48XjKbwinZoDTqmO3TbyrNhujz0SoCofglVd9sbA4RRZ323665G9XZfvB+8sqg88Uvq2gT+NTfGvS4MnVmny70fP7PWGfpxsyz1tuG6Fuu7lVWjiOuLMV6hLf6ZfvG7kHlyUGAAA="],"sourcesContent":["@keyframes _1mlv4me0 {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@keyframes _1mlv4me1 {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(30px);\n display: none;\n }\n}\n._1mlv4me2 {\n opacity: 0;\n transform: translateY(30px);\n transition: opacity 0.4s ease, transform 0.4s ease;\n pointer-events: none;\n display: none;\n}\n._1mlv4me3 {\n animation: _1mlv4me0 0.4s ease forwards;\n pointer-events: auto;\n}\n._1mlv4me4 {\n animation: _1mlv4me1 0.4s ease forwards;\n pointer-events: none;\n}\n._1mlv4me5 {\n border: none !important;\n}","@keyframes _6j1ub50 {\n 0% {\n opacity: 1;\n pointer-events: auto;\n }\n 50% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n }\n}\n._6j1ub51 {\n pointer-events: none;\n opacity: 0;\n display: flex;\n position: absolute;\n width: max-content;\n top: calc(100% + 5px);\n right: 0;\n flex-direction: column;\n justify-content: center;\n align-items: flex-end;\n padding-top: 2px;\n cursor: pointer;\n z-index: 999;\n transition: opacity 0.3s ease;\n}\n._6j1ub52 {\n pointer-events: auto;\n animation: _6j1ub50 18s forwards;\n}\n._6j1ub53 {\n opacity: 0;\n pointer-events: none;\n animation: none;\n}\n._6j1ub54 {\n display: flex;\n justify-content: flex-end;\n border-radius: var(--Radius-radiusSM, 8px);\n width: max-content;\n gap: 5px;\n}\n._6j1ub55 {\n display: flex;\n padding: 8px 12px 6px 12px;\n justify-content: flex-end;\n align-items: center;\n border-radius: var(--Radius-radiusSM, 8px);\n max-width: 340px;\n}\n._6j1ub56 {\n background-color: #171B1F;\n}\n._6j1ub57 {\n background-color: #FA6B4B;\n}\n._6j1ub58 {\n color: #fff;\n text-align: right;\n font-family: Pretendard;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px;\n white-space: pre-wrap;\n word-break: keep-all;\n overflow-wrap: break-word;\n}\n._6j1ub59 {\n display: flex;\n padding: 0px 23px;\n align-items: flex-start;\n gap: 10px;\n}\n._6j1ub5a {\n width: 15px;\n}\n._6j1ub5b {\n color: #171B1F;\n}\n._6j1ub5c {\n color: #FA6B4B;\n}\n._6j1ub5d {\n cursor: pointer;\n justify-content: center;\n align-items: center;\n width: 20px;\n height: 20px;\n border-radius: 100px;\n z-index: 999;\n transition: all 0.2s ease;\n}\n._6j1ub5d:hover {\n width: 63px;\n left: -72px;\n}\n._6j1ub54:hover ._6j1ub5d {\n display: flex;\n}\n._6j1ub5e {\n display: none;\n background-color: #171B1F;\n}\n._6j1ub5f {\n display: none;\n background-color: #171B1F;\n}\n._6j1ub5g {\n color: white;\n}\n._6j1ub5d:hover ._6j1ub5g {\n display: none;\n}\n._6j1ub5h {\n color: #fff;\n text-align: center;\n font-family: Pretendard;\n font-size: 12px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px;\n display: none;\n}\n._6j1ub5d:hover ._6j1ub5h {\n display: block;\n}",".wu2gm60 {\n width: 100%;\n min-width: max-content;\n table-layout: auto;\n border-collapse: separate;\n border-spacing: 0;\n border: 0.4px solid rgba(118, 118, 128, 0.12);\n border-radius: 8px;\n overflow: auto;\n background-color: #fff;\n cursor: pointer;\n}\n.wu2gm61 {\n border: 0.4px solid rgba(118, 118, 128, 0.12);\n padding: 10px;\n background-color: #f2f2f2;\n text-align: left;\n font-family: Pretendard;\n color: #090909;\n font-size: 12px;\n font-weight: 500;\n white-space: normal;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n.wu2gm62 {\n border: 0.4px solid rgba(118, 118, 128, 0.12);\n padding: 10px;\n color: #090909;\n font-family: Pretendard;\n font-size: 12px;\n font-weight: 400;\n width: fit-content;\n max-width: 400px;\n white-space: normal;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n.wu2gm63 {\n position: relative;\n background-color: rgb(250, 250, 250);\n border-radius: 8px;\n padding: 8px;\n overflow-y: auto;\n}\n.wu2gm64 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding-bottom: 4px;\n}\n.wu2gm65 {\n color: #4a5568;\n padding: 2px 6px;\n font-size: 12px;\n border-radius: 4px;\n z-index: 10;\n font-family: Pretendard;\n}\n.wu2gm66 {\n z-index: 10;\n cursor: pointer;\n display: flex;\n align-items: center;\n width: max-content;\n color: #4a5568;\n padding: 2px 6px;\n font-size: 12px;\n border: none;\n font-family: Pretendard;\n}\n.wu2gm67 {\n white-space: nowrap;\n}\n.wu2gm68 {\n display: flex;\n width: 12px;\n height: 12px;\n margin-bottom: 4px;\n color: #4a5568;\n flex-shrink: 0;\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["vanilla-extract-css-ns:chatBody/chatBody.css.ts.vanilla.css?source=QGtleWZyYW1lcyBfMW1sdjRtZTAgewogIGZyb20gewogICAgb3BhY2l0eTogMDsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgzMHB4KTsKICB9CiAgdG8gewogICAgb3BhY2l0eTogMTsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwKTsKICB9Cn0KQGtleWZyYW1lcyBfMW1sdjRtZTEgewogIGZyb20gewogICAgb3BhY2l0eTogMTsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwKTsKICB9CiAgdG8gewogICAgb3BhY2l0eTogMDsKICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgzMHB4KTsKICAgIGRpc3BsYXk6IG5vbmU7CiAgfQp9Ci5fMW1sdjRtZTIgewogIG9wYWNpdHk6IDA7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDMwcHgpOwogIHRyYW5zaXRpb246IG9wYWNpdHkgMC40cyBlYXNlLCB0cmFuc2Zvcm0gMC40cyBlYXNlOwogIHBvaW50ZXItZXZlbnRzOiBub25lOwogIGRpc3BsYXk6IG5vbmU7Cn0KLl8xbWx2NG1lMyB7CiAgYW5pbWF0aW9uOiBfMW1sdjRtZTAgMC40cyBlYXNlIGZvcndhcmRzOwogIHBvaW50ZXItZXZlbnRzOiBhdXRvOwp9Ci5fMW1sdjRtZTQgewogIGFuaW1hdGlvbjogXzFtbHY0bWUxIDAuNHMgZWFzZSBmb3J3YXJkczsKICBwb2ludGVyLWV2ZW50czogbm9uZTsKfQouXzFtbHY0bWU1IHsKICBib3JkZXI6IG5vbmUgIWltcG9ydGFudDsKfQ==","vanilla-extract-css-ns:ui/button/alarm/styles/alarm.css.ts.vanilla.css?source=#H4sIAAAAAAAAE61UwW7bMAy95ysIDAM6rCpsJ00b5bL10NuAYfsCxaJjNbJkSHLtdOi/D5LtxI6TtRt2SsxHUo/vUfqyw31mWIEWaveUYhTBrxlA9DH8AOiSpcLtKcTr8F1qoRwags+onKXAKqc98joDuL1Q5bE4moJRC77Obtqj45BweoLSCn3iuIwLW0q2p5BJbNahzAontKLANlbLyoWiWnCXUyhYQ1KtHCrno06XFFIm06tA6zPcls0nDxixzV13gm9MuDCYtm1TLatCeeSpsk5k+74jhRQ9Yw8xKbaKCIeFbakRVDzQY5wLtSXh6KQMlNPKWG1oP7EPvRChODYUVqtVYGqY6ufqBIDoZm4BmcX1UbrkrHS9OUyJgrVNepPjewuZNjUz3A76zEOfsdSXDBl0bUOHLovQZWLRRLehQBttOBpiGBeVpfDMzBUhP8JXF/z57RruO6PO+7plJfVeDqjcnqfS2UF9Q4iTsoFl9+dNoiOLj87/HX9PvJthvohGjJeB8Yalu63RleIk1dJvyYf4Ln6IHweZd5cyH78uHxYPg8z7kNnDWZaF3cLGkTANbRc/bL1WjmSsEHJP4btBh4ozww+QFS9IIV60QrUht5fod8AUTB6iNbZ3aRGFJZJCIcm7WBK15XUuHBJbshQplAZJbVgZAG042RhkOwo7xJIwGTrrZzSZ1HVIpBAyiE8ezLp6w/GobCCZtwSm19U6Zo67FI+tYaF151s8XrTNSOKJV+kInhjEW3j6ILz3rTmGO3q9xqean+xpHHXxP708TEqIbpLJq8Np7h0ZqrLslJWYOQrkLhmJtOgKRlOfWHVIxjHaPzvvuRnZv5duh0aFBT0z8Cj35JhDcv7WpTt69s5bl/yXW3eJ78lw+Xi4jdTpbj17/Q1FleMxMQgAAA==","vanilla-extract-css-ns:popUpImage/popUpImage.css.ts.vanilla.css?source=#H4sIAAAAAAAAE7VU7Y7bIBD8n6dYqap0lUKEXSd1uZfoK2B77dBgQIDPzlX37hX4o07qXq9qK0tY7AIzOztw6Lu0aU8Uvu0AelH5M4OE0vePO4BWKDKFWj6QUiuPyoeM54VEIvlVd54B77wO0ULbCi0ptZTcOGTg0HDLPa6SzvBSqIYB/RFkQA+ZGcBpKSqwTcEfkiTfwzik+R7oIUk/rE6xvBKdY5CbIUT1E9pa6n5FhZeXxupOVYGOtgze1XUdMmVnXZgbLZRH+7h72R1GDZKowR9TMryqYkUJHdlsYafhi8rh4AmXolEMJNZRzVorT2reCnll8MWiR1VxW0W20wH0c/iWxU48I4MkHQFjqEfRnD2DI43K9mfhMaqNDJS2LZdrpUhvuWFQWOQX0usRLPxJDN1mFoXSf6TQL6raluB3BWdTwaNRa+HXRg2+nTIZndD/izQfozRGO+GFVgwsSu7FE24bwjbFQ3qke5iHV8y9qHdndnKd7b6QyCKJSjgj+ZVBLTHuiHYjwmPrGJQ42h7ga+e8qK+zXAyiJKRA3yOqFTQptPe6ZZAFBgvaMaLNvcz48XjKbwinZoDTqmO3TbyrNhujz0SoCofglVd9sbA4RRZ323665G9XZfvB+8sqg88Uvq2gT+NTfGvS4MnVmny70fP7PWGfpxsyz1tuG6Fuu7lVWjiOuLMV6hLf6ZfvG7kHlyUGAAA="],"sourcesContent":["@keyframes _1mlv4me0 {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@keyframes _1mlv4me1 {\n from {\n opacity: 1;\n transform: translateY(0);\n }\n to {\n opacity: 0;\n transform: translateY(30px);\n display: none;\n }\n}\n._1mlv4me2 {\n opacity: 0;\n transform: translateY(30px);\n transition: opacity 0.4s ease, transform 0.4s ease;\n pointer-events: none;\n display: none;\n}\n._1mlv4me3 {\n animation: _1mlv4me0 0.4s ease forwards;\n pointer-events: auto;\n}\n._1mlv4me4 {\n animation: _1mlv4me1 0.4s ease forwards;\n pointer-events: none;\n}\n._1mlv4me5 {\n border: none !important;\n}","@keyframes wtjce00 {\n 0% {\n opacity: 1;\n pointer-events: auto;\n }\n 50% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n }\n}\n.wtjce01 {\n pointer-events: none;\n opacity: 0;\n display: flex;\n position: absolute;\n width: max-content;\n top: calc(100% + 5px);\n right: 0;\n flex-direction: column;\n justify-content: center;\n align-items: flex-end;\n padding-top: 2px;\n cursor: pointer;\n z-index: 999;\n transition: opacity 0.3s ease;\n}\n.wtjce02 {\n pointer-events: auto;\n animation: wtjce00 18s forwards;\n}\n.wtjce03 {\n opacity: 0;\n pointer-events: none;\n animation: none;\n}\n.wtjce04 {\n display: flex;\n justify-content: flex-end;\n border-radius: var(--Radius-radiusSM, 8px);\n width: max-content;\n gap: 5px;\n}\n.wtjce05 {\n display: flex;\n padding: 8px 12px 6px 12px;\n justify-content: flex-end;\n align-items: center;\n border-radius: var(--Radius-radiusSM, 8px);\n max-width: 340px;\n}\n.wtjce06 {\n background-color: #171B1F;\n}\n.wtjce07 {\n background-color: #FA6B4B;\n}\n.wtjce08 {\n color: #fff;\n text-align: right;\n font-family: Pretendard;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px;\n white-space: pre-wrap;\n word-break: keep-all;\n overflow-wrap: break-word;\n}\n.wtjce09 {\n display: flex;\n padding: 0px 23px;\n align-items: flex-start;\n gap: 10px;\n}\n.wtjce0a {\n width: 15px;\n}\n.wtjce0b {\n color: #171B1F;\n}\n.wtjce0c {\n color: #FA6B4B;\n}\n.wtjce0d {\n cursor: pointer;\n justify-content: center;\n align-items: center;\n width: 20px;\n height: 20px;\n border-radius: 100px;\n z-index: 999;\n transition: all 0.2s ease;\n}\n.wtjce0d:hover {\n width: 63px;\n left: -72px;\n}\n.wtjce04:hover .wtjce0d {\n display: flex;\n}\n.wtjce0e {\n display: none;\n background-color: #171B1F;\n}\n.wtjce0f {\n display: none;\n background-color: #171B1F;\n}\n.wtjce0g {\n color: white;\n}\n.wtjce0d:hover .wtjce0g {\n display: none;\n}\n.wtjce0h {\n color: #fff;\n text-align: center;\n font-family: Pretendard;\n font-size: 12px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px;\n display: none;\n}\n.wtjce0d:hover .wtjce0h {\n display: block;\n}",".wu2gm60 {\n width: 100%;\n min-width: max-content;\n table-layout: auto;\n border-collapse: separate;\n border-spacing: 0;\n border: 0.4px solid rgba(118, 118, 128, 0.12);\n border-radius: 8px;\n overflow: auto;\n background-color: #fff;\n cursor: pointer;\n}\n.wu2gm61 {\n border: 0.4px solid rgba(118, 118, 128, 0.12);\n padding: 10px;\n background-color: #f2f2f2;\n text-align: left;\n font-family: Pretendard;\n color: #090909;\n font-size: 12px;\n font-weight: 500;\n white-space: normal;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n.wu2gm62 {\n border: 0.4px solid rgba(118, 118, 128, 0.12);\n padding: 10px;\n color: #090909;\n font-family: Pretendard;\n font-size: 12px;\n font-weight: 400;\n width: fit-content;\n max-width: 400px;\n white-space: normal;\n overflow-wrap: break-word;\n word-break: break-word;\n}\n.wu2gm63 {\n position: relative;\n background-color: rgb(250, 250, 250);\n border-radius: 8px;\n padding: 8px;\n overflow-y: auto;\n}\n.wu2gm64 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding-bottom: 4px;\n}\n.wu2gm65 {\n color: #4a5568;\n padding: 2px 6px;\n font-size: 12px;\n border-radius: 4px;\n z-index: 10;\n font-family: Pretendard;\n}\n.wu2gm66 {\n z-index: 10;\n cursor: pointer;\n display: flex;\n align-items: center;\n width: max-content;\n color: #4a5568;\n padding: 2px 6px;\n font-size: 12px;\n border: none;\n font-family: Pretendard;\n}\n.wu2gm67 {\n white-space: nowrap;\n}\n.wu2gm68 {\n display: flex;\n width: 12px;\n height: 12px;\n margin-bottom: 4px;\n color: #4a5568;\n flex-shrink: 0;\n}"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -33,22 +33,20 @@ interface ChatInitConfig {
33
33
  apiUrl?: string | undefined;
34
34
  }
35
35
  declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
36
- protected hostClientUrl: string;
36
+ #private;
37
+ protected hostOrigin: string;
37
38
  protected apiKey: string;
38
39
  protected iframe: HTMLIFrameElement | null;
39
- constructor({ hostClientUrl, apiKey, }: {
40
- hostClientUrl: string;
40
+ constructor({ hostOrigin, apiKey }: {
41
+ hostOrigin: string;
41
42
  apiKey: string;
42
43
  });
43
44
  protected isValidOrigin(_event: MessageEvent): boolean;
44
45
  protected getMessageTarget(): Window | null;
45
46
  protected getTargetOrigin(): string;
46
- renderIframe({ chatBody, isProd, isLocal, }: {
47
- chatBody: HTMLElement;
48
- isProd: boolean;
49
- isLocal?: boolean;
50
- }): Promise<HTMLIFrameElement>;
47
+ renderIframe(iframeRootElement?: HTMLElement): Promise<HTMLIFrameElement>;
51
48
  hasIframe(): boolean;
49
+ ensureIframe(rootElement?: HTMLElement): Promise<HTMLIFrameElement>;
52
50
  removeIframe(): void;
53
51
  postToTap: (message: ToTapMessage) => boolean;
54
52
  listenToTap: <T extends "timeline:seek" | "chat:opened" | "chat:initiated" | "chat:closed" | "alarm:fadeIn" | "popUp:open" | "pdf:open" | "pdf:close">(messageType: T, callback: (data: Extract<TimelineSeekMessage, {
@@ -69,12 +67,11 @@ declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
69
67
  type: T;
70
68
  }>) => void) => () => void;
71
69
  performHandshake(config: ChatInitConfig, options?: HandshakeOptions): Promise<ChatInitiatedMessage>;
70
+ static defaultHandshakeOptions: HandshakeOptions;
72
71
  }
73
72
 
74
73
  type TapSDKConfig = {
75
74
  apiKey: string;
76
- isProd?: boolean;
77
- isLocal?: boolean;
78
75
  };
79
76
  type Course = {
80
77
  userId: string;
@@ -82,14 +79,8 @@ type Course = {
82
79
  clipId: string | null;
83
80
  };
84
81
  type CustomStyles = {
85
- floatingButton?: FloatingButtonType;
86
82
  chatBody?: ChatBodyStyle;
87
83
  };
88
- type FloatingButtonType = {
89
- isInElement?: boolean;
90
- parentElementId?: string;
91
- style?: Partial<CSSStyleDeclaration>;
92
- };
93
84
  type ChatBodyStyle = {
94
85
  position?: PositionType;
95
86
  width?: string;
@@ -111,6 +102,11 @@ type SeekTimelineParamsType = {
111
102
  declare class EventManager {
112
103
  private iframeBridge;
113
104
  constructor(iframeBridge: TapIframeBridge);
105
+ /**
106
+ * Updates timeline position in the chat interface
107
+ * @param params - Timeline seek parameters
108
+ */
109
+ seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType): void;
114
110
  onTimelineSeek(handler: (clipPlayHead: number, clipId: string) => void): void;
115
111
  onChatOpened(handler: () => void): void;
116
112
  onChatClosed(handler: () => void): void;
@@ -121,37 +117,76 @@ declare class EventManager {
121
117
  onPdfClose(handler: () => void): void;
122
118
  }
123
119
 
120
+ /**
121
+ * TapSDK - Interactive chat SDK with toggle button and iframe communication
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const sdk = new TapSDK({ apiKey: 'your-key' });
126
+ * await sdk.init({ course: { userId: 'user1', courseId: 'course1' } });
127
+ * ```
128
+ */
124
129
  declare class TapSDK {
125
130
  #private;
126
131
  private apiKey;
127
132
  private iframeBridge;
128
133
  events: EventManager;
134
+ private eventLogger;
129
135
  private chatBody;
130
136
  private chatBodyMaker;
131
- private floatingButtonMaker;
132
- private isProd;
133
- private isLocal;
134
- private isOpen;
137
+ private button;
138
+ private alarm;
139
+ private chatBodyVisible;
135
140
  private isPdfOpen;
136
- constructor({ apiKey, isProd, isLocal }: TapSDKConfig);
137
- private setIsOpen;
141
+ private _isInitialized;
142
+ /**
143
+ * Creates a new TapSDK instance
144
+ * @param config - SDK configuration options
145
+ */
146
+ constructor({ apiKey }: TapSDKConfig);
147
+ get isOpen(): boolean;
148
+ get isInitialized(): boolean;
149
+ /**
150
+ * Initializes the TapSDK with course data and optional custom styles
151
+ * @param params - Initialization parameters
152
+ * @param params.course - Course information for chat context
153
+ * @param params.customStyles - Optional UI customization styles
154
+ * @throws {Error} When initialization fails
155
+ */
156
+ init({ buttonId, course, customStyles, }: {
157
+ buttonId: string;
158
+ course: Course;
159
+ customStyles?: CustomStyles;
160
+ }): Promise<void>;
161
+ /**
162
+ * Destroys the SDK instance and cleans up all resources
163
+ */
164
+ destroy(): void;
165
+ private isClient;
166
+ private setChatBodyVisible;
138
167
  private setIsPdfOpen;
139
- private sendChatMessage;
140
- seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType): void;
141
- initChat({ course, customStyles, }: {
168
+ private toggleChatOpen;
169
+ private validateEnvironment;
170
+ private setupChatBody;
171
+ private setupButton;
172
+ private setupEventListeners;
173
+ /**
174
+ * @deprecated Use `init` method instead. Will be removed in v1.0.0
175
+ */
176
+ initChat(params: {
142
177
  course: Course;
143
178
  customStyles?: CustomStyles;
179
+ buttonId: string;
144
180
  }): Promise<void>;
145
- removeChat(): void;
146
181
  /**
147
- * @deprecated use `seekTimeline` method. gotta be expired at v1.0.0
182
+ * @deprecated Use `events.seekTimeline` method instead. Will be removed in v1.0.0
148
183
  */
149
184
  postChatInfo({ clipId, clipPlayHead, }: {
150
185
  clipId: string;
151
186
  clipPlayHead: number;
152
187
  }): void;
153
188
  /**
154
- * @deprecated use `events.onTimelineSeek` method. gotta be expired at v1.0.0
189
+ * @deprecated Use `events.onTimelineSeek` method instead. Will be removed in v1.0.0
155
190
  */
156
191
  getTimelineInfo({ callback, }: {
157
192
  callback: (clipPlayHead: number, clipId: string) => void;
package/dist/index.d.ts CHANGED
@@ -33,22 +33,20 @@ interface ChatInitConfig {
33
33
  apiUrl?: string | undefined;
34
34
  }
35
35
  declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
36
- protected hostClientUrl: string;
36
+ #private;
37
+ protected hostOrigin: string;
37
38
  protected apiKey: string;
38
39
  protected iframe: HTMLIFrameElement | null;
39
- constructor({ hostClientUrl, apiKey, }: {
40
- hostClientUrl: string;
40
+ constructor({ hostOrigin, apiKey }: {
41
+ hostOrigin: string;
41
42
  apiKey: string;
42
43
  });
43
44
  protected isValidOrigin(_event: MessageEvent): boolean;
44
45
  protected getMessageTarget(): Window | null;
45
46
  protected getTargetOrigin(): string;
46
- renderIframe({ chatBody, isProd, isLocal, }: {
47
- chatBody: HTMLElement;
48
- isProd: boolean;
49
- isLocal?: boolean;
50
- }): Promise<HTMLIFrameElement>;
47
+ renderIframe(iframeRootElement?: HTMLElement): Promise<HTMLIFrameElement>;
51
48
  hasIframe(): boolean;
49
+ ensureIframe(rootElement?: HTMLElement): Promise<HTMLIFrameElement>;
52
50
  removeIframe(): void;
53
51
  postToTap: (message: ToTapMessage) => boolean;
54
52
  listenToTap: <T extends "timeline:seek" | "chat:opened" | "chat:initiated" | "chat:closed" | "alarm:fadeIn" | "popUp:open" | "pdf:open" | "pdf:close">(messageType: T, callback: (data: Extract<TimelineSeekMessage, {
@@ -69,12 +67,11 @@ declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
69
67
  type: T;
70
68
  }>) => void) => () => void;
71
69
  performHandshake(config: ChatInitConfig, options?: HandshakeOptions): Promise<ChatInitiatedMessage>;
70
+ static defaultHandshakeOptions: HandshakeOptions;
72
71
  }
73
72
 
74
73
  type TapSDKConfig = {
75
74
  apiKey: string;
76
- isProd?: boolean;
77
- isLocal?: boolean;
78
75
  };
79
76
  type Course = {
80
77
  userId: string;
@@ -82,14 +79,8 @@ type Course = {
82
79
  clipId: string | null;
83
80
  };
84
81
  type CustomStyles = {
85
- floatingButton?: FloatingButtonType;
86
82
  chatBody?: ChatBodyStyle;
87
83
  };
88
- type FloatingButtonType = {
89
- isInElement?: boolean;
90
- parentElementId?: string;
91
- style?: Partial<CSSStyleDeclaration>;
92
- };
93
84
  type ChatBodyStyle = {
94
85
  position?: PositionType;
95
86
  width?: string;
@@ -111,6 +102,11 @@ type SeekTimelineParamsType = {
111
102
  declare class EventManager {
112
103
  private iframeBridge;
113
104
  constructor(iframeBridge: TapIframeBridge);
105
+ /**
106
+ * Updates timeline position in the chat interface
107
+ * @param params - Timeline seek parameters
108
+ */
109
+ seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType): void;
114
110
  onTimelineSeek(handler: (clipPlayHead: number, clipId: string) => void): void;
115
111
  onChatOpened(handler: () => void): void;
116
112
  onChatClosed(handler: () => void): void;
@@ -121,37 +117,76 @@ declare class EventManager {
121
117
  onPdfClose(handler: () => void): void;
122
118
  }
123
119
 
120
+ /**
121
+ * TapSDK - Interactive chat SDK with toggle button and iframe communication
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const sdk = new TapSDK({ apiKey: 'your-key' });
126
+ * await sdk.init({ course: { userId: 'user1', courseId: 'course1' } });
127
+ * ```
128
+ */
124
129
  declare class TapSDK {
125
130
  #private;
126
131
  private apiKey;
127
132
  private iframeBridge;
128
133
  events: EventManager;
134
+ private eventLogger;
129
135
  private chatBody;
130
136
  private chatBodyMaker;
131
- private floatingButtonMaker;
132
- private isProd;
133
- private isLocal;
134
- private isOpen;
137
+ private button;
138
+ private alarm;
139
+ private chatBodyVisible;
135
140
  private isPdfOpen;
136
- constructor({ apiKey, isProd, isLocal }: TapSDKConfig);
137
- private setIsOpen;
141
+ private _isInitialized;
142
+ /**
143
+ * Creates a new TapSDK instance
144
+ * @param config - SDK configuration options
145
+ */
146
+ constructor({ apiKey }: TapSDKConfig);
147
+ get isOpen(): boolean;
148
+ get isInitialized(): boolean;
149
+ /**
150
+ * Initializes the TapSDK with course data and optional custom styles
151
+ * @param params - Initialization parameters
152
+ * @param params.course - Course information for chat context
153
+ * @param params.customStyles - Optional UI customization styles
154
+ * @throws {Error} When initialization fails
155
+ */
156
+ init({ buttonId, course, customStyles, }: {
157
+ buttonId: string;
158
+ course: Course;
159
+ customStyles?: CustomStyles;
160
+ }): Promise<void>;
161
+ /**
162
+ * Destroys the SDK instance and cleans up all resources
163
+ */
164
+ destroy(): void;
165
+ private isClient;
166
+ private setChatBodyVisible;
138
167
  private setIsPdfOpen;
139
- private sendChatMessage;
140
- seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType): void;
141
- initChat({ course, customStyles, }: {
168
+ private toggleChatOpen;
169
+ private validateEnvironment;
170
+ private setupChatBody;
171
+ private setupButton;
172
+ private setupEventListeners;
173
+ /**
174
+ * @deprecated Use `init` method instead. Will be removed in v1.0.0
175
+ */
176
+ initChat(params: {
142
177
  course: Course;
143
178
  customStyles?: CustomStyles;
179
+ buttonId: string;
144
180
  }): Promise<void>;
145
- removeChat(): void;
146
181
  /**
147
- * @deprecated use `seekTimeline` method. gotta be expired at v1.0.0
182
+ * @deprecated Use `events.seekTimeline` method instead. Will be removed in v1.0.0
148
183
  */
149
184
  postChatInfo({ clipId, clipPlayHead, }: {
150
185
  clipId: string;
151
186
  clipPlayHead: number;
152
187
  }): void;
153
188
  /**
154
- * @deprecated use `events.onTimelineSeek` method. gotta be expired at v1.0.0
189
+ * @deprecated Use `events.onTimelineSeek` method instead. Will be removed in v1.0.0
155
190
  */
156
191
  getTimelineInfo({ callback, }: {
157
192
  callback: (clipPlayHead: number, clipId: string) => void;