@coxwave/tap-sdk 0.0.8 → 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 +33 -6
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.global.js +7 -3
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,13 +22,12 @@ const sdk = new TapSDK({
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
await sdk.init({
|
|
25
|
+
buttonId: "tap-button", // ID of the HTML element to attach the toggle button to
|
|
25
26
|
course: {
|
|
26
27
|
userId: "user-123",
|
|
27
28
|
courseId: "course-456",
|
|
28
29
|
clipId: null,
|
|
29
|
-
// clipPlayHead can be provided if it exists in your integration contract
|
|
30
30
|
},
|
|
31
|
-
buttonId: "tap-button",
|
|
32
31
|
customStyles: {
|
|
33
32
|
chatBody: {
|
|
34
33
|
position: { top: "64px", right: "32px" },
|
|
@@ -73,9 +72,9 @@ EduTap can send rich alarm notifications and HTML pop-ups over the iframe channe
|
|
|
73
72
|
|
|
74
73
|
Initializes the iframe, performs the handshake, and wires up UI controls. Required options:
|
|
75
74
|
|
|
76
|
-
- `
|
|
77
|
-
- `
|
|
78
|
-
- `
|
|
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
|
|
79
78
|
|
|
80
79
|
### `events.seekTimeline({ clipId, clipPlayHead })`
|
|
81
80
|
|
|
@@ -94,12 +93,17 @@ Unhooks all listeners, removes the iframe and toggle button decorations, and res
|
|
|
94
93
|
Events are exposed via the `sdk.events` helper. Every listener returns an unsubscribe function.
|
|
95
94
|
|
|
96
95
|
```ts
|
|
96
|
+
// Chat lifecycle events
|
|
97
|
+
sdk.events.onChatInitiated(() => console.log("chat initialized"));
|
|
97
98
|
sdk.events.onChatOpened(() => console.log("chat opened"));
|
|
98
99
|
sdk.events.onChatClosed(() => console.log("chat closed"));
|
|
100
|
+
|
|
101
|
+
// Timeline synchronization
|
|
99
102
|
sdk.events.onTimelineSeek((playHead, clipId) => {
|
|
100
103
|
console.log("EduTap requested timeline seek", playHead, clipId);
|
|
101
104
|
});
|
|
102
105
|
|
|
106
|
+
// Notifications and overlays
|
|
103
107
|
sdk.events.onAlarmFadeIn((alarm) => {
|
|
104
108
|
console.log("Alarm", alarm.message);
|
|
105
109
|
});
|
|
@@ -136,7 +140,30 @@ All message contracts are sourced from `@coxwave/tap-messages` and validated wit
|
|
|
136
140
|
|
|
137
141
|
MIT © 2025 Coxwave
|
|
138
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
|
+
|
|
139
165
|
## Deprecated helpers
|
|
140
166
|
|
|
167
|
+
- `initChat(options)` – use `init(options)` instead; scheduled for removal in v1.0.0
|
|
141
168
|
- `postChatInfo({ clipId, clipPlayHead })` – alias for `events.seekTimeline`; scheduled for removal in v1.0.0
|
|
142
|
-
- `getTimelineInfo({ callback })` – use `sdk.events.onTimelineSeek` instead
|
|
169
|
+
- `getTimelineInfo({ callback })` – use `sdk.events.onTimelineSeek` instead; scheduled for removal in v1.0.0
|
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 {
|
|
@@ -37,9 +57,11 @@ declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
|
|
|
37
57
|
protected hostOrigin: string;
|
|
38
58
|
protected apiKey: string;
|
|
39
59
|
protected iframe: HTMLIFrameElement | null;
|
|
40
|
-
|
|
60
|
+
private eventLogger;
|
|
61
|
+
constructor({ hostOrigin, apiKey, eventLogger, }: {
|
|
41
62
|
hostOrigin: string;
|
|
42
63
|
apiKey: string;
|
|
64
|
+
eventLogger?: EventLogger;
|
|
43
65
|
});
|
|
44
66
|
protected isValidOrigin(_event: MessageEvent): boolean;
|
|
45
67
|
protected getMessageTarget(): Window | null;
|
package/dist/index.d.ts
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 {
|
|
@@ -37,9 +57,11 @@ declare class TapIframeBridge extends Messenger<ToTapMessage, FromTapMessage> {
|
|
|
37
57
|
protected hostOrigin: string;
|
|
38
58
|
protected apiKey: string;
|
|
39
59
|
protected iframe: HTMLIFrameElement | null;
|
|
40
|
-
|
|
60
|
+
private eventLogger;
|
|
61
|
+
constructor({ hostOrigin, apiKey, eventLogger, }: {
|
|
41
62
|
hostOrigin: string;
|
|
42
63
|
apiKey: string;
|
|
64
|
+
eventLogger?: EventLogger;
|
|
43
65
|
});
|
|
44
66
|
protected isValidOrigin(_event: MessageEvent): boolean;
|
|
45
67
|
protected getMessageTarget(): Window | null;
|
package/dist/index.global.js
CHANGED
|
@@ -11,10 +11,14 @@
|
|
|
11
11
|
}
|
|
12
12
|
})();
|
|
13
13
|
|
|
14
|
-
var TapSDK=(function(){'use strict';var
|
|
14
|
+
var TapSDK=(function(){'use strict';var $e=Object.defineProperty;var Z=r=>{throw TypeError(r)};var je=(r,e,t)=>e in r?$e(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t;var o=(r,e,t)=>je(r,typeof e!="symbol"?e+"":e,t),Y=(r,e,t)=>e.has(r)||Z("Cannot "+t);var Q=(r,e,t)=>(Y(r,e,"read from private field"),t?t.call(r):e.get(r)),v=(r,e,t)=>e.has(r)?Z("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t);var m=(r,e,t)=>(Y(r,e,"access private method"),t);var ee="_1mlv4me2",E="_1mlv4me4";var S="_1mlv4me3";var N=class{constructor(){o(this,"chatBody",null);this.chatBody=null;}createChatBody({customChatBody:e}){return this.chatBody?this.chatBody:(this.chatBody=document.createElement("div"),this.chatBody.id="cw-chat-body",this.chatBody.className=ee,this.chatBody.style.setProperty("z-index","10000001","important"),this.chatBody.style.setProperty("position","fixed","important"),Object.assign(this.chatBody.style,{top:e?.position?.top??"50px",right:e?.position?.right??"24px",left:e?.position?.left??"unset",bottom:e?.position?.bottom??"unset",width:e?.width??"340px",height:e?.height??"calc(100% - 116px)",overflow:"hidden",backgroundColor:"transparent",borderRadius:e?.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(e){if(!this.chatBody)return;this.chatBody.classList.remove(L,I),this.chatBody.style.display="block";let t=()=>{this.chatBody&&(this.chatBody.classList.contains(I)&&(this.chatBody.style.display="none"),this.chatBody.removeEventListener("animationend",t));};this.chatBody.addEventListener("animationend",t),requestAnimationFrame(()=>{this.chatBody?.classList.add(e?L:I);});}removeChatBody(){this.chatBody&&(this.chatBody.remove(),this.chatBody=null);}resizeChatBody(e,t){if(!this.chatBody)return;let n=t?.width??"340px",i=parseInt(n,10),u=i/3*10-i,s=e?`${i+u}px`:`${i}px`;this.chatBody.style.width=s;}},te=N;var T,z=class{constructor(){o(this,"buttonElement");v(this,T,(e,t)=>e.key===t?true:e.code.startsWith("Key")?e.code.slice(3).toLowerCase()===t:false);}create(e){let t=document.getElementById(e);if(!t)throw new Error(`Element with id '${e}' not found`);return t.style.setProperty("position","relative","important"),t.style.setProperty("z-index","10000001","important"),this.buttonElement=t,this.buttonElement}onClick(e){if(!this.buttonElement)throw new Error("not initialized");this.buttonElement.addEventListener("click",e);}onKeyboardShortcut({openChatShortcutKey:e,callback:t}){if(!this.buttonElement)throw new Error("not initialized");window.addEventListener("keydown",n=>{Q(this,T).call(this,n,e.key)&&(!e.modifier||n[e.modifier])&&t();});}getButtonElement(){return this.buttonElement}};T=new WeakMap;var ne=z;var re="wtjce01",q={default:"wtjce0b wtjce0a","call-to-action":"wtjce0c wtjce0a"},ie="wtjce0a",se="wtjce09",R={default:"wtjce0e wtjce0d","call-to-action":"wtjce0f wtjce0d"},ue="wtjce0d",oe="wtjce0h",ae="wtjce0g",H="wtjce03",le="wtjce08",F={default:"wtjce06 wtjce05","call-to-action":"wtjce07 wtjce05"},ce="wtjce05",V="wtjce02",pe="wtjce04";var h,fe,ye,he,me,de,G=class{constructor(){v(this,h);o(this,"container");o(this,"alarmTimeout");o(this,"alarmCornerSVG");o(this,"textContainer");o(this,"circleElement");o(this,"textInTextContainer");o(this,"messageInfo");}render({rootElement:e}){this.container=document.createElement("div"),this.container.id="alarm-container",this.container.className=re,this.container.addEventListener("click",n=>{n.stopPropagation();}),e.appendChild(this.container),m(this,h,fe).call(this,this.container);let t=m(this,h,ye).call(this,this.container);m(this,h,me).call(this,t),m(this,h,he).call(this,t);}fadeIn(e){e.type==="default"||e.type==="hourSpent"?(this.textContainer.className=F.default,this.alarmCornerSVG.setAttribute("class",q.default),this.circleElement.className=R.default):(this.textContainer.className=F["call-to-action"],this.alarmCornerSVG.setAttribute("class",q["call-to-action"]),this.circleElement.className=R["call-to-action"]),this.messageInfo=e,this.textInTextContainer.textContent=e.message,this.toggleVisibility(true),this.alarmTimeout=setTimeout(()=>{this.toggleVisibility(false);},18*1e3);}onAlarmClick(e){this.container.addEventListener("click",()=>{this.toggleVisibility(false),e(this.messageInfo);});}toggleVisibility(e){this.container.classList.remove(V,H),requestAnimationFrame(()=>{this.container?.classList.add(e?V:H);});}remove(){this.container&&this.toggleVisibility(false),this.alarmTimeout&&clearTimeout(this.alarmTimeout);}};h=new WeakSet,fe=function(e){let t=document.createElement("div");t.className=se,e.appendChild(t);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",ie);let i=document.createElementNS("http://www.w3.org/2000/svg","path");i.setAttribute("d","M5.5 0L11.1292 8.25H-0.129165L5.5 0Z"),i.setAttribute("fill","currentColor"),n.appendChild(i),this.alarmCornerSVG=n,t.appendChild(n);},ye=function(e){let t=document.createElement("div");return t.className=pe,e.appendChild(t),t},he=function(e){this.textContainer=document.createElement("div"),this.textContainer.className=ce,e.appendChild(this.textContainer),this.textInTextContainer=document.createElement("span"),this.textInTextContainer.className=le,this.textContainer.appendChild(this.textInTextContainer);},me=function(e){let t=document.createElement("div");t.className=ue,e.appendChild(t),t.addEventListener("click",i=>{i.stopPropagation(),this.remove();});let n=document.createElement("span");n.className=oe,t.appendChild(n),n.textContent="\uC54C\uB9BC \uB044\uAE30",m(this,h,de).call(this,t),this.circleElement=t;},de=function(e){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("width","10"),t.setAttribute("height","10"),t.setAttribute("viewBox","0 0 14 14"),t.setAttribute("fill","none"),t.setAttribute("class",ae);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"),t.appendChild(n),e.appendChild(t);};var ve=G;var U;function ge(r){return {lang:r?.lang??U?.lang,message:r?.message,abortEarly:r?.abortEarly??U?.abortEarly,abortPipeEarly:r?.abortPipeEarly??U?.abortPipeEarly}}var Se;function Le(r){return Se?.get(r)}var Ne;function ze(r){return Ne?.get(r)}var qe;function Re(r,e){return qe?.get(r)?.get(e)}function be(r){let e=typeof r;return e==="string"?`"${r}"`:e==="number"||e==="bigint"||e==="boolean"?`${r}`:e==="object"||e==="function"?(r&&Object.getPrototypeOf(r)?.constructor?.name)??"null":e}function w(r,e,t,n,i){let u=i&&"input"in i?i.input:t.value,s=i?.expected??r.expects??null,c=i?.received??be(u),a={kind:r.kind,type:r.type,input:u,expected:s,received:c,message:`Invalid ${e}: ${s?`Expected ${s} but r`:"R"}eceived ${c}`,requirement:r.requirement,path:i?.path,issues:i?.issues,lang:n.lang,abortEarly:n.abortEarly,abortPipeEarly:n.abortPipeEarly},p=r.kind==="schema",l=i?.message??r.message??Re(r.reference,a.lang)??(p?ze(a.lang):null)??n.message??Le(a.lang);l!==void 0&&(a.message=typeof l=="function"?l(a):l),p&&(t.typed=false),t.issues?t.issues.push(a):t.issues=[a];}function E(r){return {version:1,vendor:"valibot",validate(e){return r["~run"]({value:e},ge())}}}function He(r,e){return Object.hasOwn(r,e)&&e!=="__proto__"&&e!=="prototype"&&e!=="constructor"}function Fe(r,e,t){return typeof r.fallback=="function"?r.fallback(e,t):r.fallback}function Ve(r,e,t){return typeof r.default=="function"?r.default(e,t):r.default}function K(){return {kind:"schema",type:"any",reference:K,expects:"any",async:false,get"~standard"(){return E(this)},"~run"(r){return r.typed=true,r}}}function _(r,e){return {kind:"schema",type:"literal",reference:_,expects:be(r),async:false,literal:r,message:e,get"~standard"(){return E(this)},"~run"(t,n){return t.value===this.literal?t.typed=true:w(this,"type",t,n),t}}}function C(r,e){return {kind:"schema",type:"object",reference:C,expects:"Object",async:false,entries:r,message:e,get"~standard"(){return E(this)},"~run"(t,n){let i=t.value;if(i&&typeof i=="object"){t.typed=true,t.value={};for(let u in this.entries){let s=this.entries[u];if(u in i||(s.type==="exact_optional"||s.type==="optional"||s.type==="nullish")&&s.default!==void 0){let c=u in i?i[u]:Ve(s),a=s["~run"]({value:c},n);if(a.issues){let p={type:"object",origin:"value",input:i,key:u,value:c};for(let l of a.issues)l.path?l.path.unshift(p):l.path=[p],t.issues?.push(l);if(t.issues||(t.issues=a.issues),n.abortEarly){t.typed=false;break}}a.typed||(t.typed=false),t.value[u]=a.value;}else if(s.fallback!==void 0)t.value[u]=Fe(s);else if(s.type!=="exact_optional"&&s.type!=="optional"&&s.type!=="nullish"&&(w(this,"key",t,n,{input:void 0,expected:`"${u}"`,path:[{type:"object",origin:"key",input:i,key:u,value:i[u]}]}),n.abortEarly))break}}else w(this,"type",t,n);return t}}}function W(r,e,t){return {kind:"schema",type:"record",reference:W,expects:"Object",async:false,key:r,value:e,message:t,get"~standard"(){return E(this)},"~run"(n,i){let u=n.value;if(u&&typeof u=="object"){n.typed=true,n.value={};for(let s in u)if(He(u,s)){let c=u[s],a=this.key["~run"]({value:s},i);if(a.issues){let l={type:"object",origin:"key",input:u,key:s,value:c};for(let f of a.issues)f.path=[l],n.issues?.push(f);if(n.issues||(n.issues=a.issues),i.abortEarly){n.typed=false;break}}let p=this.value["~run"]({value:c},i);if(p.issues){let l={type:"object",origin:"value",input:u,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),i.abortEarly){n.typed=false;break}}(!a.typed||!p.typed)&&(n.typed=false),a.typed&&(n.value[a.value]=p.value);}}else w(this,"type",n,i);return n}}}function A(r){return {kind:"schema",type:"string",reference:A,expects:"string",async:false,message:r,get"~standard"(){return E(this)},"~run"(e,t){return typeof e.value=="string"?e.typed=true:w(this,"type",e,t),e}}}function ke(r,e,t){let n=r["~run"]({value:e},ge(t));return {typed:n.typed,success:!n.issues,output:n.value,issues:n.issues}}var we="chat:init",Ge="chat:initiated";var Ee=C({type:_(Ge),gaId:A()});C({type:_("GA_EVENT"),payload:W(A(),K())});var M=class{constructor(){o(this,"listeners",new Map);o(this,"unifiedMessageHandler",null);}on(e,t){let n=u=>{if(this.isValidOrigin(u))try{let s=u.data,c=typeof s=="string"?JSON.parse(s):s,{type:a}=c;a===e&&t(c);}catch(s){console.warn("Messenger: Failed to parse message data",s);}},i=this.listeners.get(e)||[];return i.push(n),this.listeners.set(e,i),this.unifiedMessageHandler||(this.unifiedMessageHandler=u=>{this.listeners.forEach(s=>s.forEach(c=>c(u)));},window.addEventListener("message",this.unifiedMessageHandler)),()=>{this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}}removeListener(e){this.listeners.delete(e);}removeAllListeners(){this.listeners.clear(),this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}postMessage(e){try{let t=this.getMessageTarget();return t?(t.postMessage(e,this.getTargetOrigin()),!0):(console.warn("Messenger: Message target not available"),!1)}catch(t){return console.error("Messenger: postMessage failed",t),false}}};var g=class extends Error{constructor(t,n,i){super(`Handshake failed: ${t}${n?` - ${n}`:""}`);this.reason=t;this.details=n;this.originalError=i;this.name="HandshakeError";}},D=class{constructor(e,t,n){this.getTargetWindow=e;this.getTargetOrigin=t;this.isValidOrigin=n;o(this,"abortController",null);o(this,"messageListener",null);}async execute(e,t={}){let{timeout:n=1e4,maxRetries:i=10,retryInterval:u=500}=t;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 g("TIMEOUT","Handshake was cancelled"));};this.abortController?.signal.addEventListener("abort",f),this.messageListener=y=>{if(this.isValidOrigin(y))try{let b=y.data,$e=typeof b=="string"?JSON.parse(b):b,J=ke(Ee,$e);if(J.success){l(),this.abortController=null,s(J.output);return}}catch{}},window.addEventListener("message",this.messageListener),p=setTimeout(()=>{l(),this.abortController=null,c(new g("TIMEOUT",`No valid response received within ${n}ms`));},n);let d=()=>{if(!this.abortController?.signal.aborted)try{let y=this.getTargetWindow(),b=this.getTargetOrigin();if(!y)throw new g("NO_TARGET_WINDOW","Target iframe window is not available");y.postMessage(e,b),a++,a<i&&setTimeout(()=>{this.abortController?.signal.aborted||d();},u);}catch(y){l(),this.abortController=null,y instanceof g?c(y):c(new g("MESSAGE_SEND_FAILED","Failed to send handshake message",y));}};d();})}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 k,Ie,Te,O=class O extends M{constructor({hostOrigin:t,apiKey:n}){super();v(this,k);o(this,"hostOrigin");o(this,"apiKey");o(this,"iframe");o(this,"postToTap",t=>this.iframe?super.postMessage(t):(console.error("TapIframeBridge: iframe not found - ensure createIframeChat() was called first"),console.error("Failed to send message:",t),(t.type==="chat:open"||t.type==="chat:close")&&console.error("Chat cannot be opened/closed - iframe is not initialized"),false));o(this,"listenToTap",super.on);this.hostOrigin=t,this.apiKey=n;}isValidOrigin(t){return true}getMessageTarget(){return this.iframe?.contentWindow||null}getTargetOrigin(){if(!this.iframe?.src)return "*";try{return new URL(this.iframe.src).origin}catch{return "*"}}renderIframe(t){return new Promise(n=>{this.iframe&&(this.iframe.remove(),this.iframe=null),this.iframe=document.createElement("iframe"),this.iframe.style.setProperty("display","flex","important"),this.iframe.style.setProperty("border","none","important"),this.iframe.src=m(this,k,Ie).call(this),this.iframe.style.width="100%",this.iframe.style.height="100%",this.iframe.onload=()=>{n(this.iframe);},t?.appendChild(this.iframe);})}hasIframe(){return this.iframe!==null&&this.iframe!==void 0}async ensureIframe(t){return this.hasIframe()?this.iframe:this.renderIframe(t)}removeIframe(){this.iframe?.remove(),this.iframe=null,this.removeAllListeners();}async performHandshake(t,n=O.defaultHandshakeOptions){if(!this.iframe)throw new Error("TapIframeBridge: iframe not available for handshake");console.log("[TapIframeBridge] Starting handshake with iframe:",this.iframe.src),console.log("[TapIframeBridge] Target origin:",this.getTargetOrigin()),console.log("[TapIframeBridge] Message target available:",!!this.getMessageTarget());let i=new D(()=>this.getMessageTarget(),()=>this.getTargetOrigin(),s=>this.isValidOrigin(s)),u={type:we,hostOrigin:this.hostOrigin,apiKey:this.apiKey,chatApiParams:t.chatApiParams,apiUrl:t?.apiUrl??(m(this,k,Te).call(this)||"")};console.log("[TapIframeBridge] Sending handshake message:",{type:u.type,hostOrigin:u.hostOrigin,apiKey:u.apiKey?"***":"missing",chatApiParams:u.chatApiParams,apiUrl:u.apiUrl});try{let s=await i.execute(u,n);return console.log("[TapIframeBridge] Handshake successful:",s),s}catch(s){throw console.error("[TapIframeBridge] Handshake failed:",s),s instanceof Error?new Error(`TapIframeBridge handshake failed: ${s.message}`):s}}};k=new WeakSet,Ie=function(){if(typeof window>"u"||typeof localStorage>"u")throw new Error("TapIframeBridge: window or localStorage is not defined");try{let t=localStorage.getItem("tap-url-storage");if(t){let n=JSON.parse(t);console.log("[TapIframeBridge] Stored tap-url-storage:",n);let i=n?.state?.tapUrl;if(i)return console.log("[TapIframeBridge] Using custom TAP URL:",i),`${i}/chat`}}catch{}return "https://edutap-ai.vercel.app/chat"},Te=function(){if(!(typeof window>"u"||typeof localStorage>"u"))try{let t=localStorage.getItem("tap-api-url-storage");return t?JSON.parse(t)?.state?.apiUrl:void 0}catch{return}},o(O,"defaultHandshakeOptions",{retryInterval:500,maxRetries:3,timeout:3e4});var $=O;var j=class{constructor(e){this.iframeBridge=e;}seekTimeline({clipId:e,clipPlayHead:t}){this.iframeBridge.postToTap({type:"timeline:seek",clipId:e,clipPlayHead:t});}onTimelineSeek(e){this.iframeBridge.listenToTap("timeline:seek",t=>e(t.clipPlayHead,t.clipId));}onChatOpened(e){this.iframeBridge.listenToTap("chat:opened",e);}onChatClosed(e){this.iframeBridge.listenToTap("chat:closed",e);}onChatInitiated(e){this.iframeBridge.listenToTap("chat:initiated",e);}onAlarmFadeIn(e){this.iframeBridge.listenToTap("alarm:fadeIn",t=>{e(t.messageInfo);});}onPopUpOpen(e){this.iframeBridge.listenToTap("popUp:open",t=>{e(t.popUpInfo);});}onPdfOpen(e){this.iframeBridge.listenToTap("pdf:open",e);}onPdfClose(e){this.iframeBridge.listenToTap("pdf:close",e);}};var x=class{constructor(){}handle(e){typeof window.gtag=="function"&&window.gtag("event",e.action,{event_category:e.category,event_label:e.label,value:e.value,...e.customParams});}},B=class{constructor(e=false){this.enabled=e;}handle(e){this.enabled&&console.log("[TapSDK Event]",e);}},P=class{constructor(){o(this,"middlewares",[]);}addMiddleware(e){this.middlewares.push(e);}removeMiddleware(e){let t=this.middlewares.indexOf(e);t>-1&&this.middlewares.splice(t,1);}log(e){this.middlewares.forEach(t=>{try{t.handle(e);}catch(n){console.warn("[EventLogger] Middleware error:",n);}});}logChatAction(e,t){this.log({action:`chat_${e}`,category:"engagement",customParams:{timestamp:Date.now(),...t}});}logButtonClick(e,t,n){let i={action:`${e}_button_clicked`,category:"user_interaction",customParams:{timestamp:Date.now(),...n}};t!==void 0&&(i.label=t),this.log(i);}logSDKInitialization(e,t,n){let i=Date.now()-t,u={action:"sdk_initialization",category:"system",label:e?"success":"failure",value:i,customParams:{timestamp:Date.now(),...n&&{error:n}}};this.log(u);}};var _e="wu2gm66",Ce="wu2gm67",Ae="wu2gm68";function Ke({htmlString:r,callback:e,customStyles:t}){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 i=document.createElement("div");i.id="wow",i.style.position="fixed",i.style.display="flex",i.style.flexDirection="column";let s=15;if(t?.width){let d=parseFloat(t.width),y=t.width.match(/[a-zA-Z%]+/)?.[0];!isNaN(d)&&y==="px"&&(s+=d);}else s+=340;if(t?.position?.right){let d=parseFloat(t?.position?.right),y=t?.position?.right.match(/[a-zA-Z%]+/)?.[0];!isNaN(d)&&y==="px"&&(s+=d);}else s=s+24;i.style.top=t?.position?.top??"50px",i.style.right=`${s}px`,i.style.left=t?.position?.left??"unset",i.style.bottom=t?.position?.bottom??"unset",i.style.maxWidth="calc(100vw - 100px)",i.style.maxHeight=t?.height??"calc(100vh - 116px)",i.style.overflow="auto",i.style.background="#fff",i.style.padding="20px",i.style.border="1px solid #ccc",i.style.boxShadow="0 4px 20px rgba(0,0,0,0.2)",i.style.zIndex="10000003",i.style.borderRadius="8px";let c=document.createElement("div");c.innerHTML=r,n.addEventListener("click",()=>{document.body.removeChild(n),document.body.removeChild(i),e();}),i.addEventListener("click",d=>{d.stopPropagation();}),i.appendChild(c),document.body.appendChild(n),document.body.appendChild(i);let a=document.querySelector(`.${_e}`),p=document.querySelector(".cw-plugin-code-block"),l=document.querySelector(`.${Ae}`),f=document.querySelector(`.${Ce}`);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 Me=Ke;var S,De,X=class{constructor({apiKey:e}){v(this,S);o(this,"apiKey");o(this,"iframeBridge");o(this,"events");o(this,"eventLogger");o(this,"chatBody");o(this,"chatBodyMaker");o(this,"button");o(this,"alarm");o(this,"chatBodyVisible");o(this,"isPdfOpen");o(this,"_isInitialized",false);this.apiKey=e,this.iframeBridge=new $({hostOrigin:window.location.origin,apiKey:this.apiKey}),this.events=new j(this.iframeBridge),this.eventLogger=new P,m(this,S,De).call(this),this.button=new ne,this.alarm=new ve,this.chatBodyMaker=new te,this.chatBodyVisible="closed",this.isPdfOpen=false;}get isOpen(){return this.chatBodyVisible==="open"}get isInitialized(){return this._isInitialized}async init({buttonId:e,course:t,customStyles:n}){if(this._isInitialized){console.warn("[TapSDK] Already initialized, skipping initialization");return}let i=Date.now();try{await this.validateEnvironment(),await this.setupChatBody(n),await Promise.all([this.setupButton(e),this.iframeBridge.ensureIframe(this.chatBody)]),this.setupEventListeners(n),await this.iframeBridge.performHandshake({chatApiParams:t,customStyles:n}),this._isInitialized=!0,this.eventLogger.logSDKInitialization(!0,i);}catch(u){let s=u instanceof Error?u.message:"Unknown error";throw this.eventLogger.logSDKInitialization(false,i,s),u}}destroy(){if(!this._isInitialized){console.warn("[TapSDK] SDK not initialized, nothing to destroy");return}this.chatBodyMaker.removeChatBody(),this.alarm.remove(),this.iframeBridge.removeIframe(),this.chatBody=void 0,this.chatBodyVisible="closed",this._isInitialized=false;}isClient(){return typeof window<"u"&&typeof document<"u"}setChatBodyVisible(e){this.chatBodyVisible=e;}setIsPdfOpen(e){this.isPdfOpen=e;}toggleChatOpen(){let e=this.chatBodyVisible==="open"?"chat:close":"chat:open";try{this.iframeBridge.postToTap({type:e})||console.error(`[TapSDK] Failed to send ${e} message`);}catch(t){console.error("[TapSDK] Error sending chat message:",t);}}async validateEnvironment(){if(!this.isClient())throw new Error("Not running in client environment: window is not defined")}async setupChatBody(e){if(!this.chatBody){let t=this.chatBodyMaker.createChatBody({...e?.chatBody&&{customChatBody:e.chatBody}});if(!t)throw new Error("Failed to create chat body");this.chatBody=t;}}async setupButton(e){let t=this.button.create(e);this.button.onClick(async()=>{await this.iframeBridge.ensureIframe(this.chatBody),this.eventLogger.logButtonClick("toggle",this.chatBodyVisible==="open"?"open":"closed"),this.toggleChatOpen();}),this.alarm.render({rootElement:t}),this.alarm.onAlarmClick(n=>{this.eventLogger.logButtonClick("alarm"),this.iframeBridge.postToTap({type:"chat:open",isAlarm:true}),this.iframeBridge.postToTap({type:"alarm:click",messageInfo:n});});}setupEventListeners(e){this.iframeBridge.listenToTap("chat:opened",()=>{this.setChatBodyVisible("open"),this.chatBodyMaker.toggleVisibility(this.chatBodyVisible==="open"),this.alarm.remove(),this.eventLogger.logChatAction("opened");}),this.iframeBridge.listenToTap("chat:closed",()=>{this.setChatBodyVisible("closed"),this.chatBodyMaker.toggleVisibility(this.chatBodyVisible==="open"),this.eventLogger.logChatAction("closed");}),this.iframeBridge.listenToTap("alarm:fadeIn",t=>{this.chatBodyVisible!=="open"&&this.alarm.fadeIn(t.messageInfo);}),this.iframeBridge.listenToTap("popUp:open",t=>{Me({htmlString:t.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.listenToTap("pdf:close",()=>{this.setIsPdfOpen(false),this.chatBodyMaker.resizeChatBody(this.isPdfOpen,e?.chatBody);});}async initChat(e){return this.init(e)}postChatInfo({clipId:e,clipPlayHead:t}){this.events.seekTimeline({clipId:e,clipPlayHead:t});}getTimelineInfo({callback:e}){this.events.onTimelineSeek(e);}};S=new WeakSet,De=function(){if(typeof window>"u"||typeof localStorage>"u"){this.eventLogger.addMiddleware(new x);return}try{localStorage.getItem("tap-environment")==="local"?this.eventLogger.addMiddleware(new B(!0)):this.eventLogger.addMiddleware(new x);}catch{this.eventLogger.addMiddleware(new x);}};var Wt=X;
|
|
19
|
-
|
|
18
|
+
`,willChange:"transform, opacity, width, max-height, max-width"}),document.body.appendChild(this.chatBody),this.chatBody)}toggleVisibility(e){if(!this.chatBody)return;this.chatBody.classList.remove(S,E),this.chatBody.style.display="block";let t=()=>{this.chatBody&&(this.chatBody.classList.contains(E)&&(this.chatBody.style.display="none"),this.chatBody.removeEventListener("animationend",t));};this.chatBody.addEventListener("animationend",t),requestAnimationFrame(()=>{this.chatBody?.classList.add(e?S:E);});}removeChatBody(){this.chatBody&&(this.chatBody.remove(),this.chatBody=null);}resizeChatBody(e,t){if(!this.chatBody)return;let n=t?.width??"340px",i=parseInt(n,10),s=i/3*10-i,u=e?`${i+s}px`:`${i}px`;this.chatBody.style.width=u;}},te=N;var _,z=class{constructor(){o(this,"buttonElement");v(this,_,(e,t)=>e.key===t?true:e.code.startsWith("Key")?e.code.slice(3).toLowerCase()===t:false);}create(e){let t=document.getElementById(e);if(!t)throw new Error(`Element with id '${e}' not found`);return t.style.setProperty("position","relative","important"),t.style.setProperty("z-index","10000001","important"),this.buttonElement=t,this.buttonElement}onClick(e){if(!this.buttonElement)throw new Error("not initialized");this.buttonElement.addEventListener("click",e);}onKeyboardShortcut({openChatShortcutKey:e,callback:t}){if(!this.buttonElement)throw new Error("not initialized");window.addEventListener("keydown",n=>{Q(this,_).call(this,n,e.key)&&(!e.modifier||n[e.modifier])&&t();});}getButtonElement(){return this.buttonElement}};_=new WeakMap;var ne=z;var re="wtjce01",q={default:"wtjce0b wtjce0a","call-to-action":"wtjce0c wtjce0a"},ie="wtjce0a",se="wtjce09",R={default:"wtjce0e wtjce0d","call-to-action":"wtjce0f wtjce0d"},ue="wtjce0d",oe="wtjce0h",ae="wtjce0g",H="wtjce03",le="wtjce08",G={default:"wtjce06 wtjce05","call-to-action":"wtjce07 wtjce05"},ce="wtjce05",F="wtjce02",pe="wtjce04";var h,fe,ye,he,me,de,V=class{constructor(){v(this,h);o(this,"container");o(this,"alarmTimeout");o(this,"alarmCornerSVG");o(this,"textContainer");o(this,"circleElement");o(this,"textInTextContainer");o(this,"messageInfo");}render({rootElement:e}){this.container=document.createElement("div"),this.container.id="alarm-container",this.container.className=re,this.container.addEventListener("click",n=>{n.stopPropagation();}),e.appendChild(this.container),m(this,h,fe).call(this,this.container);let t=m(this,h,ye).call(this,this.container);m(this,h,me).call(this,t),m(this,h,he).call(this,t);}fadeIn(e){e.type==="default"||e.type==="hourSpent"?(this.textContainer.className=G.default,this.alarmCornerSVG.setAttribute("class",q.default),this.circleElement.className=R.default):(this.textContainer.className=G["call-to-action"],this.alarmCornerSVG.setAttribute("class",q["call-to-action"]),this.circleElement.className=R["call-to-action"]),this.messageInfo=e,this.textInTextContainer.textContent=e.message,this.toggleVisibility(true),this.alarmTimeout=setTimeout(()=>{this.toggleVisibility(false);},18*1e3);}onAlarmClick(e){this.container.addEventListener("click",()=>{this.toggleVisibility(false),e(this.messageInfo);});}toggleVisibility(e){this.container.classList.remove(F,H),requestAnimationFrame(()=>{this.container?.classList.add(e?F:H);});}remove(){this.container&&this.toggleVisibility(false),this.alarmTimeout&&clearTimeout(this.alarmTimeout);}};h=new WeakSet,fe=function(e){let t=document.createElement("div");t.className=se,e.appendChild(t);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",ie);let i=document.createElementNS("http://www.w3.org/2000/svg","path");i.setAttribute("d","M5.5 0L11.1292 8.25H-0.129165L5.5 0Z"),i.setAttribute("fill","currentColor"),n.appendChild(i),this.alarmCornerSVG=n,t.appendChild(n);},ye=function(e){let t=document.createElement("div");return t.className=pe,e.appendChild(t),t},he=function(e){this.textContainer=document.createElement("div"),this.textContainer.className=ce,e.appendChild(this.textContainer),this.textInTextContainer=document.createElement("span"),this.textInTextContainer.className=le,this.textContainer.appendChild(this.textInTextContainer);},me=function(e){let t=document.createElement("div");t.className=ue,e.appendChild(t),t.addEventListener("click",i=>{i.stopPropagation(),this.remove();});let n=document.createElement("span");n.className=oe,t.appendChild(n),n.textContent="\uC54C\uB9BC \uB044\uAE30",m(this,h,de).call(this,t),this.circleElement=t;},de=function(e){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("width","10"),t.setAttribute("height","10"),t.setAttribute("viewBox","0 0 14 14"),t.setAttribute("fill","none"),t.setAttribute("class",ae);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"),t.appendChild(n),e.appendChild(t);};var ve=V;var U;function ge(r){return {lang:r?.lang??U?.lang,message:r?.message,abortEarly:r?.abortEarly??U?.abortEarly,abortPipeEarly:r?.abortPipeEarly??U?.abortPipeEarly}}var Le;function Se(r){return Le?.get(r)}var Ne;function ze(r){return Ne?.get(r)}var qe;function Re(r,e){return qe?.get(r)?.get(e)}function be(r){let e=typeof r;return e==="string"?`"${r}"`:e==="number"||e==="bigint"||e==="boolean"?`${r}`:e==="object"||e==="function"?(r&&Object.getPrototypeOf(r)?.constructor?.name)??"null":e}function x(r,e,t,n,i){let s=i&&"input"in i?i.input:t.value,u=i?.expected??r.expects??null,a=i?.received??be(s),l={kind:r.kind,type:r.type,input:s,expected:u,received:a,message:`Invalid ${e}: ${u?`Expected ${u} but r`:"R"}eceived ${a}`,requirement:r.requirement,path:i?.path,issues:i?.issues,lang:n.lang,abortEarly:n.abortEarly,abortPipeEarly:n.abortPipeEarly},p=r.kind==="schema",c=i?.message??r.message??Re(r.reference,l.lang)??(p?ze(l.lang):null)??n.message??Se(l.lang);c!==void 0&&(l.message=typeof c=="function"?c(l):c),p&&(t.typed=false),t.issues?t.issues.push(l):t.issues=[l];}function w(r){return {version:1,vendor:"valibot",validate(e){return r["~run"]({value:e},ge())}}}function He(r,e){return Object.hasOwn(r,e)&&e!=="__proto__"&&e!=="prototype"&&e!=="constructor"}function Ge(r,e,t){return typeof r.fallback=="function"?r.fallback(e,t):r.fallback}function Fe(r,e,t){return typeof r.default=="function"?r.default(e,t):r.default}function W(){return {kind:"schema",type:"any",reference:W,expects:"any",async:false,get"~standard"(){return w(this)},"~run"(r){return r.typed=true,r}}}function I(r,e){return {kind:"schema",type:"literal",reference:I,expects:be(r),async:false,literal:r,message:e,get"~standard"(){return w(this)},"~run"(t,n){return t.value===this.literal?t.typed=true:x(this,"type",t,n),t}}}function T(r,e){return {kind:"schema",type:"object",reference:T,expects:"Object",async:false,entries:r,message:e,get"~standard"(){return w(this)},"~run"(t,n){let i=t.value;if(i&&typeof i=="object"){t.typed=true,t.value={};for(let s in this.entries){let u=this.entries[s];if(s in i||(u.type==="exact_optional"||u.type==="optional"||u.type==="nullish")&&u.default!==void 0){let a=s in i?i[s]:Fe(u),l=u["~run"]({value:a},n);if(l.issues){let p={type:"object",origin:"value",input:i,key:s,value:a};for(let c of l.issues)c.path?c.path.unshift(p):c.path=[p],t.issues?.push(c);if(t.issues||(t.issues=l.issues),n.abortEarly){t.typed=false;break}}l.typed||(t.typed=false),t.value[s]=l.value;}else if(u.fallback!==void 0)t.value[s]=Ge(u);else if(u.type!=="exact_optional"&&u.type!=="optional"&&u.type!=="nullish"&&(x(this,"key",t,n,{input:void 0,expected:`"${s}"`,path:[{type:"object",origin:"key",input:i,key:s,value:i[s]}]}),n.abortEarly))break}}else x(this,"type",t,n);return t}}}function X(r,e,t){return {kind:"schema",type:"record",reference:X,expects:"Object",async:false,key:r,value:e,message:t,get"~standard"(){return w(this)},"~run"(n,i){let s=n.value;if(s&&typeof s=="object"){n.typed=true,n.value={};for(let u in s)if(He(s,u)){let a=s[u],l=this.key["~run"]({value:u},i);if(l.issues){let c={type:"object",origin:"key",input:s,key:u,value:a};for(let f of l.issues)f.path=[c],n.issues?.push(f);if(n.issues||(n.issues=l.issues),i.abortEarly){n.typed=false;break}}let p=this.value["~run"]({value:a},i);if(p.issues){let c={type:"object",origin:"value",input:s,key:u,value:a};for(let f of p.issues)f.path?f.path.unshift(c):f.path=[c],n.issues?.push(f);if(n.issues||(n.issues=p.issues),i.abortEarly){n.typed=false;break}}(!l.typed||!p.typed)&&(n.typed=false),l.typed&&(n.value[l.value]=p.value);}}else x(this,"type",n,i);return n}}}function C(r){return {kind:"schema",type:"string",reference:C,expects:"string",async:false,message:r,get"~standard"(){return w(this)},"~run"(e,t){return typeof e.value=="string"?e.typed=true:x(this,"type",e,t),e}}}function ke(r,e,t){let n=r["~run"]({value:e},ge(t));return {typed:n.typed,success:!n.issues,output:n.value,issues:n.issues}}var we="chat:init",Ve="chat:initiated";var Ee=T({type:I(Ve),gaId:C()});T({type:I("GA_EVENT"),payload:X(C(),W())});var A=class{constructor(){o(this,"listeners",new Map);o(this,"unifiedMessageHandler",null);}on(e,t){let n=s=>{if(this.isValidOrigin(s))try{let u=s.data,a=typeof u=="string"?JSON.parse(u):u,{type:l}=a;l===e&&t(a);}catch(u){console.warn("Messenger: Failed to parse message data",u);}},i=this.listeners.get(e)||[];return i.push(n),this.listeners.set(e,i),this.unifiedMessageHandler||(this.unifiedMessageHandler=s=>{this.listeners.forEach(u=>u.forEach(a=>a(s)));},window.addEventListener("message",this.unifiedMessageHandler)),()=>{this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}}removeListener(e){this.listeners.delete(e);}removeAllListeners(){this.listeners.clear(),this.unifiedMessageHandler&&(window.removeEventListener("message",this.unifiedMessageHandler),this.unifiedMessageHandler=null);}postMessage(e){try{let t=this.getMessageTarget();return t?(t.postMessage(e,this.getTargetOrigin()),!0):(console.warn("Messenger: Message target not available"),!1)}catch(t){return console.error("Messenger: postMessage failed",t),false}}};var g=class extends Error{constructor(t,n,i){super(`Handshake failed: ${t}${n?` - ${n}`:""}`);this.reason=t;this.details=n;this.originalError=i;this.name="HandshakeError";}},M=class{constructor(e,t,n){this.getTargetWindow=e;this.getTargetOrigin=t;this.isValidOrigin=n;o(this,"abortController",null);o(this,"messageListener",null);}async execute(e,t={}){let{timeout:n=1e4,maxRetries:i=10,retryInterval:s=500}=t;return this.cancel(),this.abortController=new AbortController,new Promise((u,a)=>{let l=0,p,c=()=>{p&&clearTimeout(p),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null);},f=()=>{c(),a(new g("TIMEOUT","Handshake was cancelled"));};this.abortController?.signal.addEventListener("abort",f),this.messageListener=y=>{if(this.isValidOrigin(y))try{let b=y.data,Oe=typeof b=="string"?JSON.parse(b):b,J=ke(Ee,Oe);if(J.success){c(),this.abortController=null,u(J.output);return}}catch{}},window.addEventListener("message",this.messageListener),p=setTimeout(()=>{c(),this.abortController=null,a(new g("TIMEOUT",`No valid response received within ${n}ms`));},n);let d=()=>{if(!this.abortController?.signal.aborted)try{let y=this.getTargetWindow(),b=this.getTargetOrigin();if(!y)throw new g("NO_TARGET_WINDOW","Target iframe window is not available");y.postMessage(e,b),l++,l<i&&setTimeout(()=>{this.abortController?.signal.aborted||d();},s);}catch(y){c(),this.abortController=null,y instanceof g?a(y):a(new g("MESSAGE_SEND_FAILED","Failed to send handshake message",y));}};d();})}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 k,_e,Ie,O=class O extends A{constructor({hostOrigin:t,apiKey:n,eventLogger:i}){super();v(this,k);o(this,"hostOrigin");o(this,"apiKey");o(this,"iframe");o(this,"eventLogger");o(this,"postToTap",t=>{if(!this.iframe)return console.error("TapIframeBridge: iframe not found - ensure createIframeChat() was called first"),console.error("Failed to send message:",t),(t.type==="chat:open"||t.type==="chat:close")&&console.error("Chat cannot be opened/closed - iframe is not initialized"),this.eventLogger?.log({action:"iframe_message_failed",category:"error",label:t.type,customParams:{reason:"iframe_not_initialized"}}),false;let n=super.postMessage(t);return this.eventLogger?.log({action:"iframe_message_sent",category:"communication",label:t.type,customParams:{success:n}}),n});o(this,"listenToTap",super.on);this.hostOrigin=t,this.apiKey=n,this.eventLogger=i;}isValidOrigin(t){return true}getMessageTarget(){return this.iframe?.contentWindow||null}getTargetOrigin(){if(!this.iframe?.src)return "*";try{return new URL(this.iframe.src).origin}catch{return "*"}}renderIframe(t){return new Promise(n=>{this.iframe&&(this.iframe.remove(),this.iframe=null),this.iframe=document.createElement("iframe"),this.iframe.style.setProperty("display","flex","important"),this.iframe.style.setProperty("border","none","important"),this.iframe.src=m(this,k,_e).call(this),this.iframe.style.width="100%",this.iframe.style.height="100%",this.iframe.onload=()=>{n(this.iframe);},t?.appendChild(this.iframe);})}hasIframe(){return this.iframe!==null&&this.iframe!==void 0}async ensureIframe(t){return this.hasIframe()?this.iframe:this.renderIframe(t)}removeIframe(){this.iframe?.remove(),this.iframe=null,this.removeAllListeners();}async performHandshake(t,n=O.defaultHandshakeOptions){if(!this.iframe)throw new Error("TapIframeBridge: iframe not available for handshake");this.eventLogger?.log({action:"handshake_started",category:"communication",customParams:{iframeSrc:this.iframe.src,targetOrigin:this.getTargetOrigin(),messageTargetAvailable:!!this.getMessageTarget()}});let i=new M(()=>this.getMessageTarget(),()=>this.getTargetOrigin(),a=>this.isValidOrigin(a)),s={type:we,hostOrigin:this.hostOrigin,apiKey:this.apiKey,chatApiParams:t.chatApiParams,apiUrl:t?.apiUrl??(m(this,k,Ie).call(this)||"")};this.eventLogger?.log({action:"handshake_message_sending",category:"communication",customParams:{messageType:s.type,hostOrigin:s.hostOrigin,hasApiKey:!!s.apiKey,apiUrl:s.apiUrl,chatApiParams:s.chatApiParams}});let u=Date.now();try{let a=await i.execute(s,n);return this.eventLogger?.log({action:"iframe_handshake",category:"system",label:"success",value:Date.now()-u,customParams:{apiUrl:s.apiUrl,targetOrigin:this.getTargetOrigin()}}),a}catch(a){throw console.error("[TapIframeBridge] Handshake failed:",a),this.eventLogger?.log({action:"iframe_handshake",category:"error",label:"failed",value:Date.now()-u,customParams:{error:a instanceof Error?a.message:"Unknown error",apiUrl:s.apiUrl}}),a instanceof Error?new Error(`TapIframeBridge handshake failed: ${a.message}`):a}}};k=new WeakSet,_e=function(){if(typeof window>"u"||typeof localStorage>"u")throw new Error("TapIframeBridge: window or localStorage is not defined");try{let t=localStorage.getItem("tap-url-storage");if(t){let n=JSON.parse(t);this.eventLogger?.log({action:"custom_tap_url_found",category:"configuration",customParams:{stored:n}});let i=n?.state?.tapUrl;if(i)return this.eventLogger?.log({action:"custom_tap_url_used",category:"configuration",customParams:{customTapUrl:i}}),`${i}/chat`}}catch{}return "https://edutap-ai.vercel.app/chat"},Ie=function(){if(!(typeof window>"u"||typeof localStorage>"u"))try{let t=localStorage.getItem("tap-api-url-storage");return t?JSON.parse(t)?.state?.apiUrl:void 0}catch{return}},o(O,"defaultHandshakeOptions",{retryInterval:500,maxRetries:3,timeout:3e4});var D=O;var $=class{constructor(e){this.iframeBridge=e;}seekTimeline({clipId:e,clipPlayHead:t}){this.iframeBridge.postToTap({type:"timeline:seek",clipId:e,clipPlayHead:t});}onTimelineSeek(e){this.iframeBridge.listenToTap("timeline:seek",t=>e(t.clipPlayHead,t.clipId));}onChatOpened(e){this.iframeBridge.listenToTap("chat:opened",e);}onChatClosed(e){this.iframeBridge.listenToTap("chat:closed",e);}onChatInitiated(e){this.iframeBridge.listenToTap("chat:initiated",e);}onAlarmFadeIn(e){this.iframeBridge.listenToTap("alarm:fadeIn",t=>{e(t.messageInfo);});}onPopUpOpen(e){this.iframeBridge.listenToTap("popUp:open",t=>{e(t.popUpInfo);});}onPdfOpen(e){this.iframeBridge.listenToTap("pdf:open",e);}onPdfClose(e){this.iframeBridge.listenToTap("pdf:close",e);}};var Ue="G-27C0E436HL",j=class{constructor(e=Ue){this.gaId=e;this.gaId&&typeof window<"u"&&this.initializeGA(this.gaId);}initializeGA(e){if(document.querySelector(`script[src*="googletagmanager.com/gtag/js?id=${e}"]`))return;let t=document.createElement("script");if(t.async=true,t.src=`https://www.googletagmanager.com/gtag/js?id=${e}`,document.head.appendChild(t),typeof window.gtag!="function"){let n=document.createElement("script");n.innerHTML=`
|
|
19
|
+
window.dataLayer = window.dataLayer || [];
|
|
20
|
+
function gtag(){dataLayer.push(arguments);}
|
|
21
|
+
gtag('js', new Date());
|
|
22
|
+
gtag('config', '${e}');
|
|
23
|
+
`,document.head.appendChild(n);}}handle(e){typeof window.gtag=="function"?window.gtag("event",e.action,{event_category:e.category,event_label:e.label,value:e.value,...e.customParams}):this.gaId&&console.warn("[GAMiddleware] gtag not available, event queued:",e);}},P=class{constructor(e=false){this.enabled=e;}handle(e){this.enabled&&console.log("[TapSDK Event]",e);}},B=class{constructor(){o(this,"middlewares",[]);}addMiddleware(e){this.middlewares.push(e);}removeMiddleware(e){let t=this.middlewares.indexOf(e);t>-1&&this.middlewares.splice(t,1);}log(e){this.middlewares.forEach(t=>{try{t.handle(e);}catch(n){console.warn("[EventLogger] Middleware error:",n);}});}logChatAction(e,t){this.log({action:`chat_${e}`,category:"engagement",customParams:{timestamp:Date.now(),...t}});}logButtonClick(e,t,n){let i={action:`${e}_button_clicked`,category:"user_interaction",customParams:{timestamp:Date.now(),...n}};t!==void 0&&(i.label=t),this.log(i);}logSDKInitialization(e,t,n){let i=Date.now()-t,s={action:"sdk_initialization",category:"system",label:e?"success":"failure",value:i,customParams:{timestamp:Date.now(),...n&&{error:n}}};this.log(s);}};var Te="wu2gm66",Ce="wu2gm67",Ae="wu2gm68";function Xe({htmlString:r,callback:e,customStyles:t}){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 i=document.createElement("div");i.id="wow",i.style.position="fixed",i.style.display="flex",i.style.flexDirection="column";let u=15;if(t?.width){let d=parseFloat(t.width),y=t.width.match(/[a-zA-Z%]+/)?.[0];!isNaN(d)&&y==="px"&&(u+=d);}else u+=340;if(t?.position?.right){let d=parseFloat(t?.position?.right),y=t?.position?.right.match(/[a-zA-Z%]+/)?.[0];!isNaN(d)&&y==="px"&&(u+=d);}else u=u+24;i.style.top=t?.position?.top??"50px",i.style.right=`${u}px`,i.style.left=t?.position?.left??"unset",i.style.bottom=t?.position?.bottom??"unset",i.style.maxWidth="calc(100vw - 100px)",i.style.maxHeight=t?.height??"calc(100vh - 116px)",i.style.overflow="auto",i.style.background="#fff",i.style.padding="20px",i.style.border="1px solid #ccc",i.style.boxShadow="0 4px 20px rgba(0,0,0,0.2)",i.style.zIndex="10000003",i.style.borderRadius="8px";let a=document.createElement("div");a.innerHTML=r,n.addEventListener("click",()=>{document.body.removeChild(n),document.body.removeChild(i),e();}),i.addEventListener("click",d=>{d.stopPropagation();}),i.appendChild(a),document.body.appendChild(n),document.body.appendChild(i);let l=document.querySelector(`.${Te}`),p=document.querySelector(".cw-plugin-code-block"),c=document.querySelector(`.${Ae}`),f=document.querySelector(`.${Ce}`);l&&p&&c&&f&&l.addEventListener("click",()=>{navigator.clipboard.writeText(p.textContent??""),c.style.display="none",f.textContent="\uBCF5\uC0AC\uB428",setTimeout(()=>{f.textContent="\uBCF5\uC0AC",c.style.display="inline";},1e3);});}var Me=Xe;var L,De,K=class{constructor({apiKey:e}){v(this,L);o(this,"apiKey");o(this,"iframeBridge");o(this,"events");o(this,"eventLogger");o(this,"chatBody");o(this,"chatBodyMaker");o(this,"button");o(this,"alarm");o(this,"chatBodyVisible");o(this,"isPdfOpen");o(this,"_isInitialized",false);this.apiKey=e,this.eventLogger=new B,m(this,L,De).call(this),this.iframeBridge=new D({hostOrigin:window.location.origin,apiKey:this.apiKey,eventLogger:this.eventLogger}),this.events=new $(this.iframeBridge),this.button=new ne,this.alarm=new ve,this.chatBodyMaker=new te,this.chatBodyVisible="closed",this.isPdfOpen=false;}get isOpen(){return this.chatBodyVisible==="open"}get isInitialized(){return this._isInitialized}async init({buttonId:e,course:t,customStyles:n}){if(this._isInitialized){this.eventLogger.log({action:"sdk_already_initialized",category:"warning",customParams:{timestamp:Date.now()}});return}let i=Date.now();try{await this.validateEnvironment(),await this.setupChatBody(n),await Promise.all([this.setupButton(e),this.iframeBridge.ensureIframe(this.chatBody)]),this.setupEventListeners(n),await this.iframeBridge.performHandshake({chatApiParams:t,customStyles:n}),this._isInitialized=!0,this.eventLogger.logSDKInitialization(!0,i);}catch(s){let u=s instanceof Error?s.message:"Unknown error";throw this.eventLogger.logSDKInitialization(false,i,u),s}}destroy(){if(!this._isInitialized){this.eventLogger.log({action:"sdk_destroy_not_initialized",category:"warning",customParams:{timestamp:Date.now()}});return}this.chatBodyMaker.removeChatBody(),this.alarm.remove(),this.iframeBridge.removeIframe(),this.chatBody=void 0,this.chatBodyVisible="closed",this._isInitialized=false;}isClient(){return typeof window<"u"&&typeof document<"u"}setChatBodyVisible(e){this.chatBodyVisible=e;}setIsPdfOpen(e){this.isPdfOpen=e;}toggleChatOpen(){let e=this.chatBodyVisible==="open"?"chat:close":"chat:open";try{this.iframeBridge.postToTap({type:e})||this.eventLogger.log({action:"chat_message_send_failed",category:"error",label:e,customParams:{timestamp:Date.now()}});}catch(t){this.eventLogger.log({action:"chat_message_send_error",category:"error",customParams:{messageType:e,error:t instanceof Error?t.message:"Unknown error",timestamp:Date.now()}});}}async validateEnvironment(){if(!this.isClient())throw new Error("Not running in client environment: window is not defined")}async setupChatBody(e){if(!this.chatBody){let t=this.chatBodyMaker.createChatBody({...e?.chatBody&&{customChatBody:e.chatBody}});if(!t)throw new Error("Failed to create chat body");this.chatBody=t;}}async setupButton(e){let t=this.button.create(e);this.button.onClick(async()=>{await this.iframeBridge.ensureIframe(this.chatBody),this.eventLogger.logButtonClick("toggle",this.chatBodyVisible==="open"?"open":"closed"),this.toggleChatOpen();}),this.alarm.render({rootElement:t}),this.alarm.onAlarmClick(n=>{this.eventLogger.logButtonClick("alarm"),this.iframeBridge.postToTap({type:"chat:open",isAlarm:true}),this.iframeBridge.postToTap({type:"alarm:click",messageInfo:n});});}setupEventListeners(e){this.iframeBridge.listenToTap("chat:opened",()=>{this.setChatBodyVisible("open"),this.chatBodyMaker.toggleVisibility(this.chatBodyVisible==="open"),this.alarm.remove(),this.eventLogger.logChatAction("opened");}),this.iframeBridge.listenToTap("chat:closed",()=>{this.setChatBodyVisible("closed"),this.chatBodyMaker.toggleVisibility(this.chatBodyVisible==="open"),this.eventLogger.logChatAction("closed");}),this.iframeBridge.listenToTap("alarm:fadeIn",t=>{this.chatBodyVisible!=="open"&&this.alarm.fadeIn(t.messageInfo);}),this.iframeBridge.listenToTap("popUp:open",t=>{Me({htmlString:t.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.listenToTap("pdf:close",()=>{this.setIsPdfOpen(false),this.chatBodyMaker.resizeChatBody(this.isPdfOpen,e?.chatBody);});}async initChat(e){return this.init(e)}postChatInfo({clipId:e,clipPlayHead:t}){this.events.seekTimeline({clipId:e,clipPlayHead:t});}getTimelineInfo({callback:e}){this.events.onTimelineSeek(e);}};L=new WeakSet,De=function(){if(typeof window>"u"||typeof localStorage>"u")return;localStorage.getItem("tap-environment")==="local"&&this.eventLogger.addMiddleware(new P(true)),this.eventLogger.addMiddleware(new j);};var Kt=K;return Kt;})();//# sourceMappingURL=index.global.js.map
|
|
20
24
|
//# sourceMappingURL=index.global.js.map
|