@coxwave/tap-sdk 0.0.1
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 +390 -0
- package/dist/index.css +2 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.global.js +24 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +24 -0
- package/dist/index.mjs.map +1 -0
- package/index.ts +238 -0
- package/package.json +43 -0
package/index.ts
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import ChatBodyMaker from "./chatBody";
|
|
2
|
+
import FloatingButtonMaker from "./floatingButton";
|
|
3
|
+
import { TapIframeBridge } from "./services/tap-iframe-bridge";
|
|
4
|
+
import { EventManager } from "./services/event-manager";
|
|
5
|
+
import showPopupWithHtml from "./popUpImage";
|
|
6
|
+
|
|
7
|
+
import InitGA from "./ga";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
AlarmMessageInstanceType,
|
|
11
|
+
ChatApiParamsType,
|
|
12
|
+
TapSDKType,
|
|
13
|
+
CustomStylesType,
|
|
14
|
+
ShortcutKeyType,
|
|
15
|
+
SeekTimelineParamsType,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
class TapSDK {
|
|
19
|
+
private pluginKey: string;
|
|
20
|
+
private iframeBridge: TapIframeBridge;
|
|
21
|
+
public events: EventManager;
|
|
22
|
+
|
|
23
|
+
private chatBody: HTMLElement | null = null;
|
|
24
|
+
private chatBodyMaker: ChatBodyMaker;
|
|
25
|
+
private floatingButtonMaker: FloatingButtonMaker;
|
|
26
|
+
private shortcutKey: ShortcutKeyType = {
|
|
27
|
+
openChat: { key: "/", modifier: "" },
|
|
28
|
+
sendChat: { key: "Enter", modifier: "" },
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
private isProd: boolean;
|
|
32
|
+
private isLocal: boolean;
|
|
33
|
+
|
|
34
|
+
private isOpen: boolean;
|
|
35
|
+
private isPdfOpen: boolean;
|
|
36
|
+
|
|
37
|
+
constructor({ pluginKey, isProd = false, isLocal = false }: TapSDKType) {
|
|
38
|
+
// protocol
|
|
39
|
+
this.pluginKey = pluginKey;
|
|
40
|
+
this.iframeBridge = new TapIframeBridge({
|
|
41
|
+
hostClientUrl: window.location.origin,
|
|
42
|
+
pluginKey: this.pluginKey,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// events
|
|
46
|
+
this.events = new EventManager(this.iframeBridge);
|
|
47
|
+
|
|
48
|
+
// render
|
|
49
|
+
this.floatingButtonMaker = new FloatingButtonMaker();
|
|
50
|
+
this.chatBodyMaker = new ChatBodyMaker();
|
|
51
|
+
|
|
52
|
+
// ga log
|
|
53
|
+
this.isProd = isProd;
|
|
54
|
+
this.isLocal = isLocal;
|
|
55
|
+
|
|
56
|
+
// state
|
|
57
|
+
this.isOpen = false;
|
|
58
|
+
this.isPdfOpen = false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#isClient() {
|
|
62
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private setIsOpen(isOpen: boolean) {
|
|
66
|
+
this.isOpen = isOpen;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private setIsPdfOpen(isPdfOpen: boolean) {
|
|
70
|
+
this.isPdfOpen = isPdfOpen;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
seekTimeline({ clipId, clipPlayHead }: SeekTimelineParamsType) {
|
|
74
|
+
this.iframeBridge.postToTap({
|
|
75
|
+
type: "timeline:seek",
|
|
76
|
+
clipId,
|
|
77
|
+
clipPlayHead,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async initChat({
|
|
82
|
+
chatApiParams,
|
|
83
|
+
customStyles,
|
|
84
|
+
shortcutKey,
|
|
85
|
+
}: {
|
|
86
|
+
chatApiParams: ChatApiParamsType;
|
|
87
|
+
customStyles?: CustomStylesType;
|
|
88
|
+
shortcutKey?: ShortcutKeyType;
|
|
89
|
+
}) {
|
|
90
|
+
if (!this.#isClient()) throw new Error("not client");
|
|
91
|
+
|
|
92
|
+
this.shortcutKey = {
|
|
93
|
+
openChat: shortcutKey?.openChat ?? this.shortcutKey.openChat,
|
|
94
|
+
sendChat: shortcutKey?.sendChat ?? this.shortcutKey.sendChat,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// chat body render
|
|
98
|
+
if (!this.chatBody) {
|
|
99
|
+
this.chatBody = this.chatBodyMaker.createChatBody({
|
|
100
|
+
...(customStyles?.chatBody && {
|
|
101
|
+
customChatBody: customStyles.chatBody,
|
|
102
|
+
}),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// chat iframe
|
|
107
|
+
if (!this.iframeBridge.hasIframe()) {
|
|
108
|
+
await this.iframeBridge.renderIframe({
|
|
109
|
+
chatBody: this.chatBody,
|
|
110
|
+
isProd: this.isProd,
|
|
111
|
+
isLocal: this.isLocal,
|
|
112
|
+
});
|
|
113
|
+
// Handshake will be performed after iframe load
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const initiatedMessage = await this.iframeBridge.performHandshake(
|
|
117
|
+
{
|
|
118
|
+
chatApiParams,
|
|
119
|
+
customStyles,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
retryInterval: 500,
|
|
123
|
+
maxRetries: 10,
|
|
124
|
+
timeout: 10000,
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Initialize GA with the received gaId
|
|
129
|
+
new InitGA({ gaId: initiatedMessage.gaId });
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error("Handshake failed:", error);
|
|
132
|
+
throw new Error(
|
|
133
|
+
`Chat initialization failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// floating button render
|
|
138
|
+
this.floatingButtonMaker.render({
|
|
139
|
+
...(customStyles?.floatingButton && {
|
|
140
|
+
customFloatingButton: customStyles.floatingButton,
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
this.floatingButtonMaker.addClickEvent({
|
|
144
|
+
callback: () => {
|
|
145
|
+
this.iframeBridge.postToTap({
|
|
146
|
+
type: this.isOpen ? "chat:close" : "chat:open",
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
this.floatingButtonMaker.addAlarmClickEvent({
|
|
152
|
+
callback: (messageInfo: AlarmMessageInstanceType) => {
|
|
153
|
+
this.iframeBridge.postToTap({ type: "chat:open", isAlarm: true });
|
|
154
|
+
this.iframeBridge.postToTap({ type: "alarm:click", messageInfo });
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
this.iframeBridge.listenToTap("chat:opened", () => {
|
|
159
|
+
this.setIsOpen(true);
|
|
160
|
+
this.chatBodyMaker.toggleVisibility(this.isOpen);
|
|
161
|
+
this.floatingButtonMaker.alarmRemove();
|
|
162
|
+
});
|
|
163
|
+
this.iframeBridge.listenToTap("chat:closed", () => {
|
|
164
|
+
this.setIsOpen(false);
|
|
165
|
+
this.chatBodyMaker.toggleVisibility(this.isOpen);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// alarm
|
|
169
|
+
this.iframeBridge.listenToTap("alarm:fadeIn", (data) => {
|
|
170
|
+
if (this.isOpen) return;
|
|
171
|
+
this.floatingButtonMaker.alarmFadeIn(data.messageInfo);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// popUp
|
|
175
|
+
this.iframeBridge.listenToTap("popUp:open", (data) => {
|
|
176
|
+
showPopupWithHtml({
|
|
177
|
+
htmlString: data.popUpInfo.html,
|
|
178
|
+
callback: () => this.iframeBridge.postToTap({ type: "popUp:close" }),
|
|
179
|
+
...(customStyles?.chatBody && { customStyles: customStyles.chatBody }),
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// pdf Open
|
|
184
|
+
this.iframeBridge.listenToTap("pdf:open", () => {
|
|
185
|
+
this.setIsPdfOpen(true);
|
|
186
|
+
this.chatBodyMaker.resizeChatBody(this.isPdfOpen, customStyles?.chatBody);
|
|
187
|
+
this.iframeBridge.postToTap({ type: "pdf:enlarged" });
|
|
188
|
+
});
|
|
189
|
+
this.iframeBridge.listenToTap("pdf:close", () => {
|
|
190
|
+
this.setIsPdfOpen(false);
|
|
191
|
+
this.chatBodyMaker.resizeChatBody(this.isPdfOpen, customStyles?.chatBody);
|
|
192
|
+
this.iframeBridge.postToTap({ type: "pdf:shrinked" });
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// if dev, attach alaram:fadeIn event
|
|
196
|
+
if (this.isLocal) {
|
|
197
|
+
this.iframeBridge.listenToTap("alarm:fadeIn", (data) => {
|
|
198
|
+
this.floatingButtonMaker.alarmFadeIn(data.messageInfo);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
removeChat() {
|
|
204
|
+
if (!this.chatBody) throw new Error("chatBody is not initialized");
|
|
205
|
+
|
|
206
|
+
this.chatBodyMaker.removeChatBody();
|
|
207
|
+
this.floatingButtonMaker.alarmRemove();
|
|
208
|
+
this.iframeBridge.removeIframe();
|
|
209
|
+
this.chatBody = null;
|
|
210
|
+
this.isOpen = false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @deprecated use `seekTimeline` method. gotta be expired at v1.0.0
|
|
215
|
+
*/
|
|
216
|
+
postChatInfo({
|
|
217
|
+
clipId,
|
|
218
|
+
clipPlayHead,
|
|
219
|
+
}: {
|
|
220
|
+
clipId: string;
|
|
221
|
+
clipPlayHead: number;
|
|
222
|
+
}) {
|
|
223
|
+
this.seekTimeline({ clipId, clipPlayHead });
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @deprecated use `events.onTimelineSeek` method. gotta be expired at v1.0.0
|
|
228
|
+
*/
|
|
229
|
+
getTimelineInfo({
|
|
230
|
+
callback,
|
|
231
|
+
}: {
|
|
232
|
+
callback: (clipPlayHead: number, clipId: string) => void;
|
|
233
|
+
}) {
|
|
234
|
+
this.events.onTimelineSeek(callback);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export default TapSDK;
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@coxwave/tap-sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A vanilla JS SDK",
|
|
6
|
+
"main": "index.ts",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup",
|
|
16
|
+
"build:analyze": "tsup --metafile",
|
|
17
|
+
"dev": "tsup --watch",
|
|
18
|
+
"prepare": "pnpm build",
|
|
19
|
+
"lint": "eslint .",
|
|
20
|
+
"publish:npm": "./scripts/publish.sh"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"sdk",
|
|
24
|
+
"vanilla",
|
|
25
|
+
"javascript"
|
|
26
|
+
],
|
|
27
|
+
"author": "",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@coxwave/tap-messages": "workspace:*"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@coxwave/config-eslint": "workspace:*",
|
|
37
|
+
"@coxwave/config-typescript": "workspace:*",
|
|
38
|
+
"@vanilla-extract/css": "^1.17.4",
|
|
39
|
+
"@vanilla-extract/esbuild-plugin": "^2.3.18",
|
|
40
|
+
"postcss": "^8.5.6",
|
|
41
|
+
"tsup": "^8.5.0"
|
|
42
|
+
}
|
|
43
|
+
}
|