@coxwave/tap-sdk 0.0.2 → 0.0.4
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 +134 -330
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,390 +1,194 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @coxwave/tap-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A vanilla JavaScript SDK for embedding AI chat widgets into web applications with seamless iframe communication.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
- [Installation](#installation)
|
|
8
|
-
- [Quick Use](#quick-use)
|
|
9
|
-
- [Types](#types)
|
|
10
|
-
- [Legacy](#legacy)
|
|
11
|
-
- [License](#license)
|
|
12
|
-
|
|
13
|
-
## installation
|
|
14
|
-
|
|
15
|
-
### npm
|
|
5
|
+
## Installation
|
|
16
6
|
|
|
17
7
|
```bash
|
|
18
|
-
npm
|
|
8
|
+
npm install @coxwave/tap-sdk
|
|
19
9
|
```
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
yarn add ax-sdk-chatbot
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Quick Use
|
|
28
|
-
|
|
29
|
-
### vite
|
|
30
|
-
|
|
31
|
-
#### Use In Root
|
|
32
|
-
|
|
33
|
-
```ts
|
|
34
|
-
-main.tsx;
|
|
35
|
-
|
|
36
|
-
import { createRoot } from "react-dom/client";
|
|
11
|
+
## Quick Start
|
|
37
12
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
import App from "./App.tsx";
|
|
41
|
-
|
|
42
|
-
import "./index.css";
|
|
13
|
+
```javascript
|
|
14
|
+
import TapSDK from "@coxwave/tap-sdk";
|
|
43
15
|
|
|
44
16
|
const sdk = new TapSDK({
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
isProd: false,
|
|
17
|
+
pluginKey: "your-plugin-key",
|
|
18
|
+
isProd: true,
|
|
48
19
|
});
|
|
49
20
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
sdk.initChat({
|
|
21
|
+
await sdk.initChat({
|
|
53
22
|
chatApiParams: {
|
|
54
|
-
userId: "
|
|
55
|
-
courseId: "
|
|
56
|
-
courseName: "
|
|
57
|
-
courseCategory: "
|
|
58
|
-
courseSubCategory: "
|
|
59
|
-
clipId:
|
|
60
|
-
clipPlayHead:
|
|
61
|
-
},
|
|
62
|
-
shortcutKey: {
|
|
63
|
-
openChat: { key: "/", modifier: "" },
|
|
64
|
-
sendChat: { key: "Enter", modifier: "" },
|
|
65
|
-
},
|
|
66
|
-
customStyles: {
|
|
67
|
-
floatingButton: {
|
|
68
|
-
isInElement: true,
|
|
69
|
-
parentElementId: "root-button", // <------ here is your Floating Button parent element Id
|
|
70
|
-
},
|
|
23
|
+
userId: "user-123",
|
|
24
|
+
courseId: "course-456",
|
|
25
|
+
courseName: "JavaScript Fundamentals",
|
|
26
|
+
courseCategory: "Programming",
|
|
27
|
+
courseSubCategory: "Frontend",
|
|
28
|
+
clipId: null,
|
|
29
|
+
clipPlayHead: null,
|
|
71
30
|
},
|
|
72
31
|
});
|
|
32
|
+
```
|
|
73
33
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
import { useEffect, useState } from "react";
|
|
77
|
-
|
|
78
|
-
import "./App.css";
|
|
79
|
-
|
|
80
|
-
import TapSDK from "coxwave-sdk";
|
|
81
|
-
|
|
82
|
-
function App({ sdk }: { sdk: TapSDK }) {
|
|
83
|
-
const [clipPlayHead, setClipPlayHead] = useState(0);
|
|
34
|
+
## Features
|
|
84
35
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
89
42
|
|
|
90
|
-
|
|
91
|
-
}, []);
|
|
43
|
+
## API Reference
|
|
92
44
|
|
|
93
|
-
|
|
94
|
-
sdk.postChatInfo({
|
|
95
|
-
clipId: "58767",
|
|
96
|
-
clipPlayHead,
|
|
97
|
-
});
|
|
98
|
-
}, [clipPlayHead]);
|
|
45
|
+
### Constructor
|
|
99
46
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<div id="root-button">{Your Floating Button styles Element}</div> // <------ This is your floating button parent element. It must have the same ID as parentElementId.
|
|
103
|
-
</>
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export default App;
|
|
47
|
+
```javascript
|
|
48
|
+
new TapSDK(options)
|
|
108
49
|
```
|
|
109
50
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
import { useEffect, useState } from "react";
|
|
51
|
+
**Options:**
|
|
52
|
+
- `pluginKey` (string) - Your unique plugin identifier
|
|
53
|
+
- `isProd` (boolean) - Production mode flag (default: false)
|
|
54
|
+
- `isLocal` (boolean) - Local development flag (default: false)
|
|
116
55
|
|
|
117
|
-
|
|
56
|
+
### Methods
|
|
118
57
|
|
|
119
|
-
|
|
58
|
+
#### `initChat(config)`
|
|
120
59
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
60
|
+
```javascript
|
|
61
|
+
await sdk.initChat({
|
|
62
|
+
chatApiParams: {
|
|
63
|
+
userId: string,
|
|
64
|
+
courseId: string | null,
|
|
65
|
+
courseName: string,
|
|
66
|
+
courseCategory: string,
|
|
67
|
+
courseSubCategory: string,
|
|
68
|
+
clipId: string | null,
|
|
69
|
+
clipPlayHead: number | null
|
|
70
|
+
},
|
|
71
|
+
customStyles?: {
|
|
72
|
+
floatingButton?: {
|
|
73
|
+
isInElement?: boolean,
|
|
74
|
+
parentElementId?: string,
|
|
75
|
+
style?: Partial<CSSStyleDeclaration>
|
|
76
|
+
},
|
|
77
|
+
chatBody?: {
|
|
78
|
+
position?: { top?: string, right?: string, left?: string, bottom?: string },
|
|
79
|
+
width?: string,
|
|
80
|
+
height?: string,
|
|
81
|
+
borderRadius?: string
|
|
82
|
+
}
|
|
83
|
+
}
|
|
125
84
|
});
|
|
85
|
+
```
|
|
126
86
|
|
|
87
|
+
#### `seekTimeline(params)`
|
|
127
88
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
userId: "user_id",
|
|
135
|
-
courseId: "course_id",
|
|
136
|
-
courseName: "course_name",
|
|
137
|
-
courseCategory: "course_category",
|
|
138
|
-
courseSubCategory: "course_sub_category",
|
|
139
|
-
clipId: "clip_id",
|
|
140
|
-
clipPlayHead: clip_play_head_number,
|
|
141
|
-
},
|
|
142
|
-
customStyles: {
|
|
143
|
-
floatingButton: {
|
|
144
|
-
isInElement: true,
|
|
145
|
-
parentElementId: "root-button",
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
return () => {
|
|
151
|
-
sdk.removeChat(); // this is sdk cleanup function
|
|
152
|
-
};
|
|
153
|
-
}, []);
|
|
154
|
-
|
|
155
|
-
useEffect(() => {
|
|
156
|
-
const interval = setInterval(() => {
|
|
157
|
-
setClipPlayHead((prev) => prev + 5);
|
|
158
|
-
}, 1000);
|
|
159
|
-
|
|
160
|
-
return () => clearInterval(interval);
|
|
161
|
-
}, []);
|
|
162
|
-
|
|
163
|
-
useEffect(() => {
|
|
164
|
-
sdk.postChatInfo({
|
|
165
|
-
clipId: "58767",
|
|
166
|
-
clipPlayHead,
|
|
167
|
-
});
|
|
168
|
-
}, [clipPlayHead]);
|
|
169
|
-
|
|
170
|
-
return (
|
|
171
|
-
<S.LayoutContainer $isWhiteBack={true}>
|
|
172
|
-
<S.ContentBox>
|
|
173
|
-
<S.RootButton id="root-button">
|
|
174
|
-
<S.BotImage src={BotImage} />
|
|
175
|
-
<S.Text>AI 튜터</S.Text>
|
|
176
|
-
</S.RootButton>
|
|
177
|
-
</S.ContentBox>
|
|
178
|
-
</S.LayoutContainer>
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export default Test;
|
|
89
|
+
```javascript
|
|
90
|
+
sdk.seekTimeline({
|
|
91
|
+
clipId: 'clip-123',
|
|
92
|
+
clipPlayHead: 150.5
|
|
93
|
+
});
|
|
94
|
+
```
|
|
183
95
|
|
|
184
|
-
|
|
185
|
-
~
|
|
186
|
-
} // your styles (this example is for styled-components)
|
|
96
|
+
#### `removeChat()`
|
|
187
97
|
|
|
98
|
+
```javascript
|
|
99
|
+
sdk.removeChat();
|
|
188
100
|
```
|
|
189
101
|
|
|
190
|
-
###
|
|
102
|
+
### Event Listeners
|
|
191
103
|
|
|
192
|
-
|
|
104
|
+
```javascript
|
|
105
|
+
// Timeline seek events
|
|
106
|
+
sdk.events.onTimelineSeek((clipPlayHead, clipId) => {
|
|
107
|
+
console.log(`Seek to ${clipPlayHead}s in ${clipId}`);
|
|
108
|
+
});
|
|
193
109
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
export default function Home() {
|
|
198
|
-
return (
|
|
199
|
-
<Sdk />
|
|
200
|
-
);
|
|
201
|
-
}
|
|
110
|
+
// Chat state events
|
|
111
|
+
sdk.events.onChatOpened(() => console.log('Chat opened'));
|
|
112
|
+
sdk.events.onChatClosed(() => console.log('Chat closed'));
|
|
202
113
|
|
|
114
|
+
// Notification events
|
|
115
|
+
sdk.events.onAlarmFadeIn((messageInfo) => {
|
|
116
|
+
console.log('Alarm notification:', messageInfo);
|
|
117
|
+
});
|
|
203
118
|
```
|
|
204
119
|
|
|
205
|
-
|
|
120
|
+
## Framework Integration
|
|
206
121
|
|
|
207
|
-
|
|
208
|
-
"use client"; // if you use this sdk in Next.js, you must use this
|
|
122
|
+
### React
|
|
209
123
|
|
|
210
|
-
|
|
124
|
+
```jsx
|
|
125
|
+
import { useEffect, useRef } from 'react';
|
|
126
|
+
import TapSDK from '@coxwave/tap-sdk';
|
|
211
127
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const clientUrl = process.env.NEXT_PUBLIC_HOST_CLIENT_URL; // your client url (if you use localhost, your client url is http://localhost:3000)
|
|
215
|
-
const pluginKey = process.env.NEXT_PUBLIC_COXWAVE_PLUGIN_KEY;
|
|
216
|
-
|
|
217
|
-
if (!clientUrl) {
|
|
218
|
-
throw new Error("NEXT_PUBLIC_COXWAVE_CLIENT_URL is not set");
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (!pluginKey) {
|
|
222
|
-
throw new Error("NEXT_PUBLIC_COXWAVE_PLUGIN_KEY is not set");
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function Sdk() {
|
|
226
|
-
const iframeRef = useRef<HTMLDivElement>(null);
|
|
128
|
+
function ChatWidget({ userId, courseId }) {
|
|
129
|
+
const sdkRef = useRef(null);
|
|
227
130
|
|
|
228
131
|
useEffect(() => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
await TapSDKInstance.initChat({
|
|
239
|
-
chatApiParams: {
|
|
240
|
-
userId: "user_id",
|
|
241
|
-
courseId: "course_id",
|
|
242
|
-
courseName: "course_name",
|
|
243
|
-
courseCategory: "course_category",
|
|
244
|
-
courseSubCategory: "course_sub_category",
|
|
245
|
-
clipId: "clip_id",
|
|
246
|
-
clipPlayHead: clip_play_head_number,
|
|
247
|
-
},
|
|
248
|
-
customStyles: {
|
|
249
|
-
floatingButton: {
|
|
250
|
-
isInElement: true,
|
|
251
|
-
parentElementId: "root-button", // <------ here is your Floating Button parent element Id
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
});
|
|
255
|
-
} catch (err) {
|
|
256
|
-
console.error("SDK initChat 실패:", err);
|
|
257
|
-
}
|
|
132
|
+
const initSDK = async () => {
|
|
133
|
+
sdkRef.current = new TapSDK({
|
|
134
|
+
pluginKey: process.env.REACT_APP_TAP_PLUGIN_KEY,
|
|
135
|
+
isProd: process.env.NODE_ENV === 'production'
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await sdkRef.current.initChat({
|
|
139
|
+
chatApiParams: { userId, courseId, /* ... */ }
|
|
140
|
+
});
|
|
258
141
|
};
|
|
259
142
|
|
|
260
|
-
|
|
143
|
+
initSDK();
|
|
144
|
+
return () => sdkRef.current?.removeChat();
|
|
145
|
+
}, [userId, courseId]);
|
|
261
146
|
|
|
262
|
-
|
|
263
|
-
TapSDKInstance.removeChat();
|
|
264
|
-
};
|
|
265
|
-
}, [clientUrl]);
|
|
266
|
-
|
|
267
|
-
return (
|
|
268
|
-
<div
|
|
269
|
-
ref={iframeRef}
|
|
270
|
-
id="root-button" // <------ This is your floating button parent element. It must have the same ID as parentElementId.
|
|
271
|
-
style={{
|
|
272
|
-
width: "50px",
|
|
273
|
-
height: "50px",
|
|
274
|
-
backgroundColor: "red",
|
|
275
|
-
cursor: "pointer",
|
|
276
|
-
}}
|
|
277
|
-
>
|
|
278
|
-
<button>Open Chat</button>
|
|
279
|
-
</div>
|
|
280
|
-
);
|
|
147
|
+
return <div id="chat-container" />;
|
|
281
148
|
}
|
|
282
|
-
|
|
283
|
-
export default Sdk;
|
|
284
149
|
```
|
|
285
150
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
### SDK Class
|
|
289
|
-
|
|
290
|
-
```ts
|
|
291
|
-
const TapSDKInstance = new TapSDK({
|
|
292
|
-
hostClientUrl: "~",
|
|
293
|
-
pluginKey: "~",
|
|
294
|
-
});
|
|
151
|
+
### Next.js
|
|
295
152
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
};
|
|
301
|
-
```
|
|
153
|
+
```jsx
|
|
154
|
+
"use client";
|
|
155
|
+
import { useEffect } from 'react';
|
|
156
|
+
import TapSDK from '@coxwave/tap-sdk';
|
|
302
157
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
shortcutKey,
|
|
310
|
-
}: {
|
|
311
|
-
chatApiParams: ChatApiParamsType;
|
|
312
|
-
customStyles?: CustomStylesType;
|
|
313
|
-
shortcutKey?: ShortcutKeyType;
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
type ChatApiParamsType = {
|
|
317
|
-
userId: string;
|
|
318
|
-
courseId: string;
|
|
319
|
-
courseName: string;
|
|
320
|
-
courseCategory: string;
|
|
321
|
-
courseSubCategory: string;
|
|
322
|
-
clipId: string | null;
|
|
323
|
-
clipPlayHead: number | null;
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
type CustomStylesType = {
|
|
327
|
-
floatingButton?: FloatingButtonType;
|
|
328
|
-
chatBody?: ChatBodyType;
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
type ShortcutKeyType = {
|
|
332
|
-
openChat: ShortcutKeyPropertiesType;
|
|
333
|
-
sendChat: ShortcutKeyPropertiesType;
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
type FloatingButtonType = {
|
|
337
|
-
isInElement?: boolean;
|
|
338
|
-
parentElementId?: string;
|
|
339
|
-
style?: Partial<CSSStyleDeclaration>;
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
type ChatBodyType = {
|
|
343
|
-
position?: PositionType;
|
|
344
|
-
width?: string;
|
|
345
|
-
height?: string;
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
type PositionType = {
|
|
349
|
-
top?: string;
|
|
350
|
-
left?: string;
|
|
351
|
-
right?: string;
|
|
352
|
-
bottom?: string;
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
type ShortcutKeyPropertiesType = {
|
|
356
|
-
key: string;
|
|
357
|
-
modifier: "ctrlKey" | "altKey" | "shiftKey" | "metaKey" | "";
|
|
358
|
-
};
|
|
158
|
+
export default function ChatPage() {
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
const sdk = new TapSDK({
|
|
161
|
+
pluginKey: process.env.NEXT_PUBLIC_TAP_PLUGIN_KEY,
|
|
162
|
+
isProd: process.env.NODE_ENV === 'production'
|
|
163
|
+
});
|
|
359
164
|
|
|
360
|
-
|
|
165
|
+
sdk.initChat({
|
|
166
|
+
chatApiParams: { /* ... */ }
|
|
167
|
+
});
|
|
361
168
|
|
|
362
|
-
|
|
169
|
+
return () => sdk.removeChat();
|
|
170
|
+
}, []);
|
|
363
171
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
clipId,
|
|
367
|
-
clipPlayHead,
|
|
368
|
-
}: {
|
|
369
|
-
clipId: string;
|
|
370
|
-
clipPlayHead: number;
|
|
371
|
-
})
|
|
172
|
+
return <div>Chat Widget will appear here</div>;
|
|
173
|
+
}
|
|
372
174
|
```
|
|
373
175
|
|
|
374
|
-
|
|
176
|
+
## Build Formats
|
|
375
177
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
```
|
|
178
|
+
- **ESM**: `dist/index.mjs` - Modern ES modules
|
|
179
|
+
- **CJS**: `dist/index.js` - CommonJS for Node.js
|
|
180
|
+
- **IIFE**: `dist/index.global.js` - Browser global variable
|
|
181
|
+
- **Types**: `dist/index.d.ts` - TypeScript declarations
|
|
381
182
|
|
|
382
|
-
##
|
|
183
|
+
## Browser Support
|
|
383
184
|
|
|
384
|
-
|
|
185
|
+
- Chrome 60+
|
|
186
|
+
- Firefox 60+
|
|
187
|
+
- Safari 12+
|
|
188
|
+
- Edge 79+
|
|
385
189
|
|
|
386
|
-
##
|
|
190
|
+
## License
|
|
387
191
|
|
|
388
|
-
|
|
192
|
+
MIT
|
|
389
193
|
|
|
390
|
-
Copyright (c) 2025-present, Coxwave
|
|
194
|
+
Copyright (c) 2025-present, Coxwave
|
package/dist/index.js
CHANGED
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
}
|
|
12
12
|
})();
|
|
13
13
|
|
|
14
|
-
'use strict';var
|
|
14
|
+
'use strict';var je=Object.defineProperty;var J=i=>{throw TypeError(i)};var $e=(i,t,e)=>t in i?je(i,t,{enumerable:true,configurable:true,writable:true,value:e}):i[t]=e;var u=(i,t,e)=>$e(i,typeof t!="symbol"?t+"":t,e),Z=(i,t,e)=>t.has(i)||J("Cannot "+e);var Y=(i,t,e)=>(Z(i,t,"read from private field"),e?e.call(i):t.get(i)),g=(i,t,e)=>t.has(i)?J("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(i):t.set(i,e);var d=(i,t,e)=>(Z(i,t,"access private method"),e);var Q="_1mlv4me2",w="_1mlv4me4";var O="_1mlv4me3";var D=class{constructor(){u(this,"chatBody",null);this.chatBody=null;}createChatBody({customChatBody:t}){return this.chatBody?this.chatBody:(this.chatBody=document.createElement("div"),this.chatBody.id="cw-chat-body",this.chatBody.className=Q,this.chatBody.style.setProperty("z-index","10000001","important"),this.chatBody.style.setProperty("position","fixed","important"),Object.assign(this.chatBody.style,{top:t?.position?.top??"50px",right:t?.position?.right??"24px",left:t?.position?.left??"unset",bottom:t?.position?.bottom??"unset",width:t?.width??"340px",height:t?.height??"calc(100% - 116px)",overflow:"hidden",backgroundColor:"transparent",borderRadius:t?.borderRadius??"16px",boxShadow:`
|
|
15
15
|
rgba(255, 255, 255, 0.12) 0px 0px 2px 0px inset,
|
|
16
16
|
rgba(0, 0, 0, 0.05) 0px 0px 2px 1px,
|
|
17
17
|
rgba(0, 0, 0, 0.3) 0px 12px 60px
|
|
18
|
-
`,willChange:"transform, opacity, width, max-height, max-width"}),document.body.appendChild(this.chatBody),this.chatBody)}toggleVisibility(t){if(!this.chatBody)return;this.chatBody.classList.remove(_,w),this.chatBody.style.display="block";let e=()=>{this.chatBody&&(this.chatBody.classList.contains(w)&&(this.chatBody.style.display="none"),this.chatBody.removeEventListener("animationend",e));};this.chatBody.addEventListener("animationend",e),requestAnimationFrame(()=>{this.chatBody?.classList.add(t?_:w);});}removeChatBody(){this.chatBody&&(this.chatBody.remove(),this.chatBody=null);}resizeChatBody(t,e){if(!this.chatBody)return;let i=e?.width??"340px",a=parseInt(i,10),o=a/3*10-a,n=t?`${a+o}px`:`${a}px`;this.chatBody.style.width=n;}},W=A;var G="_6j1ub51",L={default:"_6j1ub5b _6j1ub5a","call-to-action":"_6j1ub5c _6j1ub5a"},$="_6j1ub5a",q="_6j1ub59",P={default:"_6j1ub5e _6j1ub5d","call-to-action":"_6j1ub5f _6j1ub5d"},Y="_6j1ub5d",X="_6j1ub5h",J="_6j1ub5g",O="_6j1ub53",Z="_6j1ub58",S={default:"_6j1ub56 _6j1ub55","call-to-action":"_6j1ub57 _6j1ub55"},Q="_6j1ub55",H="_6j1ub52",ee="_6j1ub54";var c,te,ae,ie,re,se,j=class{constructor(){v(this,c);r(this,"container");r(this,"alarmTimeout");r(this,"alarmCornerSVG");r(this,"textContainer");r(this,"circleElement");r(this,"textInTextContainer");r(this,"messageInfo");}render({rootElement:t}){this.container=document.createElement("div"),this.container.id="alarm-container",this.container.className=G,this.container.addEventListener("click",i=>{i.stopPropagation();}),t.appendChild(this.container),g(this,c,te).call(this,this.container);let e=g(this,c,ae).call(this,this.container);g(this,c,re).call(this,e),g(this,c,ie).call(this,e);}fadeIn(t){t.type==="default"||t.type==="hourSpent"?(this.textContainer.className=S.default,this.alarmCornerSVG.setAttribute("class",L.default),this.circleElement.className=P.default):(this.textContainer.className=S["call-to-action"],this.alarmCornerSVG.setAttribute("class",L["call-to-action"]),this.circleElement.className=P["call-to-action"]),this.messageInfo=t,this.textInTextContainer.textContent=t.message,this.toggleVisibility(true),this.alarmTimeout=setTimeout(()=>{this.toggleVisibility(false);},18*1e3);}addClickEvent({callback:t}){this.container.addEventListener("click",()=>{this.toggleVisibility(false),t(this.messageInfo);});}toggleVisibility(t){this.container.classList.remove(H,O),requestAnimationFrame(()=>{this.container?.classList.add(t?H:O);});}remove(){this.container&&this.toggleVisibility(false),this.alarmTimeout&&clearTimeout(this.alarmTimeout);}};c=new WeakSet,te=function(t){let e=document.createElement("div");e.className=q,t.appendChild(e);let i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("width","11"),i.setAttribute("height","8"),i.setAttribute("viewBox","0 0 11 8"),i.setAttribute("fill","currentColor"),i.setAttribute("class",$);let a=document.createElementNS("http://www.w3.org/2000/svg","path");a.setAttribute("d","M5.5 0L11.1292 8.25H-0.129165L5.5 0Z"),a.setAttribute("fill","currentColor"),i.appendChild(a),this.alarmCornerSVG=i,e.appendChild(i);},ae=function(t){let e=document.createElement("div");return e.className=ee,t.appendChild(e),e},ie=function(t){this.textContainer=document.createElement("div"),this.textContainer.className=Q,t.appendChild(this.textContainer),this.textInTextContainer=document.createElement("span"),this.textInTextContainer.className=Z,this.textContainer.appendChild(this.textInTextContainer);},re=function(t){let e=document.createElement("div");e.className=Y,t.appendChild(e),e.addEventListener("click",a=>{a.stopPropagation(),this.remove();});let i=document.createElement("span");i.className=X,e.appendChild(i),i.textContent="\uC54C\uB9BC \uB044\uAE30",g(this,c,se).call(this,e),this.circleElement=e;},se=function(t){let e=document.createElementNS("http://www.w3.org/2000/svg","svg");e.setAttribute("width","10"),e.setAttribute("height","10"),e.setAttribute("viewBox","0 0 14 14"),e.setAttribute("fill","none"),e.setAttribute("class",J);let i=document.createElementNS("http://www.w3.org/2000/svg","path");i.setAttribute("d","M1 1L13 13M13 1L1 13"),i.setAttribute("stroke","currentColor"),i.setAttribute("stroke-width","2"),i.setAttribute("stroke-linecap","round"),e.appendChild(i),t.appendChild(e);};var ne=j;var C,F=class{constructor(){r(this,"customFloatingButton");r(this,"floatingButton");r(this,"alarm");v(this,C,(t,e)=>t.key===e?true:t.code.startsWith("Key")?t.code.slice(3).toLowerCase()===e:false);this.alarm=new ne;}render({customFloatingButton:t}){if(this.customFloatingButton=t,this.customFloatingButton?.isInElement&&this.customFloatingButton?.parentElementId){let e=document.getElementById(this.customFloatingButton.parentElementId);e?.style.setProperty("position","relative","important"),e?.style.setProperty("z-index","10000001","important"),this.floatingButton=e;}else {let e=document.getElementById("cw-plugin");e||(e=document.createElement("button"),e.id="cw-plugin",e.style.zIndex="10000001",e.style.setProperty("z-index","10000001","important"),e.style.setProperty("position","fixed","important"),e.style.width="50px",e.style.height="50px",e.style.borderRadius="50%",e.style.backgroundColor="#000",document.body.appendChild(e),this.floatingButton=e);}return this.alarm.render({rootElement:this.floatingButton}),this.floatingButton}addClickEvent({callback:t}){if(!this.floatingButton)throw new Error("not initialized");this.floatingButton.addEventListener("click",()=>{t();});}addAlarmClickEvent({callback:t}){this.alarm.addClickEvent({callback:t});}addShortCutEvent({openChatShortcutKey:t,callback:e}){if(!this.floatingButton)throw new Error("not initialized");window.addEventListener("keydown",i=>{K(this,C).call(this,i,t.key)&&(!t.modifier||i[t.modifier])&&e();});}alarmFadeIn(t){this.alarm.fadeIn(t);}alarmRemove(){this.alarm.remove();}};C=new WeakMap;var oe=F;var le="chat:init",Ee="chat:initiated";var de=d__namespace.object({type:d__namespace.literal(Ee),gaId:d__namespace.string()}),pe=d__namespace.object({type:d__namespace.literal("GA_EVENT"),payload:d__namespace.record(d__namespace.string(),d__namespace.any())});var E=class{constructor(){r(this,"listeners",new Map);r(this,"unifiedMessageHandler",null);}on(t,e){let i=o=>{if(this.isValidOrigin(o))try{let n=o.data,p=typeof n=="string"?JSON.parse(n):n,{type:u}=p;u===t&&e(p);}catch(n){console.warn("Messenger: Failed to parse message data",n);}},a=this.listeners.get(t)||[];return a.push(i),this.listeners.set(t,a),this.unifiedMessageHandler||(this.unifiedMessageHandler=o=>{this.listeners.forEach(n=>n.forEach(p=>p(o)));},window.addEventListener("message",this.unifiedMessageHandler)),()=>{this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}}removeListener(t){this.listeners.delete(t);}removeAllListeners(){this.listeners.clear(),this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}postMessage(t){try{let e=this.getMessageTarget();return e?(e.postMessage(t,this.getTargetOrigin()),!0):(console.warn("Messenger: Message target not available"),!1)}catch(e){return console.error("Messenger: postMessage failed",e),false}}};var f=class extends Error{constructor(e,i,a){super(`Handshake failed: ${e}${i?` - ${i}`:""}`);this.reason=e;this.details=i;this.originalError=a;this.name="HandshakeError";}},M=class{constructor(t,e,i){this.getTargetWindow=t;this.getTargetOrigin=e;this.isValidOrigin=i;r(this,"abortController",null);r(this,"messageListener",null);}async execute(t,e={}){let{timeout:i=1e4,maxRetries:a=10,retryInterval:o=500}=e;return this.cancel(),this.abortController=new AbortController,new Promise((n,p)=>{let u=0,y,m=()=>{y&&clearTimeout(y),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null);},b=()=>{m(),p(new f("TIMEOUT","Handshake was cancelled"));};this.abortController?.signal.addEventListener("abort",b),this.messageListener=l=>{if(this.isValidOrigin(l))try{let x=l.data,be=typeof x=="string"?JSON.parse(x):x;try{let U=d__namespace.safeParse(de,be);m(),this.abortController=null,n(U.output);return}catch{}}catch(x){console.warn("Failed to parse handshake message:",x);}},window.addEventListener("message",this.messageListener),y=setTimeout(()=>{m(),this.abortController=null,p(new f("TIMEOUT",`No valid response received within ${i}ms`));},i);let h=()=>{if(!this.abortController?.signal.aborted)try{let l=this.getTargetWindow();if(!l)throw new f("NO_TARGET_WINDOW","Target iframe window is not available");l.postMessage(t,this.getTargetOrigin()),u++,u<a&&setTimeout(()=>{this.abortController?.signal.aborted||h();},o);}catch(l){m(),this.abortController=null,l instanceof f?p(l):p(new f("MESSAGE_SEND_FAILED","Failed to send handshake message",l));}};h();})}cancel(){this.abortController&&(this.abortController.abort(),this.abortController=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null);}isActive(){return this.abortController!==null&&!this.abortController.signal.aborted}};var B=class extends E{constructor({hostClientUrl:e,pluginKey:i}){super();r(this,"hostClientUrl");r(this,"pluginKey");r(this,"iframe");r(this,"listenToTap",super.on);this.hostClientUrl=e,this.pluginKey=i;}isValidOrigin(e){if(!this.iframe)return false;let i=e.origin,a=new URL(this.iframe.src).origin;return !!(i===a||i.includes("vercel.app")&&a.includes("vercel.app")||i.includes("localhost")&&a.includes("localhost"))}getMessageTarget(){return this.iframe?.contentWindow||null}getTargetOrigin(){if(!this.iframe?.src)return "*";try{return new URL(this.iframe.src).origin}catch{return "*"}}renderIframe({chatBody:e,isProd:i,isLocal:a}){return new Promise(o=>{this.iframe=document.createElement("iframe"),this.iframe.style.setProperty("display","flex","important"),this.iframe.style.setProperty("border","none","important"),a?this.iframe.src=`${this.hostClientUrl}/chat`:this.iframe.src="https://ax-tap-fe-staging.vercel.app/chat",this.iframe.style.width="100%",this.iframe.style.height="100%",this.iframe.onload=()=>o(this.iframe),e.appendChild(this.iframe);})}hasIframe(){return !!this.iframe}removeIframe(){this.iframe?.remove(),this.iframe=null,this.removeAllListeners();}get postToTap(){return this.iframe||console.warn("TapIframeBridge: iframe not found"),super.postMessage}async performHandshake(e,i){if(!this.iframe)throw new Error("TapIframeBridge: iframe not available for handshake");let a=new M(()=>this.getMessageTarget(),()=>this.getTargetOrigin(),n=>this.isValidOrigin(n)),o={type:le,hostClientUrl:this.hostClientUrl,pluginKey:this.pluginKey,chatApiParams:e.chatApiParams,theme:e.customStyles};try{return await a.execute(o,i)}catch(n){throw n instanceof Error?new Error(`TapIframeBridge handshake failed: ${n.message}`):n}}};var I=class{constructor(t){this.iframeBridge=t;}onTimelineSeek(t){this.iframeBridge.listenToTap("timeline:seek",e=>t(e.clipPlayHead,e.clipId));}onChatOpened(t){this.iframeBridge.listenToTap("chat:opened",t);}onChatClosed(t){this.iframeBridge.listenToTap("chat:closed",t);}onChatInitiated(t){this.iframeBridge.listenToTap("chat:initiated",t);}onAlarmFadeIn(t){this.iframeBridge.listenToTap("alarm:fadeIn",e=>{t(e.messageInfo);});}onPopUpOpen(t){this.iframeBridge.listenToTap("popUp:open",e=>{t(e.popUpInfo);});}onPdfOpen(t){this.iframeBridge.listenToTap("pdf:open",t);}onPdfClose(t){this.iframeBridge.listenToTap("pdf:close",t);}};var he="wu2gm66",me="wu2gm67",ge="wu2gm68";function Be({htmlString:s,callback:t,customStyles:e}){let i=document.createElement("div");i.style.position="fixed",i.style.top="0",i.style.left="0",i.style.width="100vw",i.style.height="100vh",i.style.background="rgba(0, 0, 0, 0.4)",i.style.zIndex="10000002";let a=document.createElement("div");a.style.position="fixed",a.style.display="flex",a.style.flexDirection="column";let n=15;if(e?.width){let h=parseFloat(e.width),l=e.width.match(/[a-zA-Z%]+/)?.[0];!isNaN(h)&&l==="px"&&(n+=h);}else n+=340;if(e?.position?.right){let h=parseFloat(e?.position?.right),l=e?.position?.right.match(/[a-zA-Z%]+/)?.[0];!isNaN(h)&&l==="px"&&(n+=h);}else n=n+24;a.style.top=e?.position?.top??"50px",a.style.right=`${n}px`,a.style.left=e?.position?.left??"unset",a.style.bottom=e?.position?.bottom??"unset",a.style.maxWidth="calc(100vw - 100px)",a.style.maxHeight=e?.height??"calc(100vh - 116px)",a.style.overflow="auto",a.style.background="#fff",a.style.padding="20px",a.style.border="1px solid #ccc",a.style.boxShadow="0 4px 20px rgba(0,0,0,0.2)",a.style.zIndex="10000003",a.style.borderRadius="8px";let p=document.createElement("div");p.innerHTML=s,i.addEventListener("click",()=>{document.body.removeChild(i),document.body.removeChild(a),t();}),a.addEventListener("click",h=>{h.stopPropagation();}),a.appendChild(p),document.body.appendChild(i),document.body.appendChild(a);let u=document.querySelector(`.${he}`),y=document.querySelector(".cw-plugin-code-block"),m=document.querySelector(`.${ge}`),b=document.querySelector(`.${me}`);u&&y&&m&&b&&u.addEventListener("click",()=>{navigator.clipboard.writeText(y.textContent??""),m.style.display="none",b.textContent="\uBCF5\uC0AC\uB428",setTimeout(()=>{b.textContent="\uBCF5\uC0AC",m.style.display="inline";},1e3);});}var ue=Be;var T=class T{constructor({gaId:t}){T.isInitialized||(this.init(t),T.isInitialized=true);}init(t){if(!document.querySelector(`script[src="https://www.googletagmanager.com/gtag/js?id=${t}"]`)){let e=document.createElement("script");e.async=true,e.src=`https://www.googletagmanager.com/gtag/js?id=${t}`,document.head.appendChild(e);}if(typeof window.gtag!="function"){let e=document.createElement("script");e.innerHTML=`
|
|
18
|
+
`,willChange:"transform, opacity, width, max-height, max-width"}),document.body.appendChild(this.chatBody),this.chatBody)}toggleVisibility(t){if(!this.chatBody)return;this.chatBody.classList.remove(O,w),this.chatBody.style.display="block";let e=()=>{this.chatBody&&(this.chatBody.classList.contains(w)&&(this.chatBody.style.display="none"),this.chatBody.removeEventListener("animationend",e));};this.chatBody.addEventListener("animationend",e),requestAnimationFrame(()=>{this.chatBody?.classList.add(t?O:w);});}removeChatBody(){this.chatBody&&(this.chatBody.remove(),this.chatBody=null);}resizeChatBody(t,e){if(!this.chatBody)return;let n=e?.width??"340px",r=parseInt(n,10),o=r/3*10-r,s=t?`${r+o}px`:`${r}px`;this.chatBody.style.width=s;}},ee=D;var te="_6j1ub51",P={default:"_6j1ub5b _6j1ub5a","call-to-action":"_6j1ub5c _6j1ub5a"},ne="_6j1ub5a",re="_6j1ub59",L={default:"_6j1ub5e _6j1ub5d","call-to-action":"_6j1ub5f _6j1ub5d"},ie="_6j1ub5d",se="_6j1ub5h",ue="_6j1ub5g",S="_6j1ub53",oe="_6j1ub58",N={default:"_6j1ub56 _6j1ub55","call-to-action":"_6j1ub57 _6j1ub55"},ae="_6j1ub55",q="_6j1ub52",le="_6j1ub54";var h,ce,pe,fe,ye,he,R=class{constructor(){g(this,h);u(this,"container");u(this,"alarmTimeout");u(this,"alarmCornerSVG");u(this,"textContainer");u(this,"circleElement");u(this,"textInTextContainer");u(this,"messageInfo");}render({rootElement:t}){this.container=document.createElement("div"),this.container.id="alarm-container",this.container.className=te,this.container.addEventListener("click",n=>{n.stopPropagation();}),t.appendChild(this.container),d(this,h,ce).call(this,this.container);let e=d(this,h,pe).call(this,this.container);d(this,h,ye).call(this,e),d(this,h,fe).call(this,e);}fadeIn(t){t.type==="default"||t.type==="hourSpent"?(this.textContainer.className=N.default,this.alarmCornerSVG.setAttribute("class",P.default),this.circleElement.className=L.default):(this.textContainer.className=N["call-to-action"],this.alarmCornerSVG.setAttribute("class",P["call-to-action"]),this.circleElement.className=L["call-to-action"]),this.messageInfo=t,this.textInTextContainer.textContent=t.message,this.toggleVisibility(true),this.alarmTimeout=setTimeout(()=>{this.toggleVisibility(false);},18*1e3);}addClickEvent({callback:t}){this.container.addEventListener("click",()=>{this.toggleVisibility(false),t(this.messageInfo);});}toggleVisibility(t){this.container.classList.remove(q,S),requestAnimationFrame(()=>{this.container?.classList.add(t?q:S);});}remove(){this.container&&this.toggleVisibility(false),this.alarmTimeout&&clearTimeout(this.alarmTimeout);}};h=new WeakSet,ce=function(t){let e=document.createElement("div");e.className=re,t.appendChild(e);let n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width","11"),n.setAttribute("height","8"),n.setAttribute("viewBox","0 0 11 8"),n.setAttribute("fill","currentColor"),n.setAttribute("class",ne);let r=document.createElementNS("http://www.w3.org/2000/svg","path");r.setAttribute("d","M5.5 0L11.1292 8.25H-0.129165L5.5 0Z"),r.setAttribute("fill","currentColor"),n.appendChild(r),this.alarmCornerSVG=n,e.appendChild(n);},pe=function(t){let e=document.createElement("div");return e.className=le,t.appendChild(e),e},fe=function(t){this.textContainer=document.createElement("div"),this.textContainer.className=ae,t.appendChild(this.textContainer),this.textInTextContainer=document.createElement("span"),this.textInTextContainer.className=oe,this.textContainer.appendChild(this.textInTextContainer);},ye=function(t){let e=document.createElement("div");e.className=ie,t.appendChild(e),e.addEventListener("click",r=>{r.stopPropagation(),this.remove();});let n=document.createElement("span");n.className=se,e.appendChild(n),n.textContent="\uC54C\uB9BC \uB044\uAE30",d(this,h,he).call(this,e),this.circleElement=e;},he=function(t){let e=document.createElementNS("http://www.w3.org/2000/svg","svg");e.setAttribute("width","10"),e.setAttribute("height","10"),e.setAttribute("viewBox","0 0 14 14"),e.setAttribute("fill","none"),e.setAttribute("class",ue);let n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("d","M1 1L13 13M13 1L1 13"),n.setAttribute("stroke","currentColor"),n.setAttribute("stroke-width","2"),n.setAttribute("stroke-linecap","round"),e.appendChild(n),t.appendChild(e);};var me=R;var _,z=class{constructor(){u(this,"customFloatingButton");u(this,"floatingButton");u(this,"alarm");g(this,_,(t,e)=>t.key===e?true:t.code.startsWith("Key")?t.code.slice(3).toLowerCase()===e:false);this.alarm=new me;}render({customFloatingButton:t}){if(this.customFloatingButton=t,this.customFloatingButton?.isInElement&&this.customFloatingButton?.parentElementId){let e=document.getElementById(this.customFloatingButton.parentElementId);e?.style.setProperty("position","relative","important"),e?.style.setProperty("z-index","10000001","important"),this.floatingButton=e;}else {let e=document.getElementById("cw-plugin");e||(e=document.createElement("button"),e.id="cw-plugin",e.style.zIndex="10000001",e.style.setProperty("z-index","10000001","important"),e.style.setProperty("position","fixed","important"),e.style.width="50px",e.style.height="50px",e.style.borderRadius="50%",e.style.backgroundColor="#000",document.body.appendChild(e),this.floatingButton=e);}return this.alarm.render({rootElement:this.floatingButton}),this.floatingButton}addClickEvent({callback:t}){if(!this.floatingButton)throw new Error("not initialized");this.floatingButton.addEventListener("click",()=>{t();});}addAlarmClickEvent({callback:t}){this.alarm.addClickEvent({callback:t});}addShortCutEvent({openChatShortcutKey:t,callback:e}){if(!this.floatingButton)throw new Error("not initialized");window.addEventListener("keydown",n=>{Y(this,_).call(this,n,t.key)&&(!t.modifier||n[t.modifier])&&e();});}alarmFadeIn(t){this.alarm.fadeIn(t);}alarmRemove(){this.alarm.remove();}};_=new WeakMap;var de=z;var F;function H(i){return {lang:i?.lang??F?.lang,message:i?.message,abortEarly:i?.abortEarly??F?.abortEarly,abortPipeEarly:i?.abortPipeEarly??F?.abortPipeEarly}}var De;function Pe(i){return De?.get(i)}var Le;function Se(i){return Le?.get(i)}var Ne;function qe(i,t){return Ne?.get(i)?.get(t)}function ve(i){let t=typeof i;return t==="string"?`"${i}"`:t==="number"||t==="bigint"||t==="boolean"?`${i}`:t==="object"||t==="function"?(i&&Object.getPrototypeOf(i)?.constructor?.name)??"null":t}function k(i,t,e,n,r){let o=r&&"input"in r?r.input:e.value,s=r?.expected??i.expects??null,c=r?.received??ve(o),a={kind:i.kind,type:i.type,input:o,expected:s,received:c,message:`Invalid ${t}: ${s?`Expected ${s} but r`:"R"}eceived ${c}`,requirement:i.requirement,path:r?.path,issues:r?.issues,lang:n.lang,abortEarly:n.abortEarly,abortPipeEarly:n.abortPipeEarly},p=i.kind==="schema",l=r?.message??i.message??qe(i.reference,a.lang)??(p?Se(a.lang):null)??n.message??Pe(a.lang);l!==void 0&&(a.message=typeof l=="function"?l(a):l),p&&(e.typed=false),e.issues?e.issues.push(a):e.issues=[a];}function x(i){return {version:1,vendor:"valibot",validate(t){return i["~run"]({value:t},H())}}}function Re(i,t){return Object.hasOwn(i,t)&&t!=="__proto__"&&t!=="prototype"&&t!=="constructor"}var ze=class extends Error{constructor(i){super(i[0].message),this.name="ValiError",this.issues=i;}};function Fe(i,t,e){return typeof i.fallback=="function"?i.fallback(t,e):i.fallback}function He(i,t,e){return typeof i.default=="function"?i.default(t,e):i.default}function G(){return {kind:"schema",type:"any",reference:G,expects:"any",async:false,get"~standard"(){return x(this)},"~run"(i){return i.typed=true,i}}}function T(i,t){return {kind:"schema",type:"literal",reference:T,expects:ve(i),async:false,literal:i,message:t,get"~standard"(){return x(this)},"~run"(e,n){return e.value===this.literal?e.typed=true:k(this,"type",e,n),e}}}function I(i,t){return {kind:"schema",type:"object",reference:I,expects:"Object",async:false,entries:i,message:t,get"~standard"(){return x(this)},"~run"(e,n){let r=e.value;if(r&&typeof r=="object"){e.typed=true,e.value={};for(let o in this.entries){let s=this.entries[o];if(o in r||(s.type==="exact_optional"||s.type==="optional"||s.type==="nullish")&&s.default!==void 0){let c=o in r?r[o]:He(s),a=s["~run"]({value:c},n);if(a.issues){let p={type:"object",origin:"value",input:r,key:o,value:c};for(let l of a.issues)l.path?l.path.unshift(p):l.path=[p],e.issues?.push(l);if(e.issues||(e.issues=a.issues),n.abortEarly){e.typed=false;break}}a.typed||(e.typed=false),e.value[o]=a.value;}else if(s.fallback!==void 0)e.value[o]=Fe(s);else if(s.type!=="exact_optional"&&s.type!=="optional"&&s.type!=="nullish"&&(k(this,"key",e,n,{input:void 0,expected:`"${o}"`,path:[{type:"object",origin:"key",input:r,key:o,value:r[o]}]}),n.abortEarly))break}}else k(this,"type",e,n);return e}}}function V(i,t,e){return {kind:"schema",type:"record",reference:V,expects:"Object",async:false,key:i,value:t,message:e,get"~standard"(){return x(this)},"~run"(n,r){let o=n.value;if(o&&typeof o=="object"){n.typed=true,n.value={};for(let s in o)if(Re(o,s)){let c=o[s],a=this.key["~run"]({value:s},r);if(a.issues){let l={type:"object",origin:"key",input:o,key:s,value:c};for(let f of a.issues)f.path=[l],n.issues?.push(f);if(n.issues||(n.issues=a.issues),r.abortEarly){n.typed=false;break}}let p=this.value["~run"]({value:c},r);if(p.issues){let l={type:"object",origin:"value",input:o,key:s,value:c};for(let f of p.issues)f.path?f.path.unshift(l):f.path=[l],n.issues?.push(f);if(n.issues||(n.issues=p.issues),r.abortEarly){n.typed=false;break}}(!a.typed||!p.typed)&&(n.typed=false),a.typed&&(n.value[a.value]=p.value);}}else k(this,"type",n,r);return n}}}function C(i){return {kind:"schema",type:"string",reference:C,expects:"string",async:false,message:i,get"~standard"(){return x(this)},"~run"(t,e){return typeof t.value=="string"?t.typed=true:k(this,"type",t,e),t}}}function ge(i,t,e){let n=i["~run"]({value:t},H(e));if(n.issues)throw new ze(n.issues);return n.value}function be(i,t,e){let n=i["~run"]({value:t},H(e));return {typed:n.typed,success:!n.issues,output:n.value,issues:n.issues}}var ke="chat:init",Ge="chat:initiated";var xe=I({type:T(Ge),gaId:C()}),Ee=I({type:T("GA_EVENT"),payload:V(C(),G())});var A=class{constructor(){u(this,"listeners",new Map);u(this,"unifiedMessageHandler",null);}on(t,e){let n=o=>{if(this.isValidOrigin(o))try{let s=o.data,c=typeof s=="string"?JSON.parse(s):s,{type:a}=c;a===t&&e(c);}catch(s){console.warn("Messenger: Failed to parse message data",s);}},r=this.listeners.get(t)||[];return r.push(n),this.listeners.set(t,r),this.unifiedMessageHandler||(this.unifiedMessageHandler=o=>{this.listeners.forEach(s=>s.forEach(c=>c(o)));},window.addEventListener("message",this.unifiedMessageHandler)),()=>{this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}}removeListener(t){this.listeners.delete(t);}removeAllListeners(){this.listeners.clear(),this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}postMessage(t){try{let e=this.getMessageTarget();return e?(e.postMessage(t,this.getTargetOrigin()),!0):(console.warn("Messenger: Message target not available"),!1)}catch(e){return console.error("Messenger: postMessage failed",e),false}}};var v=class extends Error{constructor(e,n,r){super(`Handshake failed: ${e}${n?` - ${n}`:""}`);this.reason=e;this.details=n;this.originalError=r;this.name="HandshakeError";}},M=class{constructor(t,e,n){this.getTargetWindow=t;this.getTargetOrigin=e;this.isValidOrigin=n;u(this,"abortController",null);u(this,"messageListener",null);}async execute(t,e={}){let{timeout:n=1e4,maxRetries:r=10,retryInterval:o=500}=e;return this.cancel(),this.abortController=new AbortController,new Promise((s,c)=>{let a=0,p,l=()=>{p&&clearTimeout(p),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null);},f=()=>{l(),c(new v("TIMEOUT","Handshake was cancelled"));};this.abortController?.signal.addEventListener("abort",f),this.messageListener=y=>{if(this.isValidOrigin(y))try{let b=y.data,Me=typeof b=="string"?JSON.parse(b):b;try{let K=be(xe,Me);l(),this.abortController=null,s(K.output);return}catch{}}catch(b){console.warn("Failed to parse handshake message:",b);}},window.addEventListener("message",this.messageListener),p=setTimeout(()=>{l(),this.abortController=null,c(new v("TIMEOUT",`No valid response received within ${n}ms`));},n);let m=()=>{if(!this.abortController?.signal.aborted)try{let y=this.getTargetWindow();if(!y)throw new v("NO_TARGET_WINDOW","Target iframe window is not available");y.postMessage(t,this.getTargetOrigin()),a++,a<r&&setTimeout(()=>{this.abortController?.signal.aborted||m();},o);}catch(y){l(),this.abortController=null,y instanceof v?c(y):c(new v("MESSAGE_SEND_FAILED","Failed to send handshake message",y));}};m();})}cancel(){this.abortController&&(this.abortController.abort(),this.abortController=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null);}isActive(){return this.abortController!==null&&!this.abortController.signal.aborted}};var j=class extends A{constructor({hostClientUrl:e,pluginKey:n}){super();u(this,"hostClientUrl");u(this,"pluginKey");u(this,"iframe");u(this,"listenToTap",super.on);this.hostClientUrl=e,this.pluginKey=n;}isValidOrigin(e){if(!this.iframe)return false;let n=e.origin,r=new URL(this.iframe.src).origin;return !!(n===r||n.includes("vercel.app")&&r.includes("vercel.app")||n.includes("localhost")&&r.includes("localhost"))}getMessageTarget(){return this.iframe?.contentWindow||null}getTargetOrigin(){if(!this.iframe?.src)return "*";try{return new URL(this.iframe.src).origin}catch{return "*"}}renderIframe({chatBody:e,isProd:n,isLocal:r}){return new Promise(o=>{this.iframe=document.createElement("iframe"),this.iframe.style.setProperty("display","flex","important"),this.iframe.style.setProperty("border","none","important"),r?this.iframe.src=`${this.hostClientUrl}/chat`:this.iframe.src="https://ax-tap-fe-staging.vercel.app/chat",this.iframe.style.width="100%",this.iframe.style.height="100%",this.iframe.onload=()=>o(this.iframe),e.appendChild(this.iframe);})}hasIframe(){return !!this.iframe}removeIframe(){this.iframe?.remove(),this.iframe=null,this.removeAllListeners();}get postToTap(){return this.iframe||console.warn("TapIframeBridge: iframe not found"),super.postMessage}async performHandshake(e,n){if(!this.iframe)throw new Error("TapIframeBridge: iframe not available for handshake");let r=new M(()=>this.getMessageTarget(),()=>this.getTargetOrigin(),s=>this.isValidOrigin(s)),o={type:ke,hostClientUrl:this.hostClientUrl,pluginKey:this.pluginKey,chatApiParams:e.chatApiParams,theme:e.customStyles};try{return await r.execute(o,n)}catch(s){throw s instanceof Error?new Error(`TapIframeBridge handshake failed: ${s.message}`):s}}};var $=class{constructor(t){this.iframeBridge=t;}onTimelineSeek(t){this.iframeBridge.listenToTap("timeline:seek",e=>t(e.clipPlayHead,e.clipId));}onChatOpened(t){this.iframeBridge.listenToTap("chat:opened",t);}onChatClosed(t){this.iframeBridge.listenToTap("chat:closed",t);}onChatInitiated(t){this.iframeBridge.listenToTap("chat:initiated",t);}onAlarmFadeIn(t){this.iframeBridge.listenToTap("alarm:fadeIn",e=>{t(e.messageInfo);});}onPopUpOpen(t){this.iframeBridge.listenToTap("popUp:open",e=>{t(e.popUpInfo);});}onPdfOpen(t){this.iframeBridge.listenToTap("pdf:open",t);}onPdfClose(t){this.iframeBridge.listenToTap("pdf:close",t);}};var we="wu2gm66",_e="wu2gm67",Te="wu2gm68";function Ue({htmlString:i,callback:t,customStyles:e}){let n=document.createElement("div");n.style.position="fixed",n.style.top="0",n.style.left="0",n.style.width="100vw",n.style.height="100vh",n.style.background="rgba(0, 0, 0, 0.4)",n.style.zIndex="10000002";let r=document.createElement("div");r.style.position="fixed",r.style.display="flex",r.style.flexDirection="column";let s=15;if(e?.width){let m=parseFloat(e.width),y=e.width.match(/[a-zA-Z%]+/)?.[0];!isNaN(m)&&y==="px"&&(s+=m);}else s+=340;if(e?.position?.right){let m=parseFloat(e?.position?.right),y=e?.position?.right.match(/[a-zA-Z%]+/)?.[0];!isNaN(m)&&y==="px"&&(s+=m);}else s=s+24;r.style.top=e?.position?.top??"50px",r.style.right=`${s}px`,r.style.left=e?.position?.left??"unset",r.style.bottom=e?.position?.bottom??"unset",r.style.maxWidth="calc(100vw - 100px)",r.style.maxHeight=e?.height??"calc(100vh - 116px)",r.style.overflow="auto",r.style.background="#fff",r.style.padding="20px",r.style.border="1px solid #ccc",r.style.boxShadow="0 4px 20px rgba(0,0,0,0.2)",r.style.zIndex="10000003",r.style.borderRadius="8px";let c=document.createElement("div");c.innerHTML=i,n.addEventListener("click",()=>{document.body.removeChild(n),document.body.removeChild(r),t();}),r.addEventListener("click",m=>{m.stopPropagation();}),r.appendChild(c),document.body.appendChild(n),document.body.appendChild(r);let a=document.querySelector(`.${we}`),p=document.querySelector(".cw-plugin-code-block"),l=document.querySelector(`.${Te}`),f=document.querySelector(`.${_e}`);a&&p&&l&&f&&a.addEventListener("click",()=>{navigator.clipboard.writeText(p.textContent??""),l.style.display="none",f.textContent="\uBCF5\uC0AC\uB428",setTimeout(()=>{f.textContent="\uBCF5\uC0AC",l.style.display="inline";},1e3);});}var Ie=Ue;var E=class E{constructor({gaId:t}){E.isInitialized||(this.init(t),E.isInitialized=true);}init(t){if(!document.querySelector(`script[src="https://www.googletagmanager.com/gtag/js?id=${t}"]`)){let e=document.createElement("script");e.async=true,e.src=`https://www.googletagmanager.com/gtag/js?id=${t}`,document.head.appendChild(e);}if(typeof window.gtag!="function"){let e=document.createElement("script");e.innerHTML=`
|
|
19
19
|
window.dataLayer = window.dataLayer || [];
|
|
20
20
|
function gtag(){dataLayer.push(arguments);}
|
|
21
21
|
gtag('js', new Date());
|
|
22
22
|
gtag('config', '${t}');
|
|
23
|
-
`,document.head.appendChild(e);}window.addEventListener("message",e=>{try{let
|
|
23
|
+
`,document.head.appendChild(e);}window.addEventListener("message",e=>{try{let n=typeof e.data=="string"?JSON.parse(e.data):e.data,r=ge(Ee,n);typeof window.gtag=="function"&&window.gtag("event",r.payload.action??"click",{event_category:r.payload.category??"Default",event_label:r.payload.label,value:r.payload.value,fastCampus_user_id:r.payload.fastCampus_user_id,course_id:r.payload.course_id,...r.payload});}catch{}});}};u(E,"isInitialized",false);var W=E,Ce=W;var B,Ae,X=class{constructor({pluginKey:t,isProd:e=false,isLocal:n=false}){g(this,B);u(this,"pluginKey");u(this,"iframeBridge");u(this,"events");u(this,"chatBody",null);u(this,"chatBodyMaker");u(this,"floatingButtonMaker");u(this,"shortcutKey",{openChat:{key:"/",modifier:""},sendChat:{key:"Enter",modifier:""}});u(this,"isProd");u(this,"isLocal");u(this,"isOpen");u(this,"isPdfOpen");this.pluginKey=t,this.iframeBridge=new j({hostClientUrl:window.location.origin,pluginKey:this.pluginKey}),this.events=new $(this.iframeBridge),this.floatingButtonMaker=new de,this.chatBodyMaker=new ee,this.isProd=e,this.isLocal=n,this.isOpen=false,this.isPdfOpen=false;}setIsOpen(t){this.isOpen=t;}setIsPdfOpen(t){this.isPdfOpen=t;}seekTimeline({clipId:t,clipPlayHead:e}){this.iframeBridge.postToTap({type:"timeline:seek",clipId:t,clipPlayHead:e});}async initChat({chatApiParams:t,customStyles:e,shortcutKey:n}){if(!d(this,B,Ae).call(this))throw new Error("not client");this.shortcutKey={openChat:n?.openChat??this.shortcutKey.openChat,sendChat:n?.sendChat??this.shortcutKey.sendChat},this.chatBody||(this.chatBody=this.chatBodyMaker.createChatBody({...e?.chatBody&&{customChatBody:e.chatBody}})),this.iframeBridge.hasIframe()||await this.iframeBridge.renderIframe({chatBody:this.chatBody,isProd:this.isProd,isLocal:this.isLocal});try{let r=await this.iframeBridge.performHandshake({chatApiParams:t,customStyles:e},{retryInterval:500,maxRetries:10,timeout:1e4});new Ce({gaId:r.gaId});}catch(r){throw console.error("Handshake failed:",r),new Error(`Chat initialization failed: ${r instanceof Error?r.message:"Unknown error"}`)}this.floatingButtonMaker.render({...e?.floatingButton&&{customFloatingButton:e.floatingButton}}),this.floatingButtonMaker.addClickEvent({callback:()=>{this.iframeBridge.postToTap({type:this.isOpen?"chat:close":"chat:open"});}}),this.floatingButtonMaker.addAlarmClickEvent({callback:r=>{this.iframeBridge.postToTap({type:"chat:open",isAlarm:true}),this.iframeBridge.postToTap({type:"alarm:click",messageInfo:r});}}),this.iframeBridge.listenToTap("chat:opened",()=>{this.setIsOpen(true),this.chatBodyMaker.toggleVisibility(this.isOpen),this.floatingButtonMaker.alarmRemove();}),this.iframeBridge.listenToTap("chat:closed",()=>{this.setIsOpen(false),this.chatBodyMaker.toggleVisibility(this.isOpen);}),this.iframeBridge.listenToTap("alarm:fadeIn",r=>{this.isOpen||this.floatingButtonMaker.alarmFadeIn(r.messageInfo);}),this.iframeBridge.listenToTap("popUp:open",r=>{Ie({htmlString:r.popUpInfo.html,callback:()=>this.iframeBridge.postToTap({type:"popUp:close"}),...e?.chatBody&&{customStyles:e.chatBody}});}),this.iframeBridge.listenToTap("pdf:open",()=>{this.setIsPdfOpen(true),this.chatBodyMaker.resizeChatBody(this.isPdfOpen,e?.chatBody),this.iframeBridge.postToTap({type:"pdf:enlarged"});}),this.iframeBridge.listenToTap("pdf:close",()=>{this.setIsPdfOpen(false),this.chatBodyMaker.resizeChatBody(this.isPdfOpen,e?.chatBody),this.iframeBridge.postToTap({type:"pdf:shrinked"});}),this.isLocal&&this.iframeBridge.listenToTap("alarm:fadeIn",r=>{this.floatingButtonMaker.alarmFadeIn(r.messageInfo);});}removeChat(){if(!this.chatBody)throw new Error("chatBody is not initialized");this.chatBodyMaker.removeChatBody(),this.floatingButtonMaker.alarmRemove(),this.iframeBridge.removeIframe(),this.chatBody=null,this.isOpen=false;}postChatInfo({clipId:t,clipPlayHead:e}){this.seekTimeline({clipId:t,clipPlayHead:e});}getTimelineInfo({callback:t}){this.events.onTimelineSeek(t);}};B=new WeakSet,Ae=function(){return typeof window<"u"&&typeof document<"u"};var Xt=X;module.exports=Xt;//# sourceMappingURL=index.js.map
|
|
24
24
|
//# sourceMappingURL=index.js.map
|