@coxwave/tap-sdk 0.0.7 → 0.0.9

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,135 @@
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
+ buttonId: "tap-button", // ID of the HTML element to attach the toggle button to
26
+ course: {
23
27
  userId: "user-123",
24
28
  courseId: "course-456",
25
- courseName: "JavaScript Fundamentals",
26
- courseCategory: "Programming",
27
- courseSubCategory: "Frontend",
28
29
  clipId: null,
29
- clipPlayHead: null,
30
+ },
31
+ customStyles: {
32
+ chatBody: {
33
+ position: { top: "64px", right: "32px" },
34
+ width: "360px",
35
+ height: "calc(100% - 128px)",
36
+ borderRadius: "18px",
37
+ },
30
38
  },
31
39
  });
32
40
  ```
33
41
 
34
- ## Features
42
+ On initialization the SDK:
35
43
 
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
44
+ - ensures it is running in a browser (guards against SSR)
45
+ - injects the chat container into `document.body`
46
+ - renders the EduTap iframe and performs a handshake for authentication
47
+ - attaches to the element with the provided `buttonId`
42
48
 
43
- ## API Reference
49
+ ## Customisation
44
50
 
45
- ### Constructor
51
+ ### Toggle button
46
52
 
47
- ```javascript
48
- new TapSDK(options);
49
- ```
53
+ The SDK will attach alarm badges and click handlers to the element with the provided `buttonId`.
50
54
 
51
- **Options:**
55
+ ### Chat body
52
56
 
53
- - `apiKey` (string) - Your unique plugin identifier
54
- - `isProd` (boolean) - Production mode flag (default: false)
55
- - `isLocal` (boolean) - Local development flag (default: false)
57
+ The chat surface is a fixed container (`#cw-chat-body`). You can override:
56
58
 
57
- ### Methods
59
+ - `position` — partial `{ top/right/bottom/left }` values (strings with units)
60
+ - `width` / `height` — strings with CSS units
61
+ - `borderRadius`
58
62
 
59
- #### `initChat(config)`
63
+ The container gracefully hides itself when the chat closes and expands when EduTap opens embedded PDFs.
60
64
 
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
- ```
65
+ ### Alarm notifications & pop-ups
87
66
 
88
- #### `seekTimeline(params)`
67
+ 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
68
 
90
- ```javascript
91
- sdk.seekTimeline({
92
- clipId: "clip-123",
93
- clipPlayHead: 150.5,
94
- });
95
- ```
69
+ ## Runtime API
96
70
 
97
- #### `removeChat()`
71
+ ### `init(options)`
98
72
 
99
- ```javascript
100
- sdk.removeChat();
101
- ```
73
+ Initializes the iframe, performs the handshake, and wires up UI controls. Required options:
102
74
 
103
- ### Event Listeners
75
+ - `buttonId` – string (required) - ID of the HTML element to attach the toggle button to
76
+ - `course` – minimal course context (`userId`, `courseId`, `clipId`)
77
+ - `customStyles?` – `{ chatBody? }` - optional UI customization
104
78
 
105
- ```javascript
106
- // Timeline seek events
107
- sdk.events.onTimelineSeek((clipPlayHead, clipId) => {
108
- console.log(`Seek to ${clipPlayHead}s in ${clipId}`);
109
- });
79
+ ### `events.seekTimeline({ clipId, clipPlayHead })`
110
80
 
111
- // Chat state events
112
- sdk.events.onChatOpened(() => console.log("Chat opened"));
113
- sdk.events.onChatClosed(() => console.log("Chat closed"));
81
+ For VOD integrations you can push timeline updates back to EduTap so that it can stay in sync with the host player.
114
82
 
115
- // Notification events
116
- sdk.events.onAlarmFadeIn((messageInfo) => {
117
- console.log("Alarm notification:", messageInfo);
118
- });
83
+ ```ts
84
+ sdk.events.seekTimeline({ clipId: "clip-42", clipPlayHead: 132.4 });
119
85
  ```
120
86
 
121
- ## Framework Integration
87
+ ### `destroy()`
122
88
 
123
- ### React
89
+ 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
90
 
125
- ```jsx
126
- import { useEffect, useRef } from "react";
127
- import TapSDK from "@coxwave/tap-sdk";
91
+ ## Event system
128
92
 
129
- function ChatWidget({ userId, courseId }) {
130
- const sdkRef = useRef(null);
93
+ Events are exposed via the `sdk.events` helper. Every listener returns an unsubscribe function.
131
94
 
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
- });
95
+ ```ts
96
+ // Chat lifecycle events
97
+ sdk.events.onChatInitiated(() => console.log("chat initialized"));
98
+ sdk.events.onChatOpened(() => console.log("chat opened"));
99
+ sdk.events.onChatClosed(() => console.log("chat closed"));
138
100
 
139
- await sdkRef.current.initChat({
140
- chatApiParams: { userId, courseId /* ... */ },
141
- });
142
- };
101
+ // Timeline synchronization
102
+ sdk.events.onTimelineSeek((playHead, clipId) => {
103
+ console.log("EduTap requested timeline seek", playHead, clipId);
104
+ });
143
105
 
144
- initSDK();
145
- return () => sdkRef.current?.removeChat();
146
- }, [userId, courseId]);
106
+ // Notifications and overlays
107
+ sdk.events.onAlarmFadeIn((alarm) => {
108
+ console.log("Alarm", alarm.message);
109
+ });
147
110
 
148
- return <div id="chat-container" />;
149
- }
111
+ sdk.events.onPopUpOpen((popUp) => {
112
+ // popUp.html contains the rendered snippet
113
+ });
114
+
115
+ sdk.events.onPdfOpen(() => console.log("PDF overlay opened"));
116
+ sdk.events.onPdfClose(() => console.log("PDF overlay closed"));
150
117
  ```
151
118
 
152
- ## Build Formats
119
+ ## TypeScript support
120
+
121
+ Type definitions ship with the package. Notable exports:
122
+
123
+ - `TapSDKConfig`
124
+ - `Course`
125
+ - `CustomStyles`
126
+ - `ChatBodyStyle`
127
+ - `SeekTimelineParamsType`
128
+ - `AlarmMessageInstanceType`
153
129
 
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
130
+ All message contracts are sourced from `@coxwave/tap-messages` and validated with `valibot` during the iframe handshake.
158
131
 
159
- ## Browser Support
132
+ ## Browser support
160
133
 
161
134
  - Chrome 60+
162
135
  - Firefox 60+
@@ -165,6 +138,32 @@ function ChatWidget({ userId, courseId }) {
165
138
 
166
139
  ## License
167
140
 
168
- MIT
141
+ MIT © 2025 Coxwave
142
+
143
+ ## Properties
144
+
145
+ ### `isOpen`
146
+
147
+ Returns `true` if the chat interface is currently open.
148
+
149
+ ```ts
150
+ if (sdk.isOpen) {
151
+ console.log("Chat is currently open");
152
+ }
153
+ ```
154
+
155
+ ### `isInitialized`
156
+
157
+ Returns `true` if the SDK has been successfully initialized.
158
+
159
+ ```ts
160
+ if (sdk.isInitialized) {
161
+ console.log("SDK is ready to use");
162
+ }
163
+ ```
164
+
165
+ ## Deprecated helpers
169
166
 
170
- Copyright (c) 2025-present, Coxwave
167
+ - `initChat(options)` use `init(options)` instead; scheduled for removal in v1.0.0
168
+ - `postChatInfo({ clipId, clipPlayHead })` – alias for `events.seekTimeline`; scheduled for removal in v1.0.0
169
+ - `getTimelineInfo({ callback })` – use `sdk.events.onTimelineSeek` instead; scheduled for removal in v1.0.0
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":"AAAA,WAAW,UACT,GACE,QAAS,EACT,UAAW,WAAW,KACxB,CACA,GACE,QAAS,EACT,UAAW,WAAW,EACxB,CACF,CACA,WAAW,UACT,GACE,QAAS,EACT,UAAW,WAAW,EACxB,CACA,GACE,QAAS,EACT,UAAW,WAAW,MACtB,QAAS,IACX,CACF,CACA,CAAC,UACC,QAAS,EACT,UAAW,WAAW,MACtB,WAAY,QAAQ,IAAK,IAAI,CAAE,UAAU,IAAK,KAC9C,eAAgB,KAChB,QAAS,IACX,CACA,CAAC,UACC,UAAW,UAAU,IAAK,KAAK,SAC/B,eAAgB,IAClB,CACA,CAAC,UACC,UAAW,UAAU,IAAK,KAAK,SAC/B,eAAgB,IAClB,CACA,CAAC,UACC,OAAQ,cACV,CCtCA,WAAW,SACT,GACE,QAAS,EACT,eAAgB,IAClB,CACA,IACE,QAAS,CACX,CACA,GACE,QAAS,CACX,CACF,CACA,CAAC,SACC,eAAgB,KAChB,QAAS,EACT,QAAS,KACT,SAAU,SACV,MAAO,YACP,IAAK,KAAK,KAAK,EAAE,KACjB,MAAO,EACP,eAAgB,OAChB,gBAAiB,OACjB,YAAa,SACb,YAAa,IACb,OAAQ,QACR,QAAS,IACT,WAAY,QAAQ,IAAK,IAC3B,CACA,CAAC,SACC,eAAgB,KAChB,UAAW,SAAS,IAAI,QAC1B,CACA,CAAC,SACC,QAAS,EACT,eAAgB,KAChB,UAAW,IACb,CACA,CAAC,SACC,QAAS,KACT,gBAAiB,SACjB,cAAe,IAAI,iBAAiB,EAAE,KACtC,MAAO,YACP,IAAK,GACP,CACA,CAAC,SACC,QAAS,KA7CX,QA8CW,IAAI,KAAK,IAClB,gBAAiB,SACjB,YAAa,OACb,cAAe,IAAI,iBAAiB,EAAE,KACtC,UAAW,KACb,CACA,CAAC,SACC,iBAAkB,OACpB,CACA,CAAC,SACC,iBAAkB,OACpB,CACA,CAAC,SACC,MAAO,KACP,WAAY,MACZ,YAAa,WACb,UAAW,KACX,WAAY,OACZ,YAAa,IACb,YAAa,KACb,YAAa,SACb,WAAY,SACZ,cAAe,UACjB,CACA,CAAC,SACC,QAAS,KAvEX,QAwEW,EAAI,KACb,YAAa,WACb,IAAK,IACP,CACA,CAAC,SACC,MAAO,IACT,CACA,CAAC,SACC,MAAO,OACT,CACA,CAAC,SACC,MAAO,OACT,CACA,CAAC,SACC,OAAQ,QACR,gBAAiB,OACjB,YAAa,OACb,MAAO,KACP,OAAQ,KA1FV,cA2FiB,MACf,QAAS,IACT,WAAY,IAAI,IAAK,IACvB,CACA,CAVC,QAUQ,OACP,MAAO,KACP,KAAM,KACR,CACA,CA9DC,QA8DQ,OAAO,CAdf,SAeC,QAAS,IACX,CACA,CAAC,SAID,CAAC,SAHC,QAAS,KACT,iBAAkB,OACpB,CAKA,CAAC,SACC,MAAO,IACT,CACA,CA5BC,QA4BQ,OAAO,CAHf,SAIC,QAAS,IACX,CACA,CAAC,SACC,MAAO,KACP,WAAY,OACZ,YAAa,WACb,UAAW,KACX,WAAY,OACZ,YAAa,IACb,YAAa,KACb,QAAS,IACX,CACA,CAzCC,QAyCQ,OAAO,CAVf,SAWC,QAAS,KACX,CChIA,CAAC,QACC,MAAO,KACP,UAAW,YACX,aAAc,KACd,gBAAiB,SACjB,eAAgB,EAChB,OAAQ,KAAM,MAAM,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,KAN1C,cAOiB,IACf,SAAU,KACV,iBAAkB,KAClB,OAAQ,OACV,CACA,CAAC,QACC,OAAQ,KAAM,MAAM,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,KAb1C,QAcW,KACT,iBAAkB,QAClB,WAAY,KACZ,YAAa,WACb,MAAO,QACP,UAAW,KACX,YAAa,IACb,YAAa,OACb,cAAe,WACf,WAAY,UACd,CACA,CAAC,QACC,OAAQ,KAAM,MAAM,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,KA1B1C,QA2BW,KACT,MAAO,QACP,YAAa,WACb,UAAW,KACX,YAAa,IACb,MAAO,YACP,UAAW,MACX,YAAa,OACb,cAAe,WACf,WAAY,UACd,CACA,CAAC,QACC,SAAU,SACV,iBAAkB,QAxCpB,cAyCiB,IAzCjB,QA0CW,IACT,WAAY,IACd,CACA,CAAC,QACC,QAAS,KACT,YAAa,OACb,gBAAiB,cACjB,eAAgB,GAClB,CACA,CAAC,QACC,MAAO,QApDT,QAqDW,IAAI,IACb,UAAW,KAtDb,cAuDiB,IACf,QAAS,GACT,YAAa,UACf,CACA,CAAC,QACC,QAAS,GACT,OAAQ,QACR,QAAS,KACT,YAAa,OACb,MAAO,YACP,MAAO,QAjET,QAkEW,IAAI,IACb,UAAW,KACX,OAAQ,KACR,YAAa,UACf,CACA,CAAC,QACC,YAAa,MACf,CACA,CAAC,QACC,QAAS,KACT,MAAO,KACP,OAAQ,KACR,cAAe,IACf,MAAO,QACP,YAAa,CACf","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":"AAAA,WAAW,UACT,GACE,QAAS,EACT,UAAW,WAAW,KACxB,CACA,GACE,QAAS,EACT,UAAW,WAAW,EACxB,CACF,CACA,WAAW,UACT,GACE,QAAS,EACT,UAAW,WAAW,EACxB,CACA,GACE,QAAS,EACT,UAAW,WAAW,MACtB,QAAS,IACX,CACF,CACA,CAAC,UACC,QAAS,EACT,UAAW,WAAW,MACtB,WAAY,QAAQ,IAAK,IAAI,CAAE,UAAU,IAAK,KAC9C,eAAgB,KAChB,QAAS,IACX,CACA,CAAC,UACC,UAAW,UAAU,IAAK,KAAK,SAC/B,eAAgB,IAClB,CACA,CAAC,UACC,UAAW,UAAU,IAAK,KAAK,SAC/B,eAAgB,IAClB,CACA,CAAC,UACC,OAAQ,cACV,CCtCA,WAAW,QACT,GACE,QAAS,EACT,eAAgB,IAClB,CACA,IACE,QAAS,CACX,CACA,GACE,QAAS,CACX,CACF,CACA,CAAC,QACC,eAAgB,KAChB,QAAS,EACT,QAAS,KACT,SAAU,SACV,MAAO,YACP,IAAK,KAAK,KAAK,EAAE,KACjB,MAAO,EACP,eAAgB,OAChB,gBAAiB,OACjB,YAAa,SACb,YAAa,IACb,OAAQ,QACR,QAAS,IACT,WAAY,QAAQ,IAAK,IAC3B,CACA,CAAC,QACC,eAAgB,KAChB,UAAW,QAAQ,IAAI,QACzB,CACA,CAAC,QACC,QAAS,EACT,eAAgB,KAChB,UAAW,IACb,CACA,CAAC,QACC,QAAS,KACT,gBAAiB,SACjB,cAAe,IAAI,iBAAiB,EAAE,KACtC,MAAO,YACP,IAAK,GACP,CACA,CAAC,QACC,QAAS,KA7CX,QA8CW,IAAI,KAAK,IAClB,gBAAiB,SACjB,YAAa,OACb,cAAe,IAAI,iBAAiB,EAAE,KACtC,UAAW,KACb,CACA,CAAC,QACC,iBAAkB,OACpB,CACA,CAAC,QACC,iBAAkB,OACpB,CACA,CAAC,QACC,MAAO,KACP,WAAY,MACZ,YAAa,WACb,UAAW,KACX,WAAY,OACZ,YAAa,IACb,YAAa,KACb,YAAa,SACb,WAAY,SACZ,cAAe,UACjB,CACA,CAAC,QACC,QAAS,KAvEX,QAwEW,EAAI,KACb,YAAa,WACb,IAAK,IACP,CACA,CAAC,QACC,MAAO,IACT,CACA,CAAC,QACC,MAAO,OACT,CACA,CAAC,QACC,MAAO,OACT,CACA,CAAC,QACC,OAAQ,QACR,gBAAiB,OACjB,YAAa,OACb,MAAO,KACP,OAAQ,KA1FV,cA2FiB,MACf,QAAS,IACT,WAAY,IAAI,IAAK,IACvB,CACA,CAVC,OAUO,OACN,MAAO,KACP,KAAM,KACR,CACA,CA9DC,OA8DO,OAAO,CAdd,QAeC,QAAS,IACX,CACA,CAAC,QAID,CAAC,QAHC,QAAS,KACT,iBAAkB,OACpB,CAKA,CAAC,QACC,MAAO,IACT,CACA,CA5BC,OA4BO,OAAO,CAHd,QAIC,QAAS,IACX,CACA,CAAC,QACC,MAAO,KACP,WAAY,OACZ,YAAa,WACb,UAAW,KACX,WAAY,OACZ,YAAa,IACb,YAAa,KACb,QAAS,IACX,CACA,CAzCC,OAyCO,OAAO,CAVd,QAWC,QAAS,KACX,CChIA,CAAC,QACC,MAAO,KACP,UAAW,YACX,aAAc,KACd,gBAAiB,SACjB,eAAgB,EAChB,OAAQ,KAAM,MAAM,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,KAN1C,cAOiB,IACf,SAAU,KACV,iBAAkB,KAClB,OAAQ,OACV,CACA,CAAC,QACC,OAAQ,KAAM,MAAM,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,KAb1C,QAcW,KACT,iBAAkB,QAClB,WAAY,KACZ,YAAa,WACb,MAAO,QACP,UAAW,KACX,YAAa,IACb,YAAa,OACb,cAAe,WACf,WAAY,UACd,CACA,CAAC,QACC,OAAQ,KAAM,MAAM,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,KA1B1C,QA2BW,KACT,MAAO,QACP,YAAa,WACb,UAAW,KACX,YAAa,IACb,MAAO,YACP,UAAW,MACX,YAAa,OACb,cAAe,WACf,WAAY,UACd,CACA,CAAC,QACC,SAAU,SACV,iBAAkB,QAxCpB,cAyCiB,IAzCjB,QA0CW,IACT,WAAY,IACd,CACA,CAAC,QACC,QAAS,KACT,YAAa,OACb,gBAAiB,cACjB,eAAgB,GAClB,CACA,CAAC,QACC,MAAO,QApDT,QAqDW,IAAI,IACb,UAAW,KAtDb,cAuDiB,IACf,QAAS,GACT,YAAa,UACf,CACA,CAAC,QACC,QAAS,GACT,OAAQ,QACR,QAAS,KACT,YAAa,OACb,MAAO,YACP,MAAO,QAjET,QAkEW,IAAI,IACb,UAAW,KACX,OAAQ,KACR,YAAa,UACf,CACA,CAAC,QACC,YAAa,MACf,CACA,CAAC,QACC,QAAS,KACT,MAAO,KACP,OAAQ,KACR,cAAe,IACf,MAAO,QACP,YAAa,CACf","names":[]}
package/dist/index.d.cts CHANGED
@@ -25,6 +25,26 @@ interface HandshakeOptions {
25
25
  retryInterval?: number;
26
26
  }
27
27
 
28
+ interface LogEvent {
29
+ action: string;
30
+ category: string;
31
+ label?: string;
32
+ value?: number;
33
+ customParams?: Record<string, any>;
34
+ }
35
+ interface EventMiddleware {
36
+ handle(event: LogEvent): void;
37
+ }
38
+ declare class EventLogger {
39
+ private middlewares;
40
+ addMiddleware(middleware: EventMiddleware): void;
41
+ removeMiddleware(middleware: EventMiddleware): void;
42
+ log(event: LogEvent): void;
43
+ logChatAction(action: "opened" | "closed" | "initialized", customParams?: Record<string, any>): void;
44
+ logButtonClick(buttonType: "toggle" | "alarm", state?: string, customParams?: Record<string, any>): void;
45
+ logSDKInitialization(success: boolean, startTime: number, error?: string): void;
46
+ }
47
+
28
48
  type ToTapMessage = ChatInitMessage | ChatOpenMessage | ChatCloseMessage | TimelineSeekMessage | AlarmClickMessage | PopUpCloseMessage | PdfEnlargedMessage | PdfShrinkedMessage;
29
49
  type FromTapMessage = ChatInitiatedMessage | ChatOpenedMessage | ChatClosedMessage | AlarmFadeInMessage | PopUpOpenMessage | PdfOpenMessage | PdfCloseMessage | TimelineSeekMessage;
30
50
  interface ChatInitConfig {
@@ -33,22 +53,22 @@ interface ChatInitConfig {
33
53
  apiUrl?: string | undefined;
34
54
  }
35
55
  declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
36
- protected hostClientUrl: string;
56
+ #private;
57
+ protected hostOrigin: string;
37
58
  protected apiKey: string;
38
59
  protected iframe: HTMLIFrameElement | null;
39
- constructor({ hostClientUrl, apiKey, }: {
40
- hostClientUrl: string;
60
+ private eventLogger;
61
+ constructor({ hostOrigin, apiKey, eventLogger, }: {
62
+ hostOrigin: string;
41
63
  apiKey: string;
64
+ eventLogger?: EventLogger;
42
65
  });
43
66
  protected isValidOrigin(_event: MessageEvent): boolean;
44
67
  protected getMessageTarget(): Window | null;
45
68
  protected getTargetOrigin(): string;
46
- renderIframe({ chatBody, isProd, isLocal, }: {
47
- chatBody: HTMLElement;
48
- isProd: boolean;
49
- isLocal?: boolean;
50
- }): Promise<HTMLIFrameElement>;
69
+ renderIframe(iframeRootElement?: HTMLElement): Promise<HTMLIFrameElement>;
51
70
  hasIframe(): boolean;
71
+ ensureIframe(rootElement?: HTMLElement): Promise<HTMLIFrameElement>;
52
72
  removeIframe(): void;
53
73
  postToTap: (message: ToTapMessage) => boolean;
54
74
  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 +89,11 @@ declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
69
89
  type: T;
70
90
  }>) => void) => () => void;
71
91
  performHandshake(config: ChatInitConfig, options?: HandshakeOptions): Promise<ChatInitiatedMessage>;
92
+ static defaultHandshakeOptions: HandshakeOptions;
72
93
  }
73
94
 
74
95
  type TapSDKConfig = {
75
96
  apiKey: string;
76
- isProd?: boolean;
77
- isLocal?: boolean;
78
97
  };
79
98
  type Course = {
80
99
  userId: string;
@@ -82,14 +101,8 @@ type Course = {
82
101
  clipId: string | null;
83
102
  };
84
103
  type CustomStyles = {
85
- floatingButton?: FloatingButtonType;
86
104
  chatBody?: ChatBodyStyle;
87
105
  };
88
- type FloatingButtonType = {
89
- isInElement?: boolean;
90
- parentElementId?: string;
91
- style?: Partial<CSSStyleDeclaration>;
92
- };
93
106
  type ChatBodyStyle = {
94
107
  position?: PositionType;
95
108
  width?: string;
@@ -111,6 +124,11 @@ type SeekTimelineParamsType = {
111
124
  declare class EventManager {
112
125
  private iframeBridge;
113
126
  constructor(iframeBridge: TapIframeBridge);
127
+ /**
128
+ * Updates timeline position in the chat interface
129
+ * @param params - Timeline seek parameters
130
+ */
131
+ seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType): void;
114
132
  onTimelineSeek(handler: (clipPlayHead: number, clipId: string) => void): void;
115
133
  onChatOpened(handler: () => void): void;
116
134
  onChatClosed(handler: () => void): void;
@@ -121,37 +139,76 @@ declare class EventManager {
121
139
  onPdfClose(handler: () => void): void;
122
140
  }
123
141
 
142
+ /**
143
+ * TapSDK - Interactive chat SDK with toggle button and iframe communication
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const sdk = new TapSDK({ apiKey: 'your-key' });
148
+ * await sdk.init({ course: { userId: 'user1', courseId: 'course1' } });
149
+ * ```
150
+ */
124
151
  declare class TapSDK {
125
152
  #private;
126
153
  private apiKey;
127
154
  private iframeBridge;
128
155
  events: EventManager;
156
+ private eventLogger;
129
157
  private chatBody;
130
158
  private chatBodyMaker;
131
- private floatingButtonMaker;
132
- private isProd;
133
- private isLocal;
134
- private isOpen;
159
+ private button;
160
+ private alarm;
161
+ private chatBodyVisible;
135
162
  private isPdfOpen;
136
- constructor({ apiKey, isProd, isLocal }: TapSDKConfig);
137
- private setIsOpen;
163
+ private _isInitialized;
164
+ /**
165
+ * Creates a new TapSDK instance
166
+ * @param config - SDK configuration options
167
+ */
168
+ constructor({ apiKey }: TapSDKConfig);
169
+ get isOpen(): boolean;
170
+ get isInitialized(): boolean;
171
+ /**
172
+ * Initializes the TapSDK with course data and optional custom styles
173
+ * @param params - Initialization parameters
174
+ * @param params.course - Course information for chat context
175
+ * @param params.customStyles - Optional UI customization styles
176
+ * @throws {Error} When initialization fails
177
+ */
178
+ init({ buttonId, course, customStyles, }: {
179
+ buttonId: string;
180
+ course: Course;
181
+ customStyles?: CustomStyles;
182
+ }): Promise<void>;
183
+ /**
184
+ * Destroys the SDK instance and cleans up all resources
185
+ */
186
+ destroy(): void;
187
+ private isClient;
188
+ private setChatBodyVisible;
138
189
  private setIsPdfOpen;
139
- private sendChatMessage;
140
- seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType): void;
141
- initChat({ course, customStyles, }: {
190
+ private toggleChatOpen;
191
+ private validateEnvironment;
192
+ private setupChatBody;
193
+ private setupButton;
194
+ private setupEventListeners;
195
+ /**
196
+ * @deprecated Use `init` method instead. Will be removed in v1.0.0
197
+ */
198
+ initChat(params: {
142
199
  course: Course;
143
200
  customStyles?: CustomStyles;
201
+ buttonId: string;
144
202
  }): Promise<void>;
145
- removeChat(): void;
146
203
  /**
147
- * @deprecated use `seekTimeline` method. gotta be expired at v1.0.0
204
+ * @deprecated Use `events.seekTimeline` method instead. Will be removed in v1.0.0
148
205
  */
149
206
  postChatInfo({ clipId, clipPlayHead, }: {
150
207
  clipId: string;
151
208
  clipPlayHead: number;
152
209
  }): void;
153
210
  /**
154
- * @deprecated use `events.onTimelineSeek` method. gotta be expired at v1.0.0
211
+ * @deprecated Use `events.onTimelineSeek` method instead. Will be removed in v1.0.0
155
212
  */
156
213
  getTimelineInfo({ callback, }: {
157
214
  callback: (clipPlayHead: number, clipId: string) => void;