@coxwave/tap-kit 2.0.1 → 2.0.2
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 +0 -1
- package/dist/index.d.cts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.cts +41 -55
- package/dist/react.d.ts +41 -55
- package/dist/react.js +373 -2
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +366 -2
- package/dist/react.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -180,7 +180,6 @@ npm 없이 CDN으로 직접 사용하려면 [CDN 사용 가이드](https://eduta
|
|
|
180
180
|
|
|
181
181
|
**Props:**
|
|
182
182
|
- `control: TapKitControl` - useTapKit hook에서 반환된 control 객체 (필수)
|
|
183
|
-
- `containerId?: string` - 커스텀 컨테이너 엘리먼트 ID (선택)
|
|
184
183
|
- `style?: CSSProperties` - 인라인 스타일 (선택)
|
|
185
184
|
- `className?: string` - CSS 클래스 (선택)
|
|
186
185
|
- `ref?: Ref<TapKitElement>` - Web Component에 대한 ref (선택)
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _coxwave_tap_kit_types from '@coxwave/tap-kit-types';
|
|
2
2
|
import { TapKitInstance, TapKitConfig, TapKitInitParams, TapButtonAttributes } from '@coxwave/tap-kit-types';
|
|
3
|
-
export { AlarmMessageInstanceType, ContainerConfig,
|
|
3
|
+
export { AlarmMessageInstanceType, ContainerConfig, Course, ITapButtonElement, PositionType, SeekTimelineParamsType, TapButtonAttributes, TapKitConfig, TapKitConstructor, TapKitInitParams, TapKitInstance } from '@coxwave/tap-kit-types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* TapKit - Official TapKit Web SDK
|
|
@@ -60,10 +60,14 @@ declare class TapKit implements TapKitInstance {
|
|
|
60
60
|
*/
|
|
61
61
|
get ready(): Promise<void>;
|
|
62
62
|
/**
|
|
63
|
-
* Create a proxy that
|
|
64
|
-
* before delegating to the actual property
|
|
63
|
+
* Create a proxy for video API that waits for ready before delegating
|
|
65
64
|
*/
|
|
66
|
-
private
|
|
65
|
+
private createVideoProxy;
|
|
66
|
+
/**
|
|
67
|
+
* Create events API that returns unsubscribe functions synchronously
|
|
68
|
+
* Queues the actual subscription until ready, but returns unsubscribe immediately
|
|
69
|
+
*/
|
|
70
|
+
private createEventsProxy;
|
|
67
71
|
get events(): {
|
|
68
72
|
seekTimeline: (params: _coxwave_tap_kit_types.SeekTimelineParamsType) => void;
|
|
69
73
|
onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _coxwave_tap_kit_types from '@coxwave/tap-kit-types';
|
|
2
2
|
import { TapKitInstance, TapKitConfig, TapKitInitParams, TapButtonAttributes } from '@coxwave/tap-kit-types';
|
|
3
|
-
export { AlarmMessageInstanceType, ContainerConfig,
|
|
3
|
+
export { AlarmMessageInstanceType, ContainerConfig, Course, ITapButtonElement, PositionType, SeekTimelineParamsType, TapButtonAttributes, TapKitConfig, TapKitConstructor, TapKitInitParams, TapKitInstance } from '@coxwave/tap-kit-types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* TapKit - Official TapKit Web SDK
|
|
@@ -60,10 +60,14 @@ declare class TapKit implements TapKitInstance {
|
|
|
60
60
|
*/
|
|
61
61
|
get ready(): Promise<void>;
|
|
62
62
|
/**
|
|
63
|
-
* Create a proxy that
|
|
64
|
-
* before delegating to the actual property
|
|
63
|
+
* Create a proxy for video API that waits for ready before delegating
|
|
65
64
|
*/
|
|
66
|
-
private
|
|
65
|
+
private createVideoProxy;
|
|
66
|
+
/**
|
|
67
|
+
* Create events API that returns unsubscribe functions synchronously
|
|
68
|
+
* Queues the actual subscription until ready, but returns unsubscribe immediately
|
|
69
|
+
*/
|
|
70
|
+
private createEventsProxy;
|
|
67
71
|
get events(): {
|
|
68
72
|
seekTimeline: (params: _coxwave_tap_kit_types.SeekTimelineParamsType) => void;
|
|
69
73
|
onTimelineSeek: (callback: (clipPlayHead: number, clipId: string) => void) => () => void;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var I=Object.defineProperty;var
|
|
2
|
-
exports.TapKit=
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var I=Object.defineProperty;var L=i=>{throw TypeError(i)};var m=(i,e,t)=>e in i?I(i,e,{enumerable:true,configurable:true,writable:true,value:t}):i[e]=t;var A=(i,e,t)=>m(i,e+"",t),D=(i,e,t)=>e.has(i)||L("Cannot "+t);var r=(i,e,t)=>(D(i,e,"read from private field"),t?t.call(i):e.get(i)),T=(i,e,t)=>e.has(i)?L("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(i):e.set(i,t),s=(i,e,t,n)=>(D(i,e,"write to private field"),e.set(i,t),t);var v="https://files.edutap.ai/tap-sdk/loader.js";function O(){return window?.__TAP_KIT_LOADER_URL__?window.__TAP_KIT_LOADER_URL__:v}function y(){return typeof window<"u"&&!!window.__TAP_KIT_CORE_URL__}function P(){return window.__TAP_KIT_CORE_URL__||""}function K(i,e,t){let n=Date.now(),a=()=>{if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,i();return}if(Date.now()-n>t){window.__TAP_KIT_LOADER_LOADING__=void 0,e(new Error(`TapKit loader timeout: SDK not available after ${t}ms`));return}typeof requestIdleCallback<"u"?requestIdleCallback(a,{timeout:500}):setTimeout(a,500);};return a}function E(i=4e3){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let e=new Promise((t,n)=>{if(typeof document>"u"){n(new Error("TapKit requires browser environment (document is undefined)"));return}if(y()){if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,t();return}let p=P(),w=document.createElement("script");w.src=p,w.async=true,w.onload=()=>{window.TapKit?(window.TapKitLoaded=true,window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,t()):(window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error("TapKit not available after loading local core")));},w.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error(`Failed to load local TapKit core: ${p}`));},document.head.appendChild(w);return}let a=O(),u=document.createElement("script");u.src=a,u.async=true,u.onload=()=>{K(t,n,i)();},u.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error(`Failed to load TapKit CDN loader: ${a}`));};let f=document.querySelector(`script[src="${a}"]`);f?(f.addEventListener("load",()=>{K(t,n,i)();}),f.addEventListener("error",()=>n(new Error(`Failed to load TapKit CDN loader: ${a}`)))):document.head.appendChild(u);});return window.__TAP_KIT_LOADER_LOADING__=e,e}var d,_,o,c,l,h=class{constructor(e){A(this,"instance",null);T(this,d);T(this,_);T(this,o,null);T(this,c);T(this,l);s(this,_,e),s(this,d,this.load());}async load(){try{if(await E(),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");this.instance=new window.TapKit(r(this,_));}catch(e){throw s(this,o,e instanceof Error?e:new Error(String(e))),r(this,o)}}get loaded(){return r(this,d).then(()=>{if(r(this,o))throw r(this,o);if(!this.instance)throw new Error(`TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${r(this,_).apiKey}`)})}get ready(){return r(this,d).then(()=>{if(r(this,o))throw r(this,o);if(!this.instance)throw new Error(`TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${r(this,_).apiKey}`);return this.instance.ready})}createVideoProxy(){return {bind:(e,t)=>{this.ready.then(()=>{this.instance?.video.bind(e,t);});},unbind:()=>{this.instance?.video?.unbind();}}}createEventsProxy(){return {seekTimeline:e=>{this.ready.then(()=>{this.instance?.events.seekTimeline(e);});},onTimelineSeek:e=>{let t,n=false;return this.ready.then(()=>{n||(t=this.instance?.events.onTimelineSeek(e));}),()=>{n=true,t?.();}},onAlarmFadeIn:e=>{let t,n=false;return this.ready.then(()=>{n||(t=this.instance?.events.onAlarmFadeIn(e));}),()=>{n=true,t?.();}}}}get events(){return r(this,c)||s(this,c,this.createEventsProxy()),r(this,c)}get isOpen(){return this.instance?.isOpen??false}get isInitialized(){return this.instance?.isInitialized??false}get video(){return r(this,l)||s(this,l,this.createVideoProxy()),r(this,l)}async init(e){if(await r(this,d),!this.instance)throw new Error("TapKit instance not available after loading");return await this.instance.init(e)}destroy(){this.instance&&(this.instance.destroy(),this.instance=null),s(this,c,void 0),s(this,l,void 0);}show(){this.instance&&this.instance.show();}hide(){this.instance&&this.instance.hide();}get[Symbol.toStringTag](){return "TapKit"}};d=new WeakMap,_=new WeakMap,o=new WeakMap,c=new WeakMap,l=new WeakMap;
|
|
2
|
+
exports.TapKit=h;exports.default=h;//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loader.ts","../src/kit.ts"],"names":["DEFAULT_CDN_LOADER_URL","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","_loading","_config","_loadError","_eventsProxy","_videoProxy","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","propertyName","_target","prop","args","method","params"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * CDN loader for TapKit\n * Dynamically loads the TapKit SDK from CDN\n *\n * For local testing, you can override the loader URL:\n * window.__TAP_KIT_LOADER_URL__ = '/tap-kit-core/loader.js';\n *\n * For local development (bypass loader, load IIFE directly):\n * window.__TAP_KIT_CORE_URL__ = '/packages/tap-kit-core/dist/index.global.js';\n */\n\n// Build-time constant injected by tsup define\ndeclare const __DEFAULT_CDN_LOADER_URL__: string;\n\nconst DEFAULT_CDN_LOADER_URL =\n typeof __DEFAULT_CDN_LOADER_URL__ !== \"undefined\"\n ? __DEFAULT_CDN_LOADER_URL__\n : \"https://files.edutap.ai/tap-sdk/loader.js\";\nconst DEFAULT_TIMEOUT_MS = 4000; // 4 seconds total timeout\nconst IDLE_CALLBACK_TIMEOUT_MS = 500; // 500ms for requestIdleCallback\n\n/**\n * Get the loader URL from window override or default CDN\n */\nfunction getLoaderURL(): string {\n return window?.__TAP_KIT_LOADER_URL__\n ? window.__TAP_KIT_LOADER_URL__\n : DEFAULT_CDN_LOADER_URL;\n}\n\n/**\n * Check if local core mode is enabled\n * When __TAP_KIT_CORE_URL__ is set, directly load the IIFE bundle\n * This bypasses the loader.js and loads tap-kit-core directly\n */\nfunction isLocalCoreMode(): boolean {\n return typeof window !== \"undefined\" && !!window.__TAP_KIT_CORE_URL__;\n}\n\n/**\n * Get the local core URL\n */\nfunction getLocalCoreURL(): string {\n return window.__TAP_KIT_CORE_URL__ || \"\";\n}\n\n/**\n * Creates a SDK checker function with timeout and retry logic\n * Uses requestIdleCallback to avoid blocking browser rendering\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n * @param timeoutMs - Maximum time to wait for SDK to load (milliseconds)\n * @returns Checker function to be called repeatedly\n */\nfunction createSDKChecker(\n resolve: (value: void | PromiseLike<void>) => void,\n reject: (reason?: unknown) => void,\n timeoutMs: number,\n): () => void {\n const startTime = Date.now();\n\n const checkSDK = (): void => {\n // Check if real TapKit is loaded (not just stub)\n // Stub has TapKitLoaded flag set to true by loader.js after real SDK loads\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const elapsed = Date.now() - startTime;\n\n // Check if exceeded timeout\n if (elapsed > timeoutMs) {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(\n new Error(\n `TapKit loader timeout: SDK not available after ${timeoutMs}ms`,\n ),\n );\n return;\n }\n\n // Use requestIdleCallback for better performance\n // Falls back to setTimeout if not available\n if (typeof requestIdleCallback !== \"undefined\") {\n requestIdleCallback(checkSDK, { timeout: IDLE_CALLBACK_TIMEOUT_MS });\n } else {\n setTimeout(checkSDK, IDLE_CALLBACK_TIMEOUT_MS);\n }\n };\n\n return checkSDK;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n *\n * If __TAP_KIT_CORE_URL__ is set, bypasses loader and loads IIFE directly\n *\n * @param timeoutMs - Maximum time to wait for SDK to load (default: 4000ms)\n * @returns Promise that resolves when SDK is loaded\n * @throws {Error} If loader fails to load or times out\n */\nexport function loadCDNLoader(\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\n \"TapKit requires browser environment (document is undefined)\",\n ),\n );\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\n // Check if TapKit is already loaded (from other pages in playground)\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const coreURL = getLocalCoreURL();\n\n const script = document.createElement(\"script\");\n script.src = coreURL;\n script.async = true;\n\n script.onload = () => {\n // IIFE directly sets window.TapKit\n // Set the loaded flag manually since we bypass loader.js\n if (window.TapKit) {\n window.TapKitLoaded = true;\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(\"TapKit not available after loading local core\"));\n }\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load local TapKit core: ${coreURL}`));\n };\n\n document.head.appendChild(script);\n return;\n }\n\n // CDN mode: Load loader.js\n const loaderURL = getLoaderURL();\n const script = document.createElement(\"script\");\n script.src = loaderURL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${loaderURL}\"]`);\n\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`)),\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n","import type {\n TapKitConfig,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/**\n * TapKit - Official TapKit Web SDK\n *\n * @example\n * ```typescript\n * import TapKit from \"@coxwave/tap-kit\";\n *\n * const kit = new TapKit({ apiKey: 'your-api-key' });\n *\n * await kit.init({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * container: {\n * position: { top: '64px', right: '32px' },\n * width: '360px',\n * height: 'calc(100% - 128px)',\n * },\n * });\n * ```\n */\nexport class TapKit implements TapKitInstance {\n private instance: TapKitInstance | null = null;\n #loading: Promise<void>;\n #config: TapKitConfig;\n #loadError: Error | null = null;\n #eventsProxy?: TapKitInstance[\"events\"]; // Cached proxy for events API\n #videoProxy?: TapKitInstance[\"video\"]; // Cached proxy for video API\n\n constructor(config: TapKitConfig) {\n this.#config = config;\n this.#loading = this.load();\n }\n\n private async load(): Promise<void> {\n try {\n await loadCDNLoader();\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n this.instance = new window.TapKit(this.#config);\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\n\n /**\n * Promise that resolves when CDN is loaded and TapKit instance is available\n * (ready to call init())\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.loaded; // CDN downloaded, window.TapKit available\n * await kit.init({...}); // Now safe to call init()\n * ```\n *\n * @see ready - For waiting until AFTER init() completes (iframe initialized)\n */\n get loaded(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n });\n }\n\n /**\n * Promise that resolves when SDK is fully initialized\n * (after init() is called and iframe is ready)\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.init({...});\n * await kit.ready; // iframe is fully initialized\n * ```\n *\n * @see loaded - For waiting until CDN load completes (before init)\n */\n get ready(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n return this.instance.ready;\n });\n }\n\n /**\n * Create a proxy that automatically waits for the instance to be ready\n * before delegating to the actual property\n */\n private createReadyProxy<T extends object>(\n propertyName: \"events\" | \"video\",\n ): T {\n return new Proxy({} as T, {\n get: (_target, prop: string) => {\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic method signature unknown at compile time\n return (...args: any[]) => {\n return this.ready.then(() => {\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic property access requires any\n const method = (this.instance?.[propertyName] as any)?.[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n }) as T;\n }\n\n get events() {\n // Cache proxy to avoid creating new Proxy object on every access\n if (!this.#eventsProxy) {\n this.#eventsProxy =\n this.createReadyProxy<TapKitInstance[\"events\"]>(\"events\");\n }\n return this.#eventsProxy;\n }\n\n get isOpen(): boolean {\n return this.instance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.instance?.isInitialized ?? false;\n }\n\n get video() {\n // Cache proxy to avoid creating new Proxy object on every access\n if (!this.#videoProxy) {\n this.#videoProxy =\n this.createReadyProxy<TapKitInstance[\"video\"]>(\"video\");\n }\n return this.#videoProxy;\n }\n\n async init(params: TapKitInitParams): Promise<() => void> {\n await this.#loading;\n if (!this.instance) {\n throw new Error(\"TapKit instance not available after loading\");\n }\n return await this.instance.init(params);\n }\n\n destroy(): void {\n if (this.instance) {\n this.instance.destroy();\n this.instance = null;\n }\n // Clear proxy references to prevent memory leaks\n this.#eventsProxy = undefined;\n this.#videoProxy = undefined;\n }\n\n show(): void {\n if (this.instance) {\n this.instance.show();\n }\n }\n\n hide(): void {\n if (this.instance) {\n this.instance.hide();\n }\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/loader.ts","../src/kit.ts"],"names":["DEFAULT_CDN_LOADER_URL","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","_loading","_config","_loadError","_eventsProxy","_videoProxy","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","clipId","params","callback","unsubscribe","cancelled","handler"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * CDN loader for TapKit\n * Dynamically loads the TapKit SDK from CDN\n *\n * For local testing, you can override the loader URL:\n * window.__TAP_KIT_LOADER_URL__ = '/tap-kit-core/loader.js';\n *\n * For local development (bypass loader, load IIFE directly):\n * window.__TAP_KIT_CORE_URL__ = '/packages/tap-kit-core/dist/index.global.js';\n */\n\n// Build-time constant injected by tsup define\ndeclare const __DEFAULT_CDN_LOADER_URL__: string;\n\nconst DEFAULT_CDN_LOADER_URL =\n typeof __DEFAULT_CDN_LOADER_URL__ !== \"undefined\"\n ? __DEFAULT_CDN_LOADER_URL__\n : \"https://files.edutap.ai/tap-sdk/loader.js\";\nconst DEFAULT_TIMEOUT_MS = 4000; // 4 seconds total timeout\nconst IDLE_CALLBACK_TIMEOUT_MS = 500; // 500ms for requestIdleCallback\n\n/**\n * Get the loader URL from window override or default CDN\n */\nfunction getLoaderURL(): string {\n return window?.__TAP_KIT_LOADER_URL__\n ? window.__TAP_KIT_LOADER_URL__\n : DEFAULT_CDN_LOADER_URL;\n}\n\n/**\n * Check if local core mode is enabled\n * When __TAP_KIT_CORE_URL__ is set, directly load the IIFE bundle\n * This bypasses the loader.js and loads tap-kit-core directly\n */\nfunction isLocalCoreMode(): boolean {\n return typeof window !== \"undefined\" && !!window.__TAP_KIT_CORE_URL__;\n}\n\n/**\n * Get the local core URL\n */\nfunction getLocalCoreURL(): string {\n return window.__TAP_KIT_CORE_URL__ || \"\";\n}\n\n/**\n * Creates a SDK checker function with timeout and retry logic\n * Uses requestIdleCallback to avoid blocking browser rendering\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n * @param timeoutMs - Maximum time to wait for SDK to load (milliseconds)\n * @returns Checker function to be called repeatedly\n */\nfunction createSDKChecker(\n resolve: (value: void | PromiseLike<void>) => void,\n reject: (reason?: unknown) => void,\n timeoutMs: number,\n): () => void {\n const startTime = Date.now();\n\n const checkSDK = (): void => {\n // Check if real TapKit is loaded (not just stub)\n // Stub has TapKitLoaded flag set to true by loader.js after real SDK loads\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const elapsed = Date.now() - startTime;\n\n // Check if exceeded timeout\n if (elapsed > timeoutMs) {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(\n new Error(\n `TapKit loader timeout: SDK not available after ${timeoutMs}ms`,\n ),\n );\n return;\n }\n\n // Use requestIdleCallback for better performance\n // Falls back to setTimeout if not available\n if (typeof requestIdleCallback !== \"undefined\") {\n requestIdleCallback(checkSDK, { timeout: IDLE_CALLBACK_TIMEOUT_MS });\n } else {\n setTimeout(checkSDK, IDLE_CALLBACK_TIMEOUT_MS);\n }\n };\n\n return checkSDK;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n *\n * If __TAP_KIT_CORE_URL__ is set, bypasses loader and loads IIFE directly\n *\n * @param timeoutMs - Maximum time to wait for SDK to load (default: 4000ms)\n * @returns Promise that resolves when SDK is loaded\n * @throws {Error} If loader fails to load or times out\n */\nexport function loadCDNLoader(\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\n \"TapKit requires browser environment (document is undefined)\",\n ),\n );\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\n // Check if TapKit is already loaded (from other pages in playground)\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const coreURL = getLocalCoreURL();\n\n const script = document.createElement(\"script\");\n script.src = coreURL;\n script.async = true;\n\n script.onload = () => {\n // IIFE directly sets window.TapKit\n // Set the loaded flag manually since we bypass loader.js\n if (window.TapKit) {\n window.TapKitLoaded = true;\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(\"TapKit not available after loading local core\"));\n }\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load local TapKit core: ${coreURL}`));\n };\n\n document.head.appendChild(script);\n return;\n }\n\n // CDN mode: Load loader.js\n const loaderURL = getLoaderURL();\n const script = document.createElement(\"script\");\n script.src = loaderURL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${loaderURL}\"]`);\n\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`)),\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n","import type {\n TapKitConfig,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/**\n * TapKit - Official TapKit Web SDK\n *\n * @example\n * ```typescript\n * import TapKit from \"@coxwave/tap-kit\";\n *\n * const kit = new TapKit({ apiKey: 'your-api-key' });\n *\n * await kit.init({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * container: {\n * position: { top: '64px', right: '32px' },\n * width: '360px',\n * height: 'calc(100% - 128px)',\n * },\n * });\n * ```\n */\nexport class TapKit implements TapKitInstance {\n private instance: TapKitInstance | null = null;\n #loading: Promise<void>;\n #config: TapKitConfig;\n #loadError: Error | null = null;\n #eventsProxy?: TapKitInstance[\"events\"]; // Cached proxy for events API\n #videoProxy?: TapKitInstance[\"video\"]; // Cached proxy for video API\n\n constructor(config: TapKitConfig) {\n this.#config = config;\n this.#loading = this.load();\n }\n\n private async load(): Promise<void> {\n try {\n await loadCDNLoader();\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n this.instance = new window.TapKit(this.#config);\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\n\n /**\n * Promise that resolves when CDN is loaded and TapKit instance is available\n * (ready to call init())\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.loaded; // CDN downloaded, window.TapKit available\n * await kit.init({...}); // Now safe to call init()\n * ```\n *\n * @see ready - For waiting until AFTER init() completes (iframe initialized)\n */\n get loaded(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n });\n }\n\n /**\n * Promise that resolves when SDK is fully initialized\n * (after init() is called and iframe is ready)\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.init({...});\n * await kit.ready; // iframe is fully initialized\n * ```\n *\n * @see loaded - For waiting until CDN load completes (before init)\n */\n get ready(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n return this.instance.ready;\n });\n }\n\n /**\n * Create a proxy for video API that waits for ready before delegating\n */\n private createVideoProxy(): TapKitInstance[\"video\"] {\n return {\n bind: (config, clipId) => {\n // Queue the bind call - will execute after ready\n this.ready.then(() => {\n this.instance?.video.bind(config, clipId);\n });\n },\n unbind: () => {\n // Unbind can be called immediately if instance exists\n this.instance?.video?.unbind();\n },\n };\n }\n\n /**\n * Create events API that returns unsubscribe functions synchronously\n * Queues the actual subscription until ready, but returns unsubscribe immediately\n */\n private createEventsProxy(): TapKitInstance[\"events\"] {\n return {\n seekTimeline: (params) => {\n this.ready.then(() => {\n this.instance?.events.seekTimeline(params);\n });\n },\n onTimelineSeek: (callback) => {\n let unsubscribe: (() => void) | undefined;\n let cancelled = false;\n\n // Queue subscription\n this.ready.then(() => {\n if (cancelled) return;\n unsubscribe = this.instance?.events.onTimelineSeek(callback);\n });\n\n // Return synchronous unsubscribe function\n return () => {\n cancelled = true;\n unsubscribe?.();\n };\n },\n onAlarmFadeIn: (handler) => {\n let unsubscribe: (() => void) | undefined;\n let cancelled = false;\n\n this.ready.then(() => {\n if (cancelled) return;\n unsubscribe = this.instance?.events.onAlarmFadeIn(handler);\n });\n\n return () => {\n cancelled = true;\n unsubscribe?.();\n };\n },\n };\n }\n\n get events() {\n // Cache proxy to avoid creating new object on every access\n if (!this.#eventsProxy) {\n this.#eventsProxy = this.createEventsProxy();\n }\n return this.#eventsProxy;\n }\n\n get isOpen(): boolean {\n return this.instance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.instance?.isInitialized ?? false;\n }\n\n get video() {\n // Cache proxy to avoid creating new object on every access\n if (!this.#videoProxy) {\n this.#videoProxy = this.createVideoProxy();\n }\n return this.#videoProxy;\n }\n\n async init(params: TapKitInitParams): Promise<() => void> {\n await this.#loading;\n if (!this.instance) {\n throw new Error(\"TapKit instance not available after loading\");\n }\n return await this.instance.init(params);\n }\n\n destroy(): void {\n if (this.instance) {\n this.instance.destroy();\n this.instance = null;\n }\n // Clear proxy references to prevent memory leaks\n this.#eventsProxy = undefined;\n this.#videoProxy = undefined;\n }\n\n show(): void {\n if (this.instance) {\n this.instance.show();\n }\n }\n\n hide(): void {\n if (this.instance) {\n this.instance.hide();\n }\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var I=Object.defineProperty;var
|
|
2
|
-
export{
|
|
1
|
+
var I=Object.defineProperty;var L=i=>{throw TypeError(i)};var m=(i,e,t)=>e in i?I(i,e,{enumerable:true,configurable:true,writable:true,value:t}):i[e]=t;var A=(i,e,t)=>m(i,e+"",t),D=(i,e,t)=>e.has(i)||L("Cannot "+t);var r=(i,e,t)=>(D(i,e,"read from private field"),t?t.call(i):e.get(i)),T=(i,e,t)=>e.has(i)?L("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(i):e.set(i,t),s=(i,e,t,n)=>(D(i,e,"write to private field"),e.set(i,t),t);var v="https://files.edutap.ai/tap-sdk/loader.js";function O(){return window?.__TAP_KIT_LOADER_URL__?window.__TAP_KIT_LOADER_URL__:v}function y(){return typeof window<"u"&&!!window.__TAP_KIT_CORE_URL__}function P(){return window.__TAP_KIT_CORE_URL__||""}function K(i,e,t){let n=Date.now(),a=()=>{if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,i();return}if(Date.now()-n>t){window.__TAP_KIT_LOADER_LOADING__=void 0,e(new Error(`TapKit loader timeout: SDK not available after ${t}ms`));return}typeof requestIdleCallback<"u"?requestIdleCallback(a,{timeout:500}):setTimeout(a,500);};return a}function E(i=4e3){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let e=new Promise((t,n)=>{if(typeof document>"u"){n(new Error("TapKit requires browser environment (document is undefined)"));return}if(y()){if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,t();return}let p=P(),w=document.createElement("script");w.src=p,w.async=true,w.onload=()=>{window.TapKit?(window.TapKitLoaded=true,window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,t()):(window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error("TapKit not available after loading local core")));},w.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error(`Failed to load local TapKit core: ${p}`));},document.head.appendChild(w);return}let a=O(),u=document.createElement("script");u.src=a,u.async=true,u.onload=()=>{K(t,n,i)();},u.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error(`Failed to load TapKit CDN loader: ${a}`));};let f=document.querySelector(`script[src="${a}"]`);f?(f.addEventListener("load",()=>{K(t,n,i)();}),f.addEventListener("error",()=>n(new Error(`Failed to load TapKit CDN loader: ${a}`)))):document.head.appendChild(u);});return window.__TAP_KIT_LOADER_LOADING__=e,e}var d,_,o,c,l,h=class{constructor(e){A(this,"instance",null);T(this,d);T(this,_);T(this,o,null);T(this,c);T(this,l);s(this,_,e),s(this,d,this.load());}async load(){try{if(await E(),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");this.instance=new window.TapKit(r(this,_));}catch(e){throw s(this,o,e instanceof Error?e:new Error(String(e))),r(this,o)}}get loaded(){return r(this,d).then(()=>{if(r(this,o))throw r(this,o);if(!this.instance)throw new Error(`TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${r(this,_).apiKey}`)})}get ready(){return r(this,d).then(()=>{if(r(this,o))throw r(this,o);if(!this.instance)throw new Error(`TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${r(this,_).apiKey}`);return this.instance.ready})}createVideoProxy(){return {bind:(e,t)=>{this.ready.then(()=>{this.instance?.video.bind(e,t);});},unbind:()=>{this.instance?.video?.unbind();}}}createEventsProxy(){return {seekTimeline:e=>{this.ready.then(()=>{this.instance?.events.seekTimeline(e);});},onTimelineSeek:e=>{let t,n=false;return this.ready.then(()=>{n||(t=this.instance?.events.onTimelineSeek(e));}),()=>{n=true,t?.();}},onAlarmFadeIn:e=>{let t,n=false;return this.ready.then(()=>{n||(t=this.instance?.events.onAlarmFadeIn(e));}),()=>{n=true,t?.();}}}}get events(){return r(this,c)||s(this,c,this.createEventsProxy()),r(this,c)}get isOpen(){return this.instance?.isOpen??false}get isInitialized(){return this.instance?.isInitialized??false}get video(){return r(this,l)||s(this,l,this.createVideoProxy()),r(this,l)}async init(e){if(await r(this,d),!this.instance)throw new Error("TapKit instance not available after loading");return await this.instance.init(e)}destroy(){this.instance&&(this.instance.destroy(),this.instance=null),s(this,c,void 0),s(this,l,void 0);}show(){this.instance&&this.instance.show();}hide(){this.instance&&this.instance.hide();}get[Symbol.toStringTag](){return "TapKit"}};d=new WeakMap,_=new WeakMap,o=new WeakMap,c=new WeakMap,l=new WeakMap;
|
|
2
|
+
export{h as TapKit,h as default};//# sourceMappingURL=index.mjs.map
|
|
3
3
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loader.ts","../src/kit.ts"],"names":["DEFAULT_CDN_LOADER_URL","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","_loading","_config","_loadError","_eventsProxy","_videoProxy","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","propertyName","_target","prop","args","method","params"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * CDN loader for TapKit\n * Dynamically loads the TapKit SDK from CDN\n *\n * For local testing, you can override the loader URL:\n * window.__TAP_KIT_LOADER_URL__ = '/tap-kit-core/loader.js';\n *\n * For local development (bypass loader, load IIFE directly):\n * window.__TAP_KIT_CORE_URL__ = '/packages/tap-kit-core/dist/index.global.js';\n */\n\n// Build-time constant injected by tsup define\ndeclare const __DEFAULT_CDN_LOADER_URL__: string;\n\nconst DEFAULT_CDN_LOADER_URL =\n typeof __DEFAULT_CDN_LOADER_URL__ !== \"undefined\"\n ? __DEFAULT_CDN_LOADER_URL__\n : \"https://files.edutap.ai/tap-sdk/loader.js\";\nconst DEFAULT_TIMEOUT_MS = 4000; // 4 seconds total timeout\nconst IDLE_CALLBACK_TIMEOUT_MS = 500; // 500ms for requestIdleCallback\n\n/**\n * Get the loader URL from window override or default CDN\n */\nfunction getLoaderURL(): string {\n return window?.__TAP_KIT_LOADER_URL__\n ? window.__TAP_KIT_LOADER_URL__\n : DEFAULT_CDN_LOADER_URL;\n}\n\n/**\n * Check if local core mode is enabled\n * When __TAP_KIT_CORE_URL__ is set, directly load the IIFE bundle\n * This bypasses the loader.js and loads tap-kit-core directly\n */\nfunction isLocalCoreMode(): boolean {\n return typeof window !== \"undefined\" && !!window.__TAP_KIT_CORE_URL__;\n}\n\n/**\n * Get the local core URL\n */\nfunction getLocalCoreURL(): string {\n return window.__TAP_KIT_CORE_URL__ || \"\";\n}\n\n/**\n * Creates a SDK checker function with timeout and retry logic\n * Uses requestIdleCallback to avoid blocking browser rendering\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n * @param timeoutMs - Maximum time to wait for SDK to load (milliseconds)\n * @returns Checker function to be called repeatedly\n */\nfunction createSDKChecker(\n resolve: (value: void | PromiseLike<void>) => void,\n reject: (reason?: unknown) => void,\n timeoutMs: number,\n): () => void {\n const startTime = Date.now();\n\n const checkSDK = (): void => {\n // Check if real TapKit is loaded (not just stub)\n // Stub has TapKitLoaded flag set to true by loader.js after real SDK loads\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const elapsed = Date.now() - startTime;\n\n // Check if exceeded timeout\n if (elapsed > timeoutMs) {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(\n new Error(\n `TapKit loader timeout: SDK not available after ${timeoutMs}ms`,\n ),\n );\n return;\n }\n\n // Use requestIdleCallback for better performance\n // Falls back to setTimeout if not available\n if (typeof requestIdleCallback !== \"undefined\") {\n requestIdleCallback(checkSDK, { timeout: IDLE_CALLBACK_TIMEOUT_MS });\n } else {\n setTimeout(checkSDK, IDLE_CALLBACK_TIMEOUT_MS);\n }\n };\n\n return checkSDK;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n *\n * If __TAP_KIT_CORE_URL__ is set, bypasses loader and loads IIFE directly\n *\n * @param timeoutMs - Maximum time to wait for SDK to load (default: 4000ms)\n * @returns Promise that resolves when SDK is loaded\n * @throws {Error} If loader fails to load or times out\n */\nexport function loadCDNLoader(\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\n \"TapKit requires browser environment (document is undefined)\",\n ),\n );\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\n // Check if TapKit is already loaded (from other pages in playground)\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const coreURL = getLocalCoreURL();\n\n const script = document.createElement(\"script\");\n script.src = coreURL;\n script.async = true;\n\n script.onload = () => {\n // IIFE directly sets window.TapKit\n // Set the loaded flag manually since we bypass loader.js\n if (window.TapKit) {\n window.TapKitLoaded = true;\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(\"TapKit not available after loading local core\"));\n }\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load local TapKit core: ${coreURL}`));\n };\n\n document.head.appendChild(script);\n return;\n }\n\n // CDN mode: Load loader.js\n const loaderURL = getLoaderURL();\n const script = document.createElement(\"script\");\n script.src = loaderURL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${loaderURL}\"]`);\n\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`)),\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n","import type {\n TapKitConfig,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/**\n * TapKit - Official TapKit Web SDK\n *\n * @example\n * ```typescript\n * import TapKit from \"@coxwave/tap-kit\";\n *\n * const kit = new TapKit({ apiKey: 'your-api-key' });\n *\n * await kit.init({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * container: {\n * position: { top: '64px', right: '32px' },\n * width: '360px',\n * height: 'calc(100% - 128px)',\n * },\n * });\n * ```\n */\nexport class TapKit implements TapKitInstance {\n private instance: TapKitInstance | null = null;\n #loading: Promise<void>;\n #config: TapKitConfig;\n #loadError: Error | null = null;\n #eventsProxy?: TapKitInstance[\"events\"]; // Cached proxy for events API\n #videoProxy?: TapKitInstance[\"video\"]; // Cached proxy for video API\n\n constructor(config: TapKitConfig) {\n this.#config = config;\n this.#loading = this.load();\n }\n\n private async load(): Promise<void> {\n try {\n await loadCDNLoader();\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n this.instance = new window.TapKit(this.#config);\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\n\n /**\n * Promise that resolves when CDN is loaded and TapKit instance is available\n * (ready to call init())\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.loaded; // CDN downloaded, window.TapKit available\n * await kit.init({...}); // Now safe to call init()\n * ```\n *\n * @see ready - For waiting until AFTER init() completes (iframe initialized)\n */\n get loaded(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n });\n }\n\n /**\n * Promise that resolves when SDK is fully initialized\n * (after init() is called and iframe is ready)\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.init({...});\n * await kit.ready; // iframe is fully initialized\n * ```\n *\n * @see loaded - For waiting until CDN load completes (before init)\n */\n get ready(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n return this.instance.ready;\n });\n }\n\n /**\n * Create a proxy that automatically waits for the instance to be ready\n * before delegating to the actual property\n */\n private createReadyProxy<T extends object>(\n propertyName: \"events\" | \"video\",\n ): T {\n return new Proxy({} as T, {\n get: (_target, prop: string) => {\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic method signature unknown at compile time\n return (...args: any[]) => {\n return this.ready.then(() => {\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic property access requires any\n const method = (this.instance?.[propertyName] as any)?.[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n }) as T;\n }\n\n get events() {\n // Cache proxy to avoid creating new Proxy object on every access\n if (!this.#eventsProxy) {\n this.#eventsProxy =\n this.createReadyProxy<TapKitInstance[\"events\"]>(\"events\");\n }\n return this.#eventsProxy;\n }\n\n get isOpen(): boolean {\n return this.instance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.instance?.isInitialized ?? false;\n }\n\n get video() {\n // Cache proxy to avoid creating new Proxy object on every access\n if (!this.#videoProxy) {\n this.#videoProxy =\n this.createReadyProxy<TapKitInstance[\"video\"]>(\"video\");\n }\n return this.#videoProxy;\n }\n\n async init(params: TapKitInitParams): Promise<() => void> {\n await this.#loading;\n if (!this.instance) {\n throw new Error(\"TapKit instance not available after loading\");\n }\n return await this.instance.init(params);\n }\n\n destroy(): void {\n if (this.instance) {\n this.instance.destroy();\n this.instance = null;\n }\n // Clear proxy references to prevent memory leaks\n this.#eventsProxy = undefined;\n this.#videoProxy = undefined;\n }\n\n show(): void {\n if (this.instance) {\n this.instance.show();\n }\n }\n\n hide(): void {\n if (this.instance) {\n this.instance.hide();\n }\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/loader.ts","../src/kit.ts"],"names":["DEFAULT_CDN_LOADER_URL","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","_loading","_config","_loadError","_eventsProxy","_videoProxy","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","clipId","params","callback","unsubscribe","cancelled","handler"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * CDN loader for TapKit\n * Dynamically loads the TapKit SDK from CDN\n *\n * For local testing, you can override the loader URL:\n * window.__TAP_KIT_LOADER_URL__ = '/tap-kit-core/loader.js';\n *\n * For local development (bypass loader, load IIFE directly):\n * window.__TAP_KIT_CORE_URL__ = '/packages/tap-kit-core/dist/index.global.js';\n */\n\n// Build-time constant injected by tsup define\ndeclare const __DEFAULT_CDN_LOADER_URL__: string;\n\nconst DEFAULT_CDN_LOADER_URL =\n typeof __DEFAULT_CDN_LOADER_URL__ !== \"undefined\"\n ? __DEFAULT_CDN_LOADER_URL__\n : \"https://files.edutap.ai/tap-sdk/loader.js\";\nconst DEFAULT_TIMEOUT_MS = 4000; // 4 seconds total timeout\nconst IDLE_CALLBACK_TIMEOUT_MS = 500; // 500ms for requestIdleCallback\n\n/**\n * Get the loader URL from window override or default CDN\n */\nfunction getLoaderURL(): string {\n return window?.__TAP_KIT_LOADER_URL__\n ? window.__TAP_KIT_LOADER_URL__\n : DEFAULT_CDN_LOADER_URL;\n}\n\n/**\n * Check if local core mode is enabled\n * When __TAP_KIT_CORE_URL__ is set, directly load the IIFE bundle\n * This bypasses the loader.js and loads tap-kit-core directly\n */\nfunction isLocalCoreMode(): boolean {\n return typeof window !== \"undefined\" && !!window.__TAP_KIT_CORE_URL__;\n}\n\n/**\n * Get the local core URL\n */\nfunction getLocalCoreURL(): string {\n return window.__TAP_KIT_CORE_URL__ || \"\";\n}\n\n/**\n * Creates a SDK checker function with timeout and retry logic\n * Uses requestIdleCallback to avoid blocking browser rendering\n * @param resolve - Promise resolve function\n * @param reject - Promise reject function\n * @param timeoutMs - Maximum time to wait for SDK to load (milliseconds)\n * @returns Checker function to be called repeatedly\n */\nfunction createSDKChecker(\n resolve: (value: void | PromiseLike<void>) => void,\n reject: (reason?: unknown) => void,\n timeoutMs: number,\n): () => void {\n const startTime = Date.now();\n\n const checkSDK = (): void => {\n // Check if real TapKit is loaded (not just stub)\n // Stub has TapKitLoaded flag set to true by loader.js after real SDK loads\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const elapsed = Date.now() - startTime;\n\n // Check if exceeded timeout\n if (elapsed > timeoutMs) {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(\n new Error(\n `TapKit loader timeout: SDK not available after ${timeoutMs}ms`,\n ),\n );\n return;\n }\n\n // Use requestIdleCallback for better performance\n // Falls back to setTimeout if not available\n if (typeof requestIdleCallback !== \"undefined\") {\n requestIdleCallback(checkSDK, { timeout: IDLE_CALLBACK_TIMEOUT_MS });\n } else {\n setTimeout(checkSDK, IDLE_CALLBACK_TIMEOUT_MS);\n }\n };\n\n return checkSDK;\n}\n\n/**\n * Loads the CDN loader script\n * The loader will then fetch versions.json and load the appropriate SDK version\n *\n * If __TAP_KIT_CORE_URL__ is set, bypasses loader and loads IIFE directly\n *\n * @param timeoutMs - Maximum time to wait for SDK to load (default: 4000ms)\n * @returns Promise that resolves when SDK is loaded\n * @throws {Error} If loader fails to load or times out\n */\nexport function loadCDNLoader(\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n): Promise<void> {\n // If already loaded, return immediately\n if (window.__TAP_KIT_LOADER_LOADED__ && window.TapKit) {\n return Promise.resolve();\n }\n\n // If currently loading, return the existing promise\n if (window.__TAP_KIT_LOADER_LOADING__) {\n return window.__TAP_KIT_LOADER_LOADING__;\n }\n\n // Create loading promise\n const loadingPromise = new Promise<void>((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(\n new Error(\n \"TapKit requires browser environment (document is undefined)\",\n ),\n );\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\n // Check if TapKit is already loaded (from other pages in playground)\n if (window.TapKit && window.TapKitLoaded === true) {\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n return;\n }\n\n const coreURL = getLocalCoreURL();\n\n const script = document.createElement(\"script\");\n script.src = coreURL;\n script.async = true;\n\n script.onload = () => {\n // IIFE directly sets window.TapKit\n // Set the loaded flag manually since we bypass loader.js\n if (window.TapKit) {\n window.TapKitLoaded = true;\n window.__TAP_KIT_LOADER_LOADED__ = true;\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n resolve();\n } else {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(\"TapKit not available after loading local core\"));\n }\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load local TapKit core: ${coreURL}`));\n };\n\n document.head.appendChild(script);\n return;\n }\n\n // CDN mode: Load loader.js\n const loaderURL = getLoaderURL();\n const script = document.createElement(\"script\");\n script.src = loaderURL;\n script.async = true;\n\n script.onload = () => {\n // The loader script will load the actual SDK\n // We need to wait a bit for the loader to fetch and load the SDK\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n };\n\n script.onerror = () => {\n window.__TAP_KIT_LOADER_LOADING__ = undefined;\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`));\n };\n\n // Check if script already exists\n const existingScript = document.querySelector(`script[src=\"${loaderURL}\"]`);\n\n if (existingScript) {\n // Script already added but not yet loaded\n existingScript.addEventListener(\"load\", () => {\n const checkSDK = createSDKChecker(resolve, reject, timeoutMs);\n checkSDK();\n });\n existingScript.addEventListener(\"error\", () =>\n reject(new Error(`Failed to load TapKit CDN loader: ${loaderURL}`)),\n );\n } else {\n document.head.appendChild(script);\n }\n });\n\n window.__TAP_KIT_LOADER_LOADING__ = loadingPromise;\n return loadingPromise;\n}\n","import type {\n TapKitConfig,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/**\n * TapKit - Official TapKit Web SDK\n *\n * @example\n * ```typescript\n * import TapKit from \"@coxwave/tap-kit\";\n *\n * const kit = new TapKit({ apiKey: 'your-api-key' });\n *\n * await kit.init({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * container: {\n * position: { top: '64px', right: '32px' },\n * width: '360px',\n * height: 'calc(100% - 128px)',\n * },\n * });\n * ```\n */\nexport class TapKit implements TapKitInstance {\n private instance: TapKitInstance | null = null;\n #loading: Promise<void>;\n #config: TapKitConfig;\n #loadError: Error | null = null;\n #eventsProxy?: TapKitInstance[\"events\"]; // Cached proxy for events API\n #videoProxy?: TapKitInstance[\"video\"]; // Cached proxy for video API\n\n constructor(config: TapKitConfig) {\n this.#config = config;\n this.#loading = this.load();\n }\n\n private async load(): Promise<void> {\n try {\n await loadCDNLoader();\n\n if (!window.TapKit) {\n throw new Error(\"TapKit not available after loading CDN loader\");\n }\n\n this.instance = new window.TapKit(this.#config);\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\n\n /**\n * Promise that resolves when CDN is loaded and TapKit instance is available\n * (ready to call init())\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.loaded; // CDN downloaded, window.TapKit available\n * await kit.init({...}); // Now safe to call init()\n * ```\n *\n * @see ready - For waiting until AFTER init() completes (iframe initialized)\n */\n get loaded(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n });\n }\n\n /**\n * Promise that resolves when SDK is fully initialized\n * (after init() is called and iframe is ready)\n *\n * @example\n * ```typescript\n * const kit = new TapKit({ apiKey });\n * await kit.init({...});\n * await kit.ready; // iframe is fully initialized\n * ```\n *\n * @see loaded - For waiting until CDN load completes (before init)\n */\n get ready(): Promise<void> {\n return this.#loading.then(() => {\n if (this.#loadError) {\n throw this.#loadError;\n }\n if (!this.instance) {\n throw new Error(\n `TapKit instance not initialized after loading. This may indicate a CDN loading failure for apiKey: ${this.#config.apiKey}`,\n );\n }\n return this.instance.ready;\n });\n }\n\n /**\n * Create a proxy for video API that waits for ready before delegating\n */\n private createVideoProxy(): TapKitInstance[\"video\"] {\n return {\n bind: (config, clipId) => {\n // Queue the bind call - will execute after ready\n this.ready.then(() => {\n this.instance?.video.bind(config, clipId);\n });\n },\n unbind: () => {\n // Unbind can be called immediately if instance exists\n this.instance?.video?.unbind();\n },\n };\n }\n\n /**\n * Create events API that returns unsubscribe functions synchronously\n * Queues the actual subscription until ready, but returns unsubscribe immediately\n */\n private createEventsProxy(): TapKitInstance[\"events\"] {\n return {\n seekTimeline: (params) => {\n this.ready.then(() => {\n this.instance?.events.seekTimeline(params);\n });\n },\n onTimelineSeek: (callback) => {\n let unsubscribe: (() => void) | undefined;\n let cancelled = false;\n\n // Queue subscription\n this.ready.then(() => {\n if (cancelled) return;\n unsubscribe = this.instance?.events.onTimelineSeek(callback);\n });\n\n // Return synchronous unsubscribe function\n return () => {\n cancelled = true;\n unsubscribe?.();\n };\n },\n onAlarmFadeIn: (handler) => {\n let unsubscribe: (() => void) | undefined;\n let cancelled = false;\n\n this.ready.then(() => {\n if (cancelled) return;\n unsubscribe = this.instance?.events.onAlarmFadeIn(handler);\n });\n\n return () => {\n cancelled = true;\n unsubscribe?.();\n };\n },\n };\n }\n\n get events() {\n // Cache proxy to avoid creating new object on every access\n if (!this.#eventsProxy) {\n this.#eventsProxy = this.createEventsProxy();\n }\n return this.#eventsProxy;\n }\n\n get isOpen(): boolean {\n return this.instance?.isOpen ?? false;\n }\n\n get isInitialized(): boolean {\n return this.instance?.isInitialized ?? false;\n }\n\n get video() {\n // Cache proxy to avoid creating new object on every access\n if (!this.#videoProxy) {\n this.#videoProxy = this.createVideoProxy();\n }\n return this.#videoProxy;\n }\n\n async init(params: TapKitInitParams): Promise<() => void> {\n await this.#loading;\n if (!this.instance) {\n throw new Error(\"TapKit instance not available after loading\");\n }\n return await this.instance.init(params);\n }\n\n destroy(): void {\n if (this.instance) {\n this.instance.destroy();\n this.instance = null;\n }\n // Clear proxy references to prevent memory leaks\n this.#eventsProxy = undefined;\n this.#videoProxy = undefined;\n }\n\n show(): void {\n if (this.instance) {\n this.instance.show();\n }\n }\n\n hide(): void {\n if (this.instance) {\n this.instance.hide();\n }\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n"]}
|
package/dist/react.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TapKitElement
|
|
2
|
-
import React
|
|
1
|
+
import { TapKitElement } from '@coxwave/tap-kit-types';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* React-specific type definitions for TapKit
|
|
@@ -66,6 +66,12 @@ interface TapKitControl<T> {
|
|
|
66
66
|
* Separated from options for easier event listener management.
|
|
67
67
|
*/
|
|
68
68
|
handlers: TapKitEventHandlers;
|
|
69
|
+
/**
|
|
70
|
+
* Whether CDN is loaded and Web Component is available
|
|
71
|
+
*
|
|
72
|
+
* @internal Used by TapKit component to delay rendering
|
|
73
|
+
*/
|
|
74
|
+
isCdnLoaded: boolean;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
/**
|
|
@@ -110,24 +116,18 @@ interface TapKitControl<T> {
|
|
|
110
116
|
/**
|
|
111
117
|
* Props for TapKit React component
|
|
112
118
|
*/
|
|
113
|
-
interface TapKitProps extends Omit<React
|
|
119
|
+
interface TapKitProps extends Omit<React.HTMLAttributes<TapKitElement>, "children" | "dangerouslySetInnerHTML"> {
|
|
114
120
|
/**
|
|
115
121
|
* Control object from useTapKit hook
|
|
116
122
|
*
|
|
117
123
|
* Provides instance management, configuration, and event handlers.
|
|
118
124
|
*/
|
|
119
125
|
control: TapKitControl<any>;
|
|
120
|
-
/**
|
|
121
|
-
* Custom container element ID (optional)
|
|
122
|
-
*
|
|
123
|
-
* If provided, TapKit will use this element as container.
|
|
124
|
-
*/
|
|
125
|
-
containerId?: string;
|
|
126
126
|
}
|
|
127
127
|
declare global {
|
|
128
128
|
namespace JSX {
|
|
129
129
|
interface IntrinsicElements {
|
|
130
|
-
"tap-kit": React
|
|
130
|
+
"tap-kit": React.DetailedHTMLProps<React.HTMLAttributes<TapKitElement>, TapKitElement> & {
|
|
131
131
|
"api-key"?: string;
|
|
132
132
|
"user-id"?: string;
|
|
133
133
|
"course-id"?: string;
|
|
@@ -135,7 +135,6 @@ declare global {
|
|
|
135
135
|
"clip-play-head"?: number;
|
|
136
136
|
language?: "ko" | "en";
|
|
137
137
|
"button-id"?: string;
|
|
138
|
-
"container-id"?: string;
|
|
139
138
|
mode?: "inline" | "floating" | "sidebar";
|
|
140
139
|
debug?: boolean;
|
|
141
140
|
"tap-url"?: string;
|
|
@@ -158,60 +157,45 @@ declare global {
|
|
|
158
157
|
* // tapkitRef.current?.show()
|
|
159
158
|
* ```
|
|
160
159
|
*/
|
|
161
|
-
declare const TapKit: React
|
|
160
|
+
declare const TapKit: React.ForwardRefExoticComponent<TapKitProps & React.RefAttributes<TapKitElement>>;
|
|
162
161
|
|
|
163
162
|
/**
|
|
164
|
-
* useTapKit Hook -
|
|
165
|
-
*
|
|
166
|
-
* This hook provides direct access to the TapKitElement instance and full
|
|
167
|
-
* control over its lifecycle. Use this when you need:
|
|
168
|
-
* - Direct element manipulation
|
|
169
|
-
* - Custom rendering logic
|
|
170
|
-
* - Imperative control over Web Component behavior
|
|
163
|
+
* useTapKit Hook - ChatKit-style control for TapKit Web Component
|
|
171
164
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
165
|
+
* This hook provides a control object to manage TapKit through the
|
|
166
|
+
* <TapKit /> component. Inspired by OpenAI's ChatKit pattern.
|
|
174
167
|
*
|
|
175
|
-
* @
|
|
176
|
-
* @returns Object with element reference, state, and control methods
|
|
177
|
-
*
|
|
178
|
-
* @example Advanced control with custom rendering
|
|
168
|
+
* @example
|
|
179
169
|
* ```tsx
|
|
180
170
|
* 'use client';
|
|
181
171
|
*
|
|
182
|
-
* import { useTapKit } from '@coxwave/tap-kit/react';
|
|
172
|
+
* import { TapKit, useTapKit } from '@coxwave/tap-kit/react';
|
|
183
173
|
*
|
|
184
|
-
* function
|
|
185
|
-
* const
|
|
174
|
+
* function MyApp() {
|
|
175
|
+
* const tapkit = useTapKit({
|
|
186
176
|
* apiKey: 'your-key',
|
|
187
177
|
* userId: 'user-123',
|
|
188
178
|
* courseId: 'course-456',
|
|
189
179
|
* clipId: 'clip-789',
|
|
180
|
+
* onReady: () => console.log('Ready!'),
|
|
181
|
+
* onError: (error) => console.error(error),
|
|
190
182
|
* });
|
|
191
183
|
*
|
|
192
|
-
* // Direct element access for advanced operations
|
|
193
|
-
* useEffect(() => {
|
|
194
|
-
* if (element) {
|
|
195
|
-
* // Direct manipulation of TapKitElement
|
|
196
|
-
* console.log('Element mounted:', element);
|
|
197
|
-
* }
|
|
198
|
-
* }, [element]);
|
|
199
|
-
*
|
|
200
184
|
* return (
|
|
201
185
|
* <div>
|
|
202
|
-
* <button onClick={show} disabled={!isReady}>
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* <
|
|
186
|
+
* <button onClick={tapkit.show} disabled={!tapkit.isReady}>
|
|
187
|
+
* Ask AI Tutor
|
|
188
|
+
* </button>
|
|
189
|
+
* <TapKit control={tapkit.control} />
|
|
206
190
|
* </div>
|
|
207
191
|
* );
|
|
208
192
|
* }
|
|
209
193
|
* ```
|
|
210
|
-
*
|
|
211
|
-
* @see TapKit - Use this component for simpler declarative API
|
|
212
194
|
*/
|
|
213
195
|
|
|
214
|
-
interface UseTapKitOptions extends
|
|
196
|
+
interface UseTapKitOptions extends TapKitEventHandlers {
|
|
197
|
+
/** API Key (required) */
|
|
198
|
+
apiKey: string;
|
|
215
199
|
/** User ID */
|
|
216
200
|
userId?: string;
|
|
217
201
|
/** Course ID */
|
|
@@ -240,13 +224,7 @@ interface UseTapKitOptions extends TapKitConfig, TapKitEventHandlers {
|
|
|
240
224
|
*/
|
|
241
225
|
type TapKitOptions = Omit<UseTapKitOptions, keyof TapKitEventHandlers>;
|
|
242
226
|
interface UseTapKitReturn {
|
|
243
|
-
/**
|
|
244
|
-
element: TapKitElement | null;
|
|
245
|
-
/** Ref object for direct element access */
|
|
246
|
-
ref: React.RefObject<TapKitElement | null>;
|
|
247
|
-
/** Container ref to attach element */
|
|
248
|
-
elementRef: React.RefCallback<HTMLDivElement>;
|
|
249
|
-
/** Control object for TapKit component */
|
|
227
|
+
/** Control object for <TapKit /> component */
|
|
250
228
|
control: TapKitControl<TapKitOptions>;
|
|
251
229
|
/** Whether TapKit is ready */
|
|
252
230
|
isReady: boolean;
|
|
@@ -263,14 +241,22 @@ interface UseTapKitReturn {
|
|
|
263
241
|
userId?: string;
|
|
264
242
|
clipPlayHead?: number;
|
|
265
243
|
}) => void;
|
|
244
|
+
/** Video adapter control */
|
|
245
|
+
video: {
|
|
246
|
+
/** Bind video player for timeline synchronization */
|
|
247
|
+
bind: (adapter: {
|
|
248
|
+
getCurrentTime: () => number;
|
|
249
|
+
setCurrentTime: (time: number) => void;
|
|
250
|
+
}, clipId: string) => void;
|
|
251
|
+
/** Unbind current video player */
|
|
252
|
+
unbind: () => void;
|
|
253
|
+
};
|
|
266
254
|
}
|
|
267
255
|
/**
|
|
268
|
-
* Hook for managing TapKit Web Component
|
|
269
|
-
*
|
|
270
|
-
* Automatically loads CDN, creates Web Component, and provides control methods.
|
|
256
|
+
* Hook for managing TapKit Web Component (ChatKit Pattern)
|
|
271
257
|
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
258
|
+
* Returns a control object to pass to <TapKit /> component.
|
|
259
|
+
* The component handles rendering, this hook handles state and methods.
|
|
274
260
|
*/
|
|
275
261
|
declare function useTapKit(options: UseTapKitOptions): UseTapKitReturn;
|
|
276
262
|
|