@coxwave/tap-kit 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -49
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- 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.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +2 -2
- package/dist/react.mjs.map +1 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -60,58 +60,11 @@ function App() {
|
|
|
60
60
|
|
|
61
61
|
## Vanilla JS에서 사용하기
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
```html
|
|
66
|
-
<!DOCTYPE html>
|
|
67
|
-
<html>
|
|
68
|
-
<body>
|
|
69
|
-
<!-- TapKit 버튼 -->
|
|
70
|
-
<tap-button></tap-button>
|
|
71
|
-
|
|
72
|
-
<script type="module">
|
|
73
|
-
import TapKit from '@coxwave/tap-kit';
|
|
74
|
-
|
|
75
|
-
const kit = new TapKit({
|
|
76
|
-
apiKey: 'your-api-key',
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
await kit.init({
|
|
80
|
-
course: {
|
|
81
|
-
userId: 'user-123',
|
|
82
|
-
courseId: 'course-456',
|
|
83
|
-
clipId: 'clip-789',
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
</script>
|
|
87
|
-
</body>
|
|
88
|
-
</html>
|
|
89
|
-
```
|
|
63
|
+
Vanilla JavaScript로 사용하려면 [TapKit 시작하기](https://edutap-ai-docs.vercel.app/docs/npm)를 참고하세요.
|
|
90
64
|
|
|
91
65
|
## CDN에서 사용하기
|
|
92
66
|
|
|
93
|
-
|
|
94
|
-
<!DOCTYPE html>
|
|
95
|
-
<html>
|
|
96
|
-
<body>
|
|
97
|
-
<!-- TapKit 버튼 -->
|
|
98
|
-
<tap-button></tap-button>
|
|
99
|
-
|
|
100
|
-
<script type="module">
|
|
101
|
-
import TapKit from 'https://cdn.jsdelivr.net/npm/@coxwave/tap-kit/+esm';
|
|
102
|
-
|
|
103
|
-
const kit = new TapKit({ apiKey: 'your-api-key' });
|
|
104
|
-
await kit.init({
|
|
105
|
-
course: {
|
|
106
|
-
userId: 'user-123',
|
|
107
|
-
courseId: 'course-456',
|
|
108
|
-
clipId: 'clip-789',
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
</script>
|
|
112
|
-
</body>
|
|
113
|
-
</html>
|
|
114
|
-
```
|
|
67
|
+
npm 없이 CDN으로 직접 사용하려면 [CDN 사용 가이드](https://edutap-ai-docs.vercel.app/docs/cdn)를 참고하세요.
|
|
115
68
|
|
|
116
69
|
## 커스텀 버튼 사용하기
|
|
117
70
|
|
package/dist/index.d.cts
CHANGED
|
@@ -34,6 +34,15 @@ declare class TapKit implements TapKitInstance {
|
|
|
34
34
|
private pendingConfig?;
|
|
35
35
|
constructor(config: TapKitConfig);
|
|
36
36
|
private load;
|
|
37
|
+
/**
|
|
38
|
+
* Promise that resolves when CDN is loaded and instance is created
|
|
39
|
+
* (ready to call init())
|
|
40
|
+
*/
|
|
41
|
+
get loaded(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Promise that resolves when SDK is fully initialized
|
|
44
|
+
* (after init() is called and iframe is ready)
|
|
45
|
+
*/
|
|
37
46
|
get ready(): Promise<void>;
|
|
38
47
|
get events(): {
|
|
39
48
|
seekTimeline: (params: _coxwave_tap_kit_types.SeekTimelineParamsType) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,15 @@ declare class TapKit implements TapKitInstance {
|
|
|
34
34
|
private pendingConfig?;
|
|
35
35
|
constructor(config: TapKitConfig);
|
|
36
36
|
private load;
|
|
37
|
+
/**
|
|
38
|
+
* Promise that resolves when CDN is loaded and instance is created
|
|
39
|
+
* (ready to call init())
|
|
40
|
+
*/
|
|
41
|
+
get loaded(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Promise that resolves when SDK is fully initialized
|
|
44
|
+
* (after init() is called and iframe is ready)
|
|
45
|
+
*/
|
|
37
46
|
get ready(): Promise<void>;
|
|
38
47
|
get events(): {
|
|
39
48
|
seekTimeline: (params: _coxwave_tap_kit_types.SeekTimelineParamsType) => void;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var
|
|
2
|
-
exports.TAPKIT_CONFIG_SYMBOL=
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var E=Object.defineProperty;var A=t=>{throw TypeError(t)};var I=(t,n,e)=>n in t?E(t,n,{enumerable:true,configurable:true,writable:true,value:e}):t[n]=e;var f=(t,n,e)=>I(t,typeof n!="symbol"?n+"":n,e),K=(t,n,e)=>n.has(t)||A("Cannot "+e);var r=(t,n,e)=>(K(t,n,"read from private field"),e?e.call(t):n.get(t)),w=(t,n,e)=>n.has(t)?A("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(t):n.set(t,e),l=(t,n,e,i)=>(K(t,n,"write to private field"),n.set(t,e),e);var O="https://files.edutap.ai/tap-sdk/loader.js";function g(){return window?.__TAP_KIT_LOADER_URL__?window.__TAP_KIT_LOADER_URL__:O}function C(){return typeof window<"u"&&!!window.__TAP_KIT_CORE_URL__}function m(){return window.__TAP_KIT_CORE_URL__||""}function D(t,n,e){let i=Date.now(),o=()=>{if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,t();return}if(Date.now()-i>e){window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error(`TapKit loader timeout: SDK not available after ${e}ms`));return}typeof requestIdleCallback<"u"?requestIdleCallback(o,{timeout:500}):setTimeout(o,500);};return o}function h(t=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 n=new Promise((e,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}if(C()){if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e();return}let T=m(),d=document.createElement("script");d.src=T,d.async=true,d.onload=()=>{window.TapKit?(window.TapKitLoaded=true,window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e()):(window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error("TapKit not available after loading local core")));},d.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load local TapKit core: ${T}`));},document.head.appendChild(d);return}let o=g(),s=document.createElement("script");s.src=o,s.async=true,s.onload=()=>{D(e,i,t)();},s.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${o}`));};let u=document.querySelector(`script[src="${o}"]`);u?(u.addEventListener("load",()=>{D(e,i,t)();}),u.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${o}`)))):document.head.appendChild(s);});return window.__TAP_KIT_LOADER_LOADING__=n,n}var p=Symbol.for("tapkit.config"),_,c,a,L=class{constructor(n){f(this,"instance",null);w(this,_);w(this,c);w(this,a,null);f(this,"pendingConfig");l(this,c,n),l(this,_,this.load());}async load(){try{if(await h(),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");this.instance=new window.TapKit(r(this,c)),this.pendingConfig&&(this.instance[p]?.(this.pendingConfig),this.pendingConfig=void 0);}catch(n){throw l(this,a,n instanceof Error?n:new Error(String(n))),r(this,a)}}get loaded(){return r(this,_).then(()=>{if(r(this,a))throw r(this,a);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.")})}get ready(){return r(this,_).then(()=>{if(r(this,a))throw r(this,a);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.");return this.instance.ready})}get events(){return new Proxy({},{get:(n,e)=>(...i)=>this.ready.then(()=>{let o=(this.instance?.events)[e];return typeof o=="function"?o(...i):o})})}get isOpen(){return this.instance?.isOpen??false}get isInitialized(){return this.instance?.isInitialized??false}get video(){return new Proxy({},{get:(n,e)=>(...i)=>this.ready.then(()=>{let o=(this.instance?.video)[e];return typeof o=="function"?o(...i):o})})}async init(n){if(await r(this,_),!this.instance)throw new Error("TapKit instance not available after loading");return await this.instance.init(n)}destroy(){this.instance&&(this.instance.destroy(),this.instance=null);}[p](n){if(!this.instance){this.pendingConfig=n;return}this.instance[p]?.(n);}get[Symbol.toStringTag](){return "TapKit"}};_=new WeakMap,c=new WeakMap,a=new WeakMap;
|
|
2
|
+
exports.TAPKIT_CONFIG_SYMBOL=p;exports.default=L;//# 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","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options"],"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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\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","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options"],"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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\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 instance is created\n * (ready to call init())\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(\"TapKit instance not initialized. Check console for errors.\");\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 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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
export{
|
|
1
|
+
var E=Object.defineProperty;var A=t=>{throw TypeError(t)};var I=(t,n,e)=>n in t?E(t,n,{enumerable:true,configurable:true,writable:true,value:e}):t[n]=e;var f=(t,n,e)=>I(t,typeof n!="symbol"?n+"":n,e),K=(t,n,e)=>n.has(t)||A("Cannot "+e);var r=(t,n,e)=>(K(t,n,"read from private field"),e?e.call(t):n.get(t)),w=(t,n,e)=>n.has(t)?A("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(t):n.set(t,e),l=(t,n,e,i)=>(K(t,n,"write to private field"),n.set(t,e),e);var O="https://files.edutap.ai/tap-sdk/loader.js";function g(){return window?.__TAP_KIT_LOADER_URL__?window.__TAP_KIT_LOADER_URL__:O}function C(){return typeof window<"u"&&!!window.__TAP_KIT_CORE_URL__}function m(){return window.__TAP_KIT_CORE_URL__||""}function D(t,n,e){let i=Date.now(),o=()=>{if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,t();return}if(Date.now()-i>e){window.__TAP_KIT_LOADER_LOADING__=void 0,n(new Error(`TapKit loader timeout: SDK not available after ${e}ms`));return}typeof requestIdleCallback<"u"?requestIdleCallback(o,{timeout:500}):setTimeout(o,500);};return o}function h(t=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 n=new Promise((e,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}if(C()){if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e();return}let T=m(),d=document.createElement("script");d.src=T,d.async=true,d.onload=()=>{window.TapKit?(window.TapKitLoaded=true,window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e()):(window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error("TapKit not available after loading local core")));},d.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load local TapKit core: ${T}`));},document.head.appendChild(d);return}let o=g(),s=document.createElement("script");s.src=o,s.async=true,s.onload=()=>{D(e,i,t)();},s.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${o}`));};let u=document.querySelector(`script[src="${o}"]`);u?(u.addEventListener("load",()=>{D(e,i,t)();}),u.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${o}`)))):document.head.appendChild(s);});return window.__TAP_KIT_LOADER_LOADING__=n,n}var p=Symbol.for("tapkit.config"),_,c,a,L=class{constructor(n){f(this,"instance",null);w(this,_);w(this,c);w(this,a,null);f(this,"pendingConfig");l(this,c,n),l(this,_,this.load());}async load(){try{if(await h(),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");this.instance=new window.TapKit(r(this,c)),this.pendingConfig&&(this.instance[p]?.(this.pendingConfig),this.pendingConfig=void 0);}catch(n){throw l(this,a,n instanceof Error?n:new Error(String(n))),r(this,a)}}get loaded(){return r(this,_).then(()=>{if(r(this,a))throw r(this,a);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.")})}get ready(){return r(this,_).then(()=>{if(r(this,a))throw r(this,a);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.");return this.instance.ready})}get events(){return new Proxy({},{get:(n,e)=>(...i)=>this.ready.then(()=>{let o=(this.instance?.events)[e];return typeof o=="function"?o(...i):o})})}get isOpen(){return this.instance?.isOpen??false}get isInitialized(){return this.instance?.isInitialized??false}get video(){return new Proxy({},{get:(n,e)=>(...i)=>this.ready.then(()=>{let o=(this.instance?.video)[e];return typeof o=="function"?o(...i):o})})}async init(n){if(await r(this,_),!this.instance)throw new Error("TapKit instance not available after loading");return await this.instance.init(n)}destroy(){this.instance&&(this.instance.destroy(),this.instance=null);}[p](n){if(!this.instance){this.pendingConfig=n;return}this.instance[p]?.(n);}get[Symbol.toStringTag](){return "TapKit"}};_=new WeakMap,c=new WeakMap,a=new WeakMap;
|
|
2
|
+
export{p as TAPKIT_CONFIG_SYMBOL,L 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","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options"],"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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\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","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options"],"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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\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 instance is created\n * (ready to call init())\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(\"TapKit instance not initialized. Check console for errors.\");\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 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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\n"]}
|
package/dist/react.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');var x=Object.defineProperty;var
|
|
2
|
-
exports.TapKitProvider=$;exports.useTapKit=g;exports.useTapKitContext=
|
|
1
|
+
'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');var x=Object.defineProperty;var E=e=>{throw TypeError(e)};var S=(e,t,n)=>t in e?x(e,t,{enumerable:true,configurable:true,writable:true,value:n}):e[t]=n;var h=(e,t,n)=>S(e,typeof t!="symbol"?t+"":t,n),D=(e,t,n)=>t.has(e)||E("Cannot "+n);var a=(e,t,n)=>(D(e,t,"read from private field"),n?n.call(e):t.get(e)),T=(e,t,n)=>t.has(e)?E("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),f=(e,t,n,i)=>(D(e,t,"write to private field"),t.set(e,n),n);var N=typeof __DEFAULT_CDN_LOADER_URL__<"u"?__DEFAULT_CDN_LOADER_URL__:"https://files.edutap.ai/tap-sdk/loader.js",U=4e3,y=500;function b(){return window?.__TAP_KIT_LOADER_URL__?window.__TAP_KIT_LOADER_URL__:N}function k(){return typeof window<"u"&&!!window.__TAP_KIT_CORE_URL__}function G(){return window.__TAP_KIT_CORE_URL__||""}function C(e,t,n){let i=Date.now(),r=()=>{if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e();return}if(Date.now()-i>n){window.__TAP_KIT_LOADER_LOADING__=void 0,t(new Error(`TapKit loader timeout: SDK not available after ${n}ms`));return}typeof requestIdleCallback<"u"?requestIdleCallback(r,{timeout:y}):setTimeout(r,y);};return r}function I(e=U){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let t=new Promise((n,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}if(k()){if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,n();return}let l=G(),_=document.createElement("script");_.src=l,_.async=true,_.onload=()=>{window.TapKit?(window.TapKitLoaded=true,window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,n()):(window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error("TapKit not available after loading local core")));},_.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load local TapKit core: ${l}`));},document.head.appendChild(_);return}let r=b(),o=document.createElement("script");o.src=r,o.async=true,o.onload=()=>{C(n,i,e)();},o.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${r}`));};let p=document.querySelector(`script[src="${r}"]`);p?(p.addEventListener("load",()=>{C(n,i,e)();}),p.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${r}`)))):document.head.appendChild(o);});return window.__TAP_KIT_LOADER_LOADING__=t,t}var L=Symbol.for("tapkit.config"),d,u,s,K=class{constructor(t){h(this,"instance",null);T(this,d);T(this,u);T(this,s,null);h(this,"pendingConfig");f(this,u,t),f(this,d,this.load());}async load(){try{if(await I(),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");this.instance=new window.TapKit(a(this,u)),this.pendingConfig&&(this.instance[L]?.(this.pendingConfig),this.pendingConfig=void 0);}catch(t){throw f(this,s,t instanceof Error?t:new Error(String(t))),a(this,s)}}get loaded(){return a(this,d).then(()=>{if(a(this,s))throw a(this,s);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.")})}get ready(){return a(this,d).then(()=>{if(a(this,s))throw a(this,s);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.");return this.instance.ready})}get events(){return new Proxy({},{get:(t,n)=>(...i)=>this.ready.then(()=>{let r=(this.instance?.events)[n];return typeof r=="function"?r(...i):r})})}get isOpen(){return this.instance?.isOpen??false}get isInitialized(){return this.instance?.isInitialized??false}get video(){return new Proxy({},{get:(t,n)=>(...i)=>this.ready.then(()=>{let r=(this.instance?.video)[n];return typeof r=="function"?r(...i):r})})}async init(t){if(await a(this,d),!this.instance)throw new Error("TapKit instance not available after loading");return await this.instance.init(t)}destroy(){this.instance&&(this.instance.destroy(),this.instance=null);}[L](t){if(!this.instance){this.pendingConfig=t;return}this.instance[L]?.(t);}get[Symbol.toStringTag](){return "TapKit"}};d=new WeakMap,u=new WeakMap,s=new WeakMap;var c=new Map;function v(e){let{apiKey:t}=e;if(!c.has(t)){let i=new K(e),r={state:{instance:i,isReady:false,error:null},listeners:new Set};c.set(t,r),i.loaded.then(()=>{r.state.isReady=true,r.state.error=null,P(t);}).catch(o=>{r.state.error=o instanceof Error?o:new Error(String(o)),r.state.isReady=false,P(t);});}let n=c.get(t);if(!n)throw new Error(`Store for apiKey "${t}" should exist but was not found`);return n}function O(e,t){let n=c.get(e);return n?(n.listeners.add(t),()=>{n.listeners.delete(t);}):()=>{}}function m(e){let t=c.get(e);return t?t.state:null}function P(e){let t=c.get(e);if(t)for(let n of t.listeners)n();}function g(e){let{apiKey:t}=e,n=react.useRef(null);react.useEffect(()=>{v(e);},[e]);let i=react.useSyncExternalStore(react.useCallback(o=>O(t,o),[t]),react.useCallback(()=>m(t),[t]),react.useCallback(()=>m(t),[t])),r=react.useCallback(async o=>{if(!i?.instance)throw new Error("TapKit instance not initialized");let p=await i.instance.init(o);return n.current=p,p},[i?.instance]);return react.useEffect(()=>()=>{n.current?.();},[]),{kit:i?.instance??null,isReady:i?.isReady??false,error:i?.error??null,setup:r}}var A=react.createContext(null);function $({config:e,children:t}){let n=g(e);return jsxRuntime.jsx(A.Provider,{value:n,children:t})}function V(){let e=react.useContext(A);if(!e)throw new Error("useTapKitContext must be used within a TapKitProvider. Wrap your component tree with <TapKitProvider config={...}>");return e}
|
|
2
|
+
exports.TapKitProvider=$;exports.useTapKit=g;exports.useTapKitContext=V;//# sourceMappingURL=react.js.map
|
|
3
3
|
//# sourceMappingURL=react.js.map
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loader.ts","../src/kit.ts","../src/react/store.ts","../src/react/useTapKit.ts","../src/react/TapKitProvider.tsx","../src/react/useTapKitContext.ts"],"names":["DEFAULT_CDN_LOADER_URL","DEFAULT_TIMEOUT_MS","IDLE_CALLBACK_TIMEOUT_MS","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options","stores","getTapKitStore","apiKey","instance","store","notifyListeners","subscribe","callback","getSnapshot","listener","useTapKit","cleanupRef","useRef","useEffect","state","useSyncExternalStore","useCallback","setup","cleanup","TapKitContext","createContext","TapKitProvider","children","tapKit","jsx","useTapKitContext","context","useContext"],"mappings":"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","file":"react.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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\n","/**\n * TapKit Instance Store\n *\n * useSyncExternalStore를 활용하여 apiKey별 인스턴스를 관리합니다.\n * Zustand와 유사한 방식으로 Context 없이도 여러 컴포넌트에서 같은 인스턴스를 공유할 수 있습니다.\n */\n\nimport type { TapKitConfig } from \"@coxwave/tap-kit-types\";\nimport { TapKit } from \"../kit.js\";\n\ninterface StoreState {\n instance: TapKit;\n isReady: boolean;\n error: Error | null;\n}\n\ntype Listener = () => void;\n\n/**\n * apiKey별 store를 관리하는 Map\n */\nconst stores = new Map<\n string,\n {\n state: StoreState;\n listeners: Set<Listener>;\n }\n>();\n\n/**\n * apiKey에 해당하는 TapKit store를 가져오거나 생성합니다.\n *\n * @param config - TapKit 설정\n * @returns Store object with state and subscription methods\n */\nexport function getTapKitStore(config: TapKitConfig) {\n const { apiKey } = config;\n\n if (!stores.has(apiKey)) {\n const instance = new TapKit(config);\n const store = {\n state: {\n instance,\n isReady: false,\n error: null as Error | null,\n },\n listeners: new Set<Listener>(),\n };\n\n stores.set(apiKey, store);\n\n // Initialize and update ready state\n instance.ready\n .then(() => {\n store.state.isReady = true;\n store.state.error = null;\n notifyListeners(apiKey);\n })\n .catch((err) => {\n store.state.error = err instanceof Error ? err : new Error(String(err));\n store.state.isReady = false;\n notifyListeners(apiKey);\n });\n }\n\n const store = stores.get(apiKey);\n if (!store) {\n throw new Error(`Store for apiKey \"${apiKey}\" should exist but was not found`);\n }\n return store;\n}\n\n/**\n * Subscribe to store changes for useSyncExternalStore\n */\nexport function subscribe(apiKey: string, callback: Listener): () => void {\n const store = stores.get(apiKey);\n if (!store) {\n return () => {};\n }\n\n store.listeners.add(callback);\n return () => {\n store.listeners.delete(callback);\n };\n}\n\n/**\n * Get current snapshot for useSyncExternalStore\n */\nexport function getSnapshot(apiKey: string): StoreState | null {\n const store = stores.get(apiKey);\n return store ? store.state : null;\n}\n\n/**\n * Notify all listeners of a store\n */\nfunction notifyListeners(apiKey: string): void {\n const store = stores.get(apiKey);\n if (!store) return;\n\n for (const listener of store.listeners) {\n listener();\n }\n}\n\n/**\n * 특정 apiKey의 인스턴스를 제거합니다.\n * 주로 테스트나 cleanup에 사용됩니다.\n *\n * @param apiKey - 제거할 인스턴스의 apiKey\n */\nexport function clearTapKitInstance(apiKey: string): void {\n const store = stores.get(apiKey);\n if (store) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n stores.delete(apiKey);\n }\n}\n\n/**\n * 모든 캐시된 인스턴스를 제거합니다.\n * 주로 테스트 cleanup에 사용됩니다.\n */\nexport function clearAllTapKitInstances(): void {\n for (const [_apiKey, store] of stores.entries()) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n }\n stores.clear();\n}\n","import { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\nimport type { TapKitConfig, TapKitInstance, TapKitInitParams } from \"../types\";\nimport { getSnapshot, getTapKitStore, subscribe } from \"./store.js\";\n\nexport interface UseTapKitReturn {\n /** TapKit instance */\n kit: TapKitInstance | null;\n /** Whether TapKit is ready to use */\n isReady: boolean;\n /** Error that occurred during loading */\n error: Error | null;\n /** Setup TapKit with given parameters (button, course info, etc.) */\n setup: (params: TapKitInitParams) => Promise<() => void>;\n}\n\n/**\n * 🌟 TapKit을 React에서 사용하기 위한 핵심 Hook\n *\n * useSyncExternalStore를 활용하여 TapKit 인스턴스를 관리합니다.\n * 같은 apiKey로 여러 컴포넌트에서 호출해도 동일한 인스턴스를 공유합니다.\n *\n * @param config - TapKit 설정 (apiKey 등)\n * @returns TapKit 인스턴스, 로딩 상태, 에러 정보, 설정 함수\n *\n * @example\n * ```tsx\n * import { useEffect } from 'react';\n * import { useTapKit } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, error, setup } = useTapKit({\n * apiKey: 'your-api-key',\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * setup({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * });\n * }\n * }, [isReady, setup]);\n *\n * if (error) {\n * return <div>에러 발생: {error.message}</div>;\n * }\n *\n * if (!isReady) {\n * return <div>TapKit 로딩 중...</div>;\n * }\n *\n * return <div id=\"tap-button\">AI 튜터</div>;\n * }\n * ```\n */\nexport function useTapKit(config: TapKitConfig): UseTapKitReturn {\n const { apiKey } = config;\n const cleanupRef = useRef<(() => void) | null>(null);\n\n // Store 초기화\n useEffect(() => {\n getTapKitStore(config);\n }, [config]);\n\n // useSyncExternalStore로 상태 구독\n const state = useSyncExternalStore(\n useCallback((callback) => subscribe(apiKey, callback), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]) // Server snapshot (same as client)\n );\n\n const setup = useCallback(\n async (params: TapKitInitParams): Promise<() => void> => {\n if (!state?.instance) {\n throw new Error(\"TapKit instance not initialized\");\n }\n const cleanup = await state.instance.init(params);\n cleanupRef.current = cleanup;\n return cleanup;\n },\n [state?.instance]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupRef.current?.();\n };\n }, []);\n\n return {\n kit: state?.instance ?? null,\n isReady: state?.isReady ?? false,\n error: state?.error ?? null,\n setup,\n };\n}\n","import { createContext, type ReactNode } from \"react\";\nimport { useTapKit, type UseTapKitReturn } from \"./useTapKit\";\nimport type { TapKitConfig } from \"../types\";\n\nexport interface TapKitContextValue extends UseTapKitReturn {}\n\nexport const TapKitContext = createContext<TapKitContextValue | null>(null);\n\nexport interface TapKitProviderProps {\n /** TapKit configuration */\n config: TapKitConfig;\n /** React children */\n children: ReactNode;\n}\n\n/**\n * TapKit Context Provider\n *\n * 여러 컴포넌트에서 같은 TapKit 인스턴스를 공유하려면 이 Provider를 사용하세요.\n * Provider 하위의 모든 컴포넌트에서 useTapKitContext()로 접근할 수 있습니다.\n *\n * @param props - Provider props\n * @param props.config - TapKit 설정 (apiKey 등)\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * import { TapKitProvider } from '@coxwave/tap-kit/react';\n *\n * function App() {\n * return (\n * <TapKitProvider config={{ apiKey: 'your-key' }}>\n * <YourApp />\n * </TapKitProvider>\n * );\n * }\n * ```\n */\nexport function TapKitProvider({ config, children }: TapKitProviderProps) {\n const tapKit = useTapKit(config);\n\n return <TapKitContext.Provider value={tapKit}>{children}</TapKitContext.Provider>;\n}\n","import { useContext } from \"react\";\nimport { TapKitContext, type TapKitContextValue } from \"./TapKitProvider\";\n\n/**\n * TapKit Context에 접근하는 Hook\n *\n * TapKitProvider 하위에서만 사용할 수 있습니다.\n * Provider 없이 사용하면 에러가 발생합니다.\n *\n * @returns TapKit context value (kit, isReady, error, init)\n * @throws {Error} TapKitProvider 외부에서 사용한 경우\n *\n * @example\n * ```tsx\n * import { useTapKitContext } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, init } = useTapKitContext();\n *\n * // ...\n * }\n * ```\n */\nexport function useTapKitContext(): TapKitContextValue {\n const context = useContext(TapKitContext);\n\n if (!context) {\n throw new Error(\n \"useTapKitContext must be used within a TapKitProvider. \" +\n \"Wrap your component tree with <TapKitProvider config={...}>\"\n );\n }\n\n return context;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/useTapKit.ts","../src/loader.ts","../src/kit.ts","../src/react/store.ts","../src/react/TapKitProvider.tsx","../src/react/useTapKitContext.ts"],"names":["DEFAULT_CDN_LOADER_URL","DEFAULT_TIMEOUT_MS","IDLE_CALLBACK_TIMEOUT_MS","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options","stores","getTapKitStore","apiKey","instance","store","notifyListeners","subscribe","callback","getSnapshot","listener","useTapKit","cleanupRef","useRef","useEffect","state","useSyncExternalStore","useCallback","setup","cleanup","TapKitContext","createContext","TapKitProvider","children","tapKit","jsx","useTapKitContext","context","useContext"],"mappings":"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","file":"react.js","sourcesContent":["import { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\nimport type { TapKitConfig, TapKitInstance, TapKitInitParams } from \"../types\";\nimport { getSnapshot, getTapKitStore, subscribe } from \"./store.js\";\n\nexport interface UseTapKitReturn {\n /** TapKit instance */\n kit: TapKitInstance | null;\n /** Whether TapKit is ready to use */\n isReady: boolean;\n /** Error that occurred during loading */\n error: Error | null;\n /** Setup TapKit with given parameters (button, course info, etc.) */\n setup: (params: TapKitInitParams) => Promise<() => void>;\n}\n\n/**\n * 🌟 TapKit을 React에서 사용하기 위한 핵심 Hook\n *\n * useSyncExternalStore를 활용하여 TapKit 인스턴스를 관리합니다.\n * 같은 apiKey로 여러 컴포넌트에서 호출해도 동일한 인스턴스를 공유합니다.\n *\n * @param config - TapKit 설정 (apiKey 등)\n * @returns TapKit 인스턴스, 로딩 상태, 에러 정보, 설정 함수\n *\n * @example\n * ```tsx\n * import { useEffect } from 'react';\n * import { useTapKit } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, error, setup } = useTapKit({\n * apiKey: 'your-api-key',\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * setup({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * });\n * }\n * }, [isReady, setup]);\n *\n * if (error) {\n * return <div>에러 발생: {error.message}</div>;\n * }\n *\n * if (!isReady) {\n * return <div>TapKit 로딩 중...</div>;\n * }\n *\n * return <div id=\"tap-button\">AI 튜터</div>;\n * }\n * ```\n */\nexport function useTapKit(config: TapKitConfig): UseTapKitReturn {\n const { apiKey } = config;\n const cleanupRef = useRef<(() => void) | null>(null);\n\n // Store 초기화\n useEffect(() => {\n getTapKitStore(config);\n }, [config]);\n\n // useSyncExternalStore로 상태 구독\n const state = useSyncExternalStore(\n useCallback((callback) => subscribe(apiKey, callback), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]) // Server snapshot (same as client)\n );\n\n const setup = useCallback(\n async (params: TapKitInitParams): Promise<() => void> => {\n if (!state?.instance) {\n throw new Error(\"TapKit instance not initialized\");\n }\n const cleanup = await state.instance.init(params);\n cleanupRef.current = cleanup;\n return cleanup;\n },\n [state?.instance]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupRef.current?.();\n };\n }, []);\n\n return {\n kit: state?.instance ?? null,\n isReady: state?.isReady ?? false,\n error: state?.error ?? null,\n setup,\n };\n}\n","/**\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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\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 instance is created\n * (ready to call init())\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(\"TapKit instance not initialized. Check console for errors.\");\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 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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\n","/**\n * TapKit Instance Store\n *\n * useSyncExternalStore를 활용하여 apiKey별 인스턴스를 관리합니다.\n * Zustand와 유사한 방식으로 Context 없이도 여러 컴포넌트에서 같은 인스턴스를 공유할 수 있습니다.\n */\n\nimport type { TapKitConfig } from \"@coxwave/tap-kit-types\";\nimport { TapKit } from \"../kit.js\";\n\ninterface StoreState {\n instance: TapKit;\n isReady: boolean;\n error: Error | null;\n}\n\ntype Listener = () => void;\n\n/**\n * apiKey별 store를 관리하는 Map\n */\nconst stores = new Map<\n string,\n {\n state: StoreState;\n listeners: Set<Listener>;\n }\n>();\n\n/**\n * apiKey에 해당하는 TapKit store를 가져오거나 생성합니다.\n *\n * @param config - TapKit 설정\n * @returns Store object with state and subscription methods\n */\nexport function getTapKitStore(config: TapKitConfig) {\n const { apiKey } = config;\n\n if (!stores.has(apiKey)) {\n const instance = new TapKit(config);\n const store = {\n state: {\n instance,\n isReady: false,\n error: null as Error | null,\n },\n listeners: new Set<Listener>(),\n };\n\n stores.set(apiKey, store);\n\n // Wait for CDN to load and instance to be created (ready to call init())\n instance.loaded\n .then(() => {\n store.state.isReady = true;\n store.state.error = null;\n notifyListeners(apiKey);\n })\n .catch((err) => {\n store.state.error = err instanceof Error ? err : new Error(String(err));\n store.state.isReady = false;\n notifyListeners(apiKey);\n });\n }\n\n const store = stores.get(apiKey);\n if (!store) {\n throw new Error(`Store for apiKey \"${apiKey}\" should exist but was not found`);\n }\n return store;\n}\n\n/**\n * Subscribe to store changes for useSyncExternalStore\n */\nexport function subscribe(apiKey: string, callback: Listener): () => void {\n const store = stores.get(apiKey);\n if (!store) {\n return () => {};\n }\n\n store.listeners.add(callback);\n return () => {\n store.listeners.delete(callback);\n };\n}\n\n/**\n * Get current snapshot for useSyncExternalStore\n */\nexport function getSnapshot(apiKey: string): StoreState | null {\n const store = stores.get(apiKey);\n return store ? store.state : null;\n}\n\n/**\n * Notify all listeners of a store\n */\nfunction notifyListeners(apiKey: string): void {\n const store = stores.get(apiKey);\n if (!store) return;\n\n for (const listener of store.listeners) {\n listener();\n }\n}\n\n/**\n * 특정 apiKey의 인스턴스를 제거합니다.\n * 주로 테스트나 cleanup에 사용됩니다.\n *\n * @param apiKey - 제거할 인스턴스의 apiKey\n */\nexport function clearTapKitInstance(apiKey: string): void {\n const store = stores.get(apiKey);\n if (store) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n stores.delete(apiKey);\n }\n}\n\n/**\n * 모든 캐시된 인스턴스를 제거합니다.\n * 주로 테스트 cleanup에 사용됩니다.\n */\nexport function clearAllTapKitInstances(): void {\n for (const [_apiKey, store] of stores.entries()) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n }\n stores.clear();\n}\n","import { createContext, type ReactNode } from \"react\";\nimport { useTapKit, type UseTapKitReturn } from \"./useTapKit\";\nimport type { TapKitConfig } from \"../types\";\n\nexport interface TapKitContextValue extends UseTapKitReturn {}\n\nexport const TapKitContext = createContext<TapKitContextValue | null>(null);\n\nexport interface TapKitProviderProps {\n /** TapKit configuration */\n config: TapKitConfig;\n /** React children */\n children: ReactNode;\n}\n\n/**\n * TapKit Context Provider\n *\n * 여러 컴포넌트에서 같은 TapKit 인스턴스를 공유하려면 이 Provider를 사용하세요.\n * Provider 하위의 모든 컴포넌트에서 useTapKitContext()로 접근할 수 있습니다.\n *\n * @param props - Provider props\n * @param props.config - TapKit 설정 (apiKey 등)\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * import { TapKitProvider } from '@coxwave/tap-kit/react';\n *\n * function App() {\n * return (\n * <TapKitProvider config={{ apiKey: 'your-key' }}>\n * <YourApp />\n * </TapKitProvider>\n * );\n * }\n * ```\n */\nexport function TapKitProvider({ config, children }: TapKitProviderProps) {\n const tapKit = useTapKit(config);\n\n return <TapKitContext.Provider value={tapKit}>{children}</TapKitContext.Provider>;\n}\n","import { useContext } from \"react\";\nimport { TapKitContext, type TapKitContextValue } from \"./TapKitProvider\";\n\n/**\n * TapKit Context에 접근하는 Hook\n *\n * TapKitProvider 하위에서만 사용할 수 있습니다.\n * Provider 없이 사용하면 에러가 발생합니다.\n *\n * @returns TapKit context value (kit, isReady, error, init)\n * @throws {Error} TapKitProvider 외부에서 사용한 경우\n *\n * @example\n * ```tsx\n * import { useTapKitContext } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, init } = useTapKitContext();\n *\n * // ...\n * }\n * ```\n */\nexport function useTapKitContext(): TapKitContextValue {\n const context = useContext(TapKitContext);\n\n if (!context) {\n throw new Error(\n \"useTapKitContext must be used within a TapKitProvider. \" +\n \"Wrap your component tree with <TapKitProvider config={...}>\"\n );\n }\n\n return context;\n}\n"]}
|
package/dist/react.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {createContext,useRef,useEffect,useSyncExternalStore,useCallback,useContext}from'react';import {jsx}from'react/jsx-runtime';var x=Object.defineProperty;var
|
|
2
|
-
export{$ as TapKitProvider,g as useTapKit,
|
|
1
|
+
import {createContext,useRef,useEffect,useSyncExternalStore,useCallback,useContext}from'react';import {jsx}from'react/jsx-runtime';var x=Object.defineProperty;var E=e=>{throw TypeError(e)};var S=(e,t,n)=>t in e?x(e,t,{enumerable:true,configurable:true,writable:true,value:n}):e[t]=n;var h=(e,t,n)=>S(e,typeof t!="symbol"?t+"":t,n),D=(e,t,n)=>t.has(e)||E("Cannot "+n);var a=(e,t,n)=>(D(e,t,"read from private field"),n?n.call(e):t.get(e)),T=(e,t,n)=>t.has(e)?E("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),f=(e,t,n,i)=>(D(e,t,"write to private field"),t.set(e,n),n);var N=typeof __DEFAULT_CDN_LOADER_URL__<"u"?__DEFAULT_CDN_LOADER_URL__:"https://files.edutap.ai/tap-sdk/loader.js",U=4e3,y=500;function b(){return window?.__TAP_KIT_LOADER_URL__?window.__TAP_KIT_LOADER_URL__:N}function k(){return typeof window<"u"&&!!window.__TAP_KIT_CORE_URL__}function G(){return window.__TAP_KIT_CORE_URL__||""}function C(e,t,n){let i=Date.now(),r=()=>{if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,e();return}if(Date.now()-i>n){window.__TAP_KIT_LOADER_LOADING__=void 0,t(new Error(`TapKit loader timeout: SDK not available after ${n}ms`));return}typeof requestIdleCallback<"u"?requestIdleCallback(r,{timeout:y}):setTimeout(r,y);};return r}function I(e=U){if(window.__TAP_KIT_LOADER_LOADED__&&window.TapKit)return Promise.resolve();if(window.__TAP_KIT_LOADER_LOADING__)return window.__TAP_KIT_LOADER_LOADING__;let t=new Promise((n,i)=>{if(typeof document>"u"){i(new Error("TapKit requires browser environment (document is undefined)"));return}if(k()){if(window.TapKit&&window.TapKitLoaded===true){window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,n();return}let l=G(),_=document.createElement("script");_.src=l,_.async=true,_.onload=()=>{window.TapKit?(window.TapKitLoaded=true,window.__TAP_KIT_LOADER_LOADED__=true,window.__TAP_KIT_LOADER_LOADING__=void 0,n()):(window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error("TapKit not available after loading local core")));},_.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load local TapKit core: ${l}`));},document.head.appendChild(_);return}let r=b(),o=document.createElement("script");o.src=r,o.async=true,o.onload=()=>{C(n,i,e)();},o.onerror=()=>{window.__TAP_KIT_LOADER_LOADING__=void 0,i(new Error(`Failed to load TapKit CDN loader: ${r}`));};let p=document.querySelector(`script[src="${r}"]`);p?(p.addEventListener("load",()=>{C(n,i,e)();}),p.addEventListener("error",()=>i(new Error(`Failed to load TapKit CDN loader: ${r}`)))):document.head.appendChild(o);});return window.__TAP_KIT_LOADER_LOADING__=t,t}var L=Symbol.for("tapkit.config"),d,u,s,K=class{constructor(t){h(this,"instance",null);T(this,d);T(this,u);T(this,s,null);h(this,"pendingConfig");f(this,u,t),f(this,d,this.load());}async load(){try{if(await I(),!window.TapKit)throw new Error("TapKit not available after loading CDN loader");this.instance=new window.TapKit(a(this,u)),this.pendingConfig&&(this.instance[L]?.(this.pendingConfig),this.pendingConfig=void 0);}catch(t){throw f(this,s,t instanceof Error?t:new Error(String(t))),a(this,s)}}get loaded(){return a(this,d).then(()=>{if(a(this,s))throw a(this,s);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.")})}get ready(){return a(this,d).then(()=>{if(a(this,s))throw a(this,s);if(!this.instance)throw new Error("TapKit instance not initialized. Check console for errors.");return this.instance.ready})}get events(){return new Proxy({},{get:(t,n)=>(...i)=>this.ready.then(()=>{let r=(this.instance?.events)[n];return typeof r=="function"?r(...i):r})})}get isOpen(){return this.instance?.isOpen??false}get isInitialized(){return this.instance?.isInitialized??false}get video(){return new Proxy({},{get:(t,n)=>(...i)=>this.ready.then(()=>{let r=(this.instance?.video)[n];return typeof r=="function"?r(...i):r})})}async init(t){if(await a(this,d),!this.instance)throw new Error("TapKit instance not available after loading");return await this.instance.init(t)}destroy(){this.instance&&(this.instance.destroy(),this.instance=null);}[L](t){if(!this.instance){this.pendingConfig=t;return}this.instance[L]?.(t);}get[Symbol.toStringTag](){return "TapKit"}};d=new WeakMap,u=new WeakMap,s=new WeakMap;var c=new Map;function v(e){let{apiKey:t}=e;if(!c.has(t)){let i=new K(e),r={state:{instance:i,isReady:false,error:null},listeners:new Set};c.set(t,r),i.loaded.then(()=>{r.state.isReady=true,r.state.error=null,P(t);}).catch(o=>{r.state.error=o instanceof Error?o:new Error(String(o)),r.state.isReady=false,P(t);});}let n=c.get(t);if(!n)throw new Error(`Store for apiKey "${t}" should exist but was not found`);return n}function O(e,t){let n=c.get(e);return n?(n.listeners.add(t),()=>{n.listeners.delete(t);}):()=>{}}function m(e){let t=c.get(e);return t?t.state:null}function P(e){let t=c.get(e);if(t)for(let n of t.listeners)n();}function g(e){let{apiKey:t}=e,n=useRef(null);useEffect(()=>{v(e);},[e]);let i=useSyncExternalStore(useCallback(o=>O(t,o),[t]),useCallback(()=>m(t),[t]),useCallback(()=>m(t),[t])),r=useCallback(async o=>{if(!i?.instance)throw new Error("TapKit instance not initialized");let p=await i.instance.init(o);return n.current=p,p},[i?.instance]);return useEffect(()=>()=>{n.current?.();},[]),{kit:i?.instance??null,isReady:i?.isReady??false,error:i?.error??null,setup:r}}var A=createContext(null);function $({config:e,children:t}){let n=g(e);return jsx(A.Provider,{value:n,children:t})}function V(){let e=useContext(A);if(!e)throw new Error("useTapKitContext must be used within a TapKitProvider. Wrap your component tree with <TapKitProvider config={...}>");return e}
|
|
2
|
+
export{$ as TapKitProvider,g as useTapKit,V as useTapKitContext};//# sourceMappingURL=react.mjs.map
|
|
3
3
|
//# sourceMappingURL=react.mjs.map
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/loader.ts","../src/kit.ts","../src/react/store.ts","../src/react/useTapKit.ts","../src/react/TapKitProvider.tsx","../src/react/useTapKitContext.ts"],"names":["DEFAULT_CDN_LOADER_URL","DEFAULT_TIMEOUT_MS","IDLE_CALLBACK_TIMEOUT_MS","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options","stores","getTapKitStore","apiKey","instance","store","notifyListeners","subscribe","callback","getSnapshot","listener","useTapKit","cleanupRef","useRef","useEffect","state","useSyncExternalStore","useCallback","setup","cleanup","TapKitContext","createContext","TapKitProvider","children","tapKit","jsx","useTapKitContext","context","useContext"],"mappings":"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","file":"react.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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\n return;\n }\n\n // Local core mode: Load IIFE directly\n if (isLocalCoreMode()) {\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\n } catch (err) {\n this.#loadError = err instanceof Error ? err : new Error(String(err));\n throw this.#loadError;\n }\n }\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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\n","/**\n * TapKit Instance Store\n *\n * useSyncExternalStore를 활용하여 apiKey별 인스턴스를 관리합니다.\n * Zustand와 유사한 방식으로 Context 없이도 여러 컴포넌트에서 같은 인스턴스를 공유할 수 있습니다.\n */\n\nimport type { TapKitConfig } from \"@coxwave/tap-kit-types\";\nimport { TapKit } from \"../kit.js\";\n\ninterface StoreState {\n instance: TapKit;\n isReady: boolean;\n error: Error | null;\n}\n\ntype Listener = () => void;\n\n/**\n * apiKey별 store를 관리하는 Map\n */\nconst stores = new Map<\n string,\n {\n state: StoreState;\n listeners: Set<Listener>;\n }\n>();\n\n/**\n * apiKey에 해당하는 TapKit store를 가져오거나 생성합니다.\n *\n * @param config - TapKit 설정\n * @returns Store object with state and subscription methods\n */\nexport function getTapKitStore(config: TapKitConfig) {\n const { apiKey } = config;\n\n if (!stores.has(apiKey)) {\n const instance = new TapKit(config);\n const store = {\n state: {\n instance,\n isReady: false,\n error: null as Error | null,\n },\n listeners: new Set<Listener>(),\n };\n\n stores.set(apiKey, store);\n\n // Initialize and update ready state\n instance.ready\n .then(() => {\n store.state.isReady = true;\n store.state.error = null;\n notifyListeners(apiKey);\n })\n .catch((err) => {\n store.state.error = err instanceof Error ? err : new Error(String(err));\n store.state.isReady = false;\n notifyListeners(apiKey);\n });\n }\n\n const store = stores.get(apiKey);\n if (!store) {\n throw new Error(`Store for apiKey \"${apiKey}\" should exist but was not found`);\n }\n return store;\n}\n\n/**\n * Subscribe to store changes for useSyncExternalStore\n */\nexport function subscribe(apiKey: string, callback: Listener): () => void {\n const store = stores.get(apiKey);\n if (!store) {\n return () => {};\n }\n\n store.listeners.add(callback);\n return () => {\n store.listeners.delete(callback);\n };\n}\n\n/**\n * Get current snapshot for useSyncExternalStore\n */\nexport function getSnapshot(apiKey: string): StoreState | null {\n const store = stores.get(apiKey);\n return store ? store.state : null;\n}\n\n/**\n * Notify all listeners of a store\n */\nfunction notifyListeners(apiKey: string): void {\n const store = stores.get(apiKey);\n if (!store) return;\n\n for (const listener of store.listeners) {\n listener();\n }\n}\n\n/**\n * 특정 apiKey의 인스턴스를 제거합니다.\n * 주로 테스트나 cleanup에 사용됩니다.\n *\n * @param apiKey - 제거할 인스턴스의 apiKey\n */\nexport function clearTapKitInstance(apiKey: string): void {\n const store = stores.get(apiKey);\n if (store) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n stores.delete(apiKey);\n }\n}\n\n/**\n * 모든 캐시된 인스턴스를 제거합니다.\n * 주로 테스트 cleanup에 사용됩니다.\n */\nexport function clearAllTapKitInstances(): void {\n for (const [_apiKey, store] of stores.entries()) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n }\n stores.clear();\n}\n","import { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\nimport type { TapKitConfig, TapKitInstance, TapKitInitParams } from \"../types\";\nimport { getSnapshot, getTapKitStore, subscribe } from \"./store.js\";\n\nexport interface UseTapKitReturn {\n /** TapKit instance */\n kit: TapKitInstance | null;\n /** Whether TapKit is ready to use */\n isReady: boolean;\n /** Error that occurred during loading */\n error: Error | null;\n /** Setup TapKit with given parameters (button, course info, etc.) */\n setup: (params: TapKitInitParams) => Promise<() => void>;\n}\n\n/**\n * 🌟 TapKit을 React에서 사용하기 위한 핵심 Hook\n *\n * useSyncExternalStore를 활용하여 TapKit 인스턴스를 관리합니다.\n * 같은 apiKey로 여러 컴포넌트에서 호출해도 동일한 인스턴스를 공유합니다.\n *\n * @param config - TapKit 설정 (apiKey 등)\n * @returns TapKit 인스턴스, 로딩 상태, 에러 정보, 설정 함수\n *\n * @example\n * ```tsx\n * import { useEffect } from 'react';\n * import { useTapKit } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, error, setup } = useTapKit({\n * apiKey: 'your-api-key',\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * setup({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * });\n * }\n * }, [isReady, setup]);\n *\n * if (error) {\n * return <div>에러 발생: {error.message}</div>;\n * }\n *\n * if (!isReady) {\n * return <div>TapKit 로딩 중...</div>;\n * }\n *\n * return <div id=\"tap-button\">AI 튜터</div>;\n * }\n * ```\n */\nexport function useTapKit(config: TapKitConfig): UseTapKitReturn {\n const { apiKey } = config;\n const cleanupRef = useRef<(() => void) | null>(null);\n\n // Store 초기화\n useEffect(() => {\n getTapKitStore(config);\n }, [config]);\n\n // useSyncExternalStore로 상태 구독\n const state = useSyncExternalStore(\n useCallback((callback) => subscribe(apiKey, callback), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]) // Server snapshot (same as client)\n );\n\n const setup = useCallback(\n async (params: TapKitInitParams): Promise<() => void> => {\n if (!state?.instance) {\n throw new Error(\"TapKit instance not initialized\");\n }\n const cleanup = await state.instance.init(params);\n cleanupRef.current = cleanup;\n return cleanup;\n },\n [state?.instance]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupRef.current?.();\n };\n }, []);\n\n return {\n kit: state?.instance ?? null,\n isReady: state?.isReady ?? false,\n error: state?.error ?? null,\n setup,\n };\n}\n","import { createContext, type ReactNode } from \"react\";\nimport { useTapKit, type UseTapKitReturn } from \"./useTapKit\";\nimport type { TapKitConfig } from \"../types\";\n\nexport interface TapKitContextValue extends UseTapKitReturn {}\n\nexport const TapKitContext = createContext<TapKitContextValue | null>(null);\n\nexport interface TapKitProviderProps {\n /** TapKit configuration */\n config: TapKitConfig;\n /** React children */\n children: ReactNode;\n}\n\n/**\n * TapKit Context Provider\n *\n * 여러 컴포넌트에서 같은 TapKit 인스턴스를 공유하려면 이 Provider를 사용하세요.\n * Provider 하위의 모든 컴포넌트에서 useTapKitContext()로 접근할 수 있습니다.\n *\n * @param props - Provider props\n * @param props.config - TapKit 설정 (apiKey 등)\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * import { TapKitProvider } from '@coxwave/tap-kit/react';\n *\n * function App() {\n * return (\n * <TapKitProvider config={{ apiKey: 'your-key' }}>\n * <YourApp />\n * </TapKitProvider>\n * );\n * }\n * ```\n */\nexport function TapKitProvider({ config, children }: TapKitProviderProps) {\n const tapKit = useTapKit(config);\n\n return <TapKitContext.Provider value={tapKit}>{children}</TapKitContext.Provider>;\n}\n","import { useContext } from \"react\";\nimport { TapKitContext, type TapKitContextValue } from \"./TapKitProvider\";\n\n/**\n * TapKit Context에 접근하는 Hook\n *\n * TapKitProvider 하위에서만 사용할 수 있습니다.\n * Provider 없이 사용하면 에러가 발생합니다.\n *\n * @returns TapKit context value (kit, isReady, error, init)\n * @throws {Error} TapKitProvider 외부에서 사용한 경우\n *\n * @example\n * ```tsx\n * import { useTapKitContext } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, init } = useTapKitContext();\n *\n * // ...\n * }\n * ```\n */\nexport function useTapKitContext(): TapKitContextValue {\n const context = useContext(TapKitContext);\n\n if (!context) {\n throw new Error(\n \"useTapKitContext must be used within a TapKitProvider. \" +\n \"Wrap your component tree with <TapKitProvider config={...}>\"\n );\n }\n\n return context;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/useTapKit.ts","../src/loader.ts","../src/kit.ts","../src/react/store.ts","../src/react/TapKitProvider.tsx","../src/react/useTapKitContext.ts"],"names":["DEFAULT_CDN_LOADER_URL","DEFAULT_TIMEOUT_MS","IDLE_CALLBACK_TIMEOUT_MS","getLoaderURL","isLocalCoreMode","getLocalCoreURL","createSDKChecker","resolve","reject","timeoutMs","startTime","checkSDK","loadCDNLoader","loadingPromise","coreURL","script","loaderURL","existingScript","TAPKIT_CONFIG_SYMBOL","_loading","_config","_loadError","TapKit","config","__publicField","__privateAdd","__privateSet","__privateGet","err","_target","prop","args","method","params","options","stores","getTapKitStore","apiKey","instance","store","notifyListeners","subscribe","callback","getSnapshot","listener","useTapKit","cleanupRef","useRef","useEffect","state","useSyncExternalStore","useCallback","setup","cleanup","TapKitContext","createContext","TapKitProvider","children","tapKit","jsx","useTapKitContext","context","useContext"],"mappings":"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","file":"react.mjs","sourcesContent":["import { useCallback, useEffect, useRef, useSyncExternalStore } from \"react\";\nimport type { TapKitConfig, TapKitInstance, TapKitInitParams } from \"../types\";\nimport { getSnapshot, getTapKitStore, subscribe } from \"./store.js\";\n\nexport interface UseTapKitReturn {\n /** TapKit instance */\n kit: TapKitInstance | null;\n /** Whether TapKit is ready to use */\n isReady: boolean;\n /** Error that occurred during loading */\n error: Error | null;\n /** Setup TapKit with given parameters (button, course info, etc.) */\n setup: (params: TapKitInitParams) => Promise<() => void>;\n}\n\n/**\n * 🌟 TapKit을 React에서 사용하기 위한 핵심 Hook\n *\n * useSyncExternalStore를 활용하여 TapKit 인스턴스를 관리합니다.\n * 같은 apiKey로 여러 컴포넌트에서 호출해도 동일한 인스턴스를 공유합니다.\n *\n * @param config - TapKit 설정 (apiKey 등)\n * @returns TapKit 인스턴스, 로딩 상태, 에러 정보, 설정 함수\n *\n * @example\n * ```tsx\n * import { useEffect } from 'react';\n * import { useTapKit } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, error, setup } = useTapKit({\n * apiKey: 'your-api-key',\n * });\n *\n * useEffect(() => {\n * if (isReady) {\n * setup({\n * buttonId: 'tap-button',\n * course: {\n * userId: 'user-123',\n * courseId: 'course-456',\n * clipId: 'clip-789',\n * },\n * });\n * }\n * }, [isReady, setup]);\n *\n * if (error) {\n * return <div>에러 발생: {error.message}</div>;\n * }\n *\n * if (!isReady) {\n * return <div>TapKit 로딩 중...</div>;\n * }\n *\n * return <div id=\"tap-button\">AI 튜터</div>;\n * }\n * ```\n */\nexport function useTapKit(config: TapKitConfig): UseTapKitReturn {\n const { apiKey } = config;\n const cleanupRef = useRef<(() => void) | null>(null);\n\n // Store 초기화\n useEffect(() => {\n getTapKitStore(config);\n }, [config]);\n\n // useSyncExternalStore로 상태 구독\n const state = useSyncExternalStore(\n useCallback((callback) => subscribe(apiKey, callback), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]),\n useCallback(() => getSnapshot(apiKey), [apiKey]) // Server snapshot (same as client)\n );\n\n const setup = useCallback(\n async (params: TapKitInitParams): Promise<() => void> => {\n if (!state?.instance) {\n throw new Error(\"TapKit instance not initialized\");\n }\n const cleanup = await state.instance.init(params);\n cleanupRef.current = cleanup;\n return cleanup;\n },\n [state?.instance]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n cleanupRef.current?.();\n };\n }, []);\n\n return {\n kit: state?.instance ?? null,\n isReady: state?.isReady ?? false,\n error: state?.error ?? null,\n setup,\n };\n}\n","/**\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__ ? window.__TAP_KIT_LOADER_URL__ : 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(new Error(`TapKit loader timeout: SDK not available after ${timeoutMs}ms`));\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(timeoutMs: number = DEFAULT_TIMEOUT_MS): 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(new Error(\"TapKit requires browser environment (document is undefined)\"));\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 TAPKIT_CONFIG_SYMBOL as TAPKIT_CONFIG_SYMBOL_TYPE,\n TapKitConfig,\n TapKitConfigOptions,\n TapKitInitParams,\n TapKitInstance,\n} from \"@coxwave/tap-kit-types\";\nimport { loadCDNLoader } from \"./loader\";\n\n/** @internal Symbol for internal configuration method */\n// biome-ignore lint/suspicious/noExplicitAny: Symbol type casting required for compatibility\nconst TAPKIT_CONFIG_SYMBOL: typeof TAPKIT_CONFIG_SYMBOL_TYPE = Symbol.for(\"tapkit.config\") as any;\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 private pendingConfig?: TapKitConfigOptions; // Queue config until instance is ready\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\n // Apply pending config if any\n if (this.pendingConfig) {\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(this.pendingConfig);\n this.pendingConfig = undefined;\n }\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 instance is created\n * (ready to call init())\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(\"TapKit instance not initialized. Check console for errors.\");\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 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(\"TapKit instance not initialized. Check console for errors.\");\n }\n return this.instance.ready;\n });\n }\n\n get events() {\n // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"events\"], {\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?.events as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 // Proxy pattern: automatically wait for ready when calling methods\n return new Proxy({} as TapKitInstance[\"video\"], {\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?.video as any)[prop];\n if (typeof method === \"function\") {\n return method(...args);\n }\n return method;\n });\n };\n },\n });\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 }\n\n [TAPKIT_CONFIG_SYMBOL](options: TapKitConfigOptions): void {\n if (!this.instance) {\n // Queue config until instance is ready\n this.pendingConfig = options;\n return;\n }\n this.instance[TAPKIT_CONFIG_SYMBOL]?.(options);\n }\n\n get [Symbol.toStringTag]() {\n return \"TapKit\";\n }\n}\n\n// Export the symbol for type compatibility\nexport { TAPKIT_CONFIG_SYMBOL };\n","/**\n * TapKit Instance Store\n *\n * useSyncExternalStore를 활용하여 apiKey별 인스턴스를 관리합니다.\n * Zustand와 유사한 방식으로 Context 없이도 여러 컴포넌트에서 같은 인스턴스를 공유할 수 있습니다.\n */\n\nimport type { TapKitConfig } from \"@coxwave/tap-kit-types\";\nimport { TapKit } from \"../kit.js\";\n\ninterface StoreState {\n instance: TapKit;\n isReady: boolean;\n error: Error | null;\n}\n\ntype Listener = () => void;\n\n/**\n * apiKey별 store를 관리하는 Map\n */\nconst stores = new Map<\n string,\n {\n state: StoreState;\n listeners: Set<Listener>;\n }\n>();\n\n/**\n * apiKey에 해당하는 TapKit store를 가져오거나 생성합니다.\n *\n * @param config - TapKit 설정\n * @returns Store object with state and subscription methods\n */\nexport function getTapKitStore(config: TapKitConfig) {\n const { apiKey } = config;\n\n if (!stores.has(apiKey)) {\n const instance = new TapKit(config);\n const store = {\n state: {\n instance,\n isReady: false,\n error: null as Error | null,\n },\n listeners: new Set<Listener>(),\n };\n\n stores.set(apiKey, store);\n\n // Wait for CDN to load and instance to be created (ready to call init())\n instance.loaded\n .then(() => {\n store.state.isReady = true;\n store.state.error = null;\n notifyListeners(apiKey);\n })\n .catch((err) => {\n store.state.error = err instanceof Error ? err : new Error(String(err));\n store.state.isReady = false;\n notifyListeners(apiKey);\n });\n }\n\n const store = stores.get(apiKey);\n if (!store) {\n throw new Error(`Store for apiKey \"${apiKey}\" should exist but was not found`);\n }\n return store;\n}\n\n/**\n * Subscribe to store changes for useSyncExternalStore\n */\nexport function subscribe(apiKey: string, callback: Listener): () => void {\n const store = stores.get(apiKey);\n if (!store) {\n return () => {};\n }\n\n store.listeners.add(callback);\n return () => {\n store.listeners.delete(callback);\n };\n}\n\n/**\n * Get current snapshot for useSyncExternalStore\n */\nexport function getSnapshot(apiKey: string): StoreState | null {\n const store = stores.get(apiKey);\n return store ? store.state : null;\n}\n\n/**\n * Notify all listeners of a store\n */\nfunction notifyListeners(apiKey: string): void {\n const store = stores.get(apiKey);\n if (!store) return;\n\n for (const listener of store.listeners) {\n listener();\n }\n}\n\n/**\n * 특정 apiKey의 인스턴스를 제거합니다.\n * 주로 테스트나 cleanup에 사용됩니다.\n *\n * @param apiKey - 제거할 인스턴스의 apiKey\n */\nexport function clearTapKitInstance(apiKey: string): void {\n const store = stores.get(apiKey);\n if (store) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n stores.delete(apiKey);\n }\n}\n\n/**\n * 모든 캐시된 인스턴스를 제거합니다.\n * 주로 테스트 cleanup에 사용됩니다.\n */\nexport function clearAllTapKitInstances(): void {\n for (const [_apiKey, store] of stores.entries()) {\n store.state.instance.destroy?.();\n store.listeners.clear();\n }\n stores.clear();\n}\n","import { createContext, type ReactNode } from \"react\";\nimport { useTapKit, type UseTapKitReturn } from \"./useTapKit\";\nimport type { TapKitConfig } from \"../types\";\n\nexport interface TapKitContextValue extends UseTapKitReturn {}\n\nexport const TapKitContext = createContext<TapKitContextValue | null>(null);\n\nexport interface TapKitProviderProps {\n /** TapKit configuration */\n config: TapKitConfig;\n /** React children */\n children: ReactNode;\n}\n\n/**\n * TapKit Context Provider\n *\n * 여러 컴포넌트에서 같은 TapKit 인스턴스를 공유하려면 이 Provider를 사용하세요.\n * Provider 하위의 모든 컴포넌트에서 useTapKitContext()로 접근할 수 있습니다.\n *\n * @param props - Provider props\n * @param props.config - TapKit 설정 (apiKey 등)\n * @param props.children - React children\n *\n * @example\n * ```tsx\n * import { TapKitProvider } from '@coxwave/tap-kit/react';\n *\n * function App() {\n * return (\n * <TapKitProvider config={{ apiKey: 'your-key' }}>\n * <YourApp />\n * </TapKitProvider>\n * );\n * }\n * ```\n */\nexport function TapKitProvider({ config, children }: TapKitProviderProps) {\n const tapKit = useTapKit(config);\n\n return <TapKitContext.Provider value={tapKit}>{children}</TapKitContext.Provider>;\n}\n","import { useContext } from \"react\";\nimport { TapKitContext, type TapKitContextValue } from \"./TapKitProvider\";\n\n/**\n * TapKit Context에 접근하는 Hook\n *\n * TapKitProvider 하위에서만 사용할 수 있습니다.\n * Provider 없이 사용하면 에러가 발생합니다.\n *\n * @returns TapKit context value (kit, isReady, error, init)\n * @throws {Error} TapKitProvider 외부에서 사용한 경우\n *\n * @example\n * ```tsx\n * import { useTapKitContext } from '@coxwave/tap-kit/react';\n *\n * function MyComponent() {\n * const { kit, isReady, init } = useTapKitContext();\n *\n * // ...\n * }\n * ```\n */\nexport function useTapKitContext(): TapKitContextValue {\n const context = useContext(TapKitContext);\n\n if (!context) {\n throw new Error(\n \"useTapKitContext must be used within a TapKitProvider. \" +\n \"Wrap your component tree with <TapKitProvider config={...}>\"\n );\n }\n\n return context;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coxwave/tap-kit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "EduTAP SDK with React support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,14 +22,8 @@
|
|
|
22
22
|
"dist",
|
|
23
23
|
"README.md"
|
|
24
24
|
],
|
|
25
|
-
"scripts": {
|
|
26
|
-
"build": "tsup",
|
|
27
|
-
"dev": "tsup --watch",
|
|
28
|
-
"typecheck": "tsc --noEmit",
|
|
29
|
-
"publish:npm": "./scripts/publish.sh"
|
|
30
|
-
},
|
|
31
25
|
"dependencies": {
|
|
32
|
-
"@coxwave/tap-kit-types": "
|
|
26
|
+
"@coxwave/tap-kit-types": "0.0.66"
|
|
33
27
|
},
|
|
34
28
|
"peerDependencies": {
|
|
35
29
|
"react": "^18.0.0 || ^19.0.0"
|
|
@@ -40,11 +34,11 @@
|
|
|
40
34
|
}
|
|
41
35
|
},
|
|
42
36
|
"devDependencies": {
|
|
43
|
-
"@coxwave/config-typescript": "workspace:*",
|
|
44
37
|
"@types/react": "^19.0.0",
|
|
45
38
|
"react": "^19.0.0",
|
|
46
39
|
"tsup": "^8.0.0",
|
|
47
|
-
"typescript": "^5.0.0"
|
|
40
|
+
"typescript": "^5.0.0",
|
|
41
|
+
"@coxwave/config-typescript": "1.0.0"
|
|
48
42
|
},
|
|
49
43
|
"keywords": [
|
|
50
44
|
"edutap",
|
|
@@ -63,5 +57,11 @@
|
|
|
63
57
|
"license": "MIT",
|
|
64
58
|
"publishConfig": {
|
|
65
59
|
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"dev": "tsup --watch",
|
|
64
|
+
"typecheck": "tsc --noEmit",
|
|
65
|
+
"publish:npm": "./scripts/publish.sh"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|