API Reference
TapKit의 전체 API 레퍼런스
API Reference
TapKitElement
<tap-kit> Web Component 요소입니다.
API 요약
라이프사이클
| API | 설명 |
|---|---|
ready | 초기화 완료 Promise |
isInitialized | 초기화 완료 여부 (boolean) |
UI 제어
| API | 설명 |
|---|---|
show() | 채팅 컨테이너 표시 |
hide() | 채팅 컨테이너 숨김 |
isOpen | 채팅 열림 상태 (boolean) |
코스 정보
| API | 설명 |
|---|---|
setCourse({ courseId, clipId, userId?, clipPlayHead? }) | 코스 정보 업데이트 |
이벤트 (kit.events)
| API | 설명 |
|---|---|
seekTimeline({ clipPlayHead, clipId }) | 타임라인 이동 요청 |
onTimelineSeek(callback) | 타임라인 seek 이벤트 구독, unsubscribe 함수 반환 |
onAlarmFadeIn(handler) | 알람 표시 이벤트 구독, unsubscribe 함수 반환 |
비디오 (kit.video)
| API | 설명 |
|---|---|
bind(config, clipId?) | 비디오 플레이어 바인딩 (타임라인 동기화) |
unbind() | 비디오 바인딩 해제 |
Properties
apiKey: string (write-only)
보안
Property로만 설정 가능합니다. HTML attribute로 설정하지 마세요.
kit.apiKey = 'your-api-key'; // O
// <tap-kit api-key="..."> 사용 금지userId: string
kit.userId = 'user-123';
// 또는 <tap-kit user-id="user-123">courseId: string
kit.courseId = 'course-456';clipId: string
kit.clipId = 'clip-789';clipPlayHead: number
재생 위치 (초 단위)입니다.
kit.clipPlayHead = 100;language: "ko" | "en"
언어 설정입니다. 기본값은 "ko"입니다.
kit.language = 'en';
// 또는 <tap-kit language="en">mode: "inline" | "floating" | "sidebar"
표시 모드입니다. 기본값은 "inline"입니다.
| 값 | 설명 |
|---|---|
inline | 페이지 콘텐츠에 임베드 (기본값) |
floating | 화면에 떠있는 컴팩트 위젯 |
sidebar | 화면 우측 전체 높이 사이드바 |
kit.mode = 'floating';
// 또는 <tap-kit mode="sidebar">allowLayoutToggle: boolean
floating ↔ sidebar 모드 간 전환 버튼 표시 여부입니다. 기본값은 true입니다.
kit.allowLayoutToggle = false; // 레이아웃 토글 버튼 숨김videoTarget: HTMLVideoElement | VideoAdapter
비디오 플레이어 동기화를 위한 선언적 바인딩입니다. video.bind() 대신 권장됩니다.
// HTMLVideoElement
kit.videoTarget = document.querySelector('video');
// VideoAdapter (YouTube, Vimeo 등)
kit.videoTarget = {
getCurrentTime: () => player.getCurrentTime(),
setCurrentTime: (time, clipId) => player.seekTo(time), // clipId는 cross-clip seeking용 (optional)
};videoTarget은 라이프사이클 변경(mode 변경, 재연결)에도 유지됩니다.
buttonId: string
커스텀 버튼 요소 ID입니다.
debug: boolean
디버그 로깅 활성화 여부입니다.
isOpen: boolean (read-only)
채팅이 현재 열려있는지 확인합니다.
isInitialized: boolean (read-only)
SDK 초기화가 완료되었는지 확인합니다.
ready: Promise<void> (read-only)
SDK가 준비될 때까지 대기하는 Promise입니다.
await kit.ready;
kit.show();Methods
show(): void
채팅 창을 표시합니다.
hide(): void
채팅 창을 숨깁니다.
setCourse(course): void
강의 정보를 업데이트합니다.
interface SetCourseParams {
userId?: string;
courseId: string; // 필수
clipId: string; // 필수
clipPlayHead?: number;
}kit.setCourse({
courseId: 'course-999',
clipId: 'clip-001',
clipPlayHead: 50
});Events
tap-kit:ready
SDK 초기화가 완료되면 발생합니다.
kit.addEventListener('tap-kit:ready', () => {
console.log('TapKit이 준비되었습니다!');
});tap-kit:error
초기화 중 오류가 발생하면 발생합니다.
kit.addEventListener('tap-kit:error', (e) => {
console.error('TapKit 오류:', e.detail.error);
});kit.events
이벤트 관련 API입니다.
kit.events.seekTimeline(params): void
타임라인을 특정 위치로 이동합니다.
interface SeekTimelineParams {
clipPlayHead: number; // 이동할 위치 (초 단위)
clipId: string;
}kit.events.seekTimeline({ clipPlayHead: 100, clipId: 'clip-789' });kit.events.onTimelineSeek(handler): () => void
타임라인 이동 이벤트를 리스닝합니다. Unsubscribe 함수를 반환합니다.
const unsubscribe = kit.events.onTimelineSeek((playHead, clipId) => {
console.log(`${playHead}초로 이동: ${clipId}`);
videoElement.currentTime = playHead;
});
// 구독 해제
unsubscribe();kit.events.onAlarmFadeIn(handler): () => void
알림이 도착할 때 발생하는 이벤트를 리스닝합니다.
const unsubscribe = kit.events.onAlarmFadeIn((alarm) => {
console.log('새 알림:', alarm.message);
});kit.video
비디오 플레이어 동기화 API입니다.
왜 video.bind가 중요한가요?
video.bind()를 사용하면:
- AI 튜터가 현재 재생 시점을 인식하여 정확한 답변 제공
- 채팅에서 특정 구간 클릭 시 비디오 자동 이동
setCourse()호출 시 자동으로 새 clipId 추적
kit.video.bind(config, clipId?): void
비디오 플레이어를 TapKit과 동기화합니다.
| Parameter | Type | Required | Description |
|---|---|---|---|
config | HTMLVideoElement | VideoAdapter | O | 비디오 요소 또는 커스텀 어댑터 |
clipId | string | 생략 시 SDK 설정에서 자동 추적 |
interface VideoAdapter {
getCurrentTime: () => number;
setCurrentTime: (time: number, clipId?: string) => void; // clipId는 cross-clip seeking용
}자동 추적 (권장):
kit.video.bind(videoElement);
// 나중에 강의 변경 시 자동으로 새 clipId 사용
kit.setCourse({ courseId: 'new-course', clipId: 'new-clip' });커스텀 어댑터 (YouTube 등):
kit.video.bind({
getCurrentTime: () => player.getCurrentTime(),
// clipId는 optional - cross-clip seeking 시 활용
setCurrentTime: (time, clipId) => player.seekTo(time, true),
});kit.video.unbind(): void
비디오 플레이어 동기화를 해제합니다.
kit.video.unbind();createTapKit()
<tap-kit> Web Component 요소를 프로그래밍 방식으로 생성하고 제어할 수 있는 Factory API입니다.
npm 패키지와 CDN 모두에서 사용 가능합니다.
- npm:
import { createTapKit } from '@coxwave/tap-kit' - CDN:
window.createTapKit(...)
React 프로젝트에서는 useTapKit Hook을 권장합니다.
Syntax
// npm 패키지
import { createTapKit } from '@coxwave/tap-kit';
const tapkit = createTapKit(options);
tapkit.mount(); // DOM에 추가 (필수)
await tapkit.ready; // 초기화 완료 대기
tapkit.show(); // 채팅 창 표시Parameters
| Property | Type | Required | Description |
|---|---|---|---|
apiKey | string | O | TapKit API 키 |
userId | string | 사용자 ID | |
courseId | string | 강의 ID | |
clipId | string | 클립 ID | |
clipPlayHead | number | 초기 재생 위치 (초 단위) | |
language | 'ko' | 'en' | 언어 설정 | |
mode | 'inline' | 'floating' | 'sidebar' | 표시 모드 (기본값: 'floating') | |
allowLayoutToggle | boolean | floating↔sidebar 토글 허용 (기본값: true) | |
videoTarget | HTMLVideoElement | VideoAdapter | 비디오 플레이어 바인딩 | |
buttonId | string | 커스텀 버튼 요소 ID | |
debug | boolean | 디버그 로깅 활성화 |
Advanced Options (테스트/개발용):
| Property | Type | Description |
|---|---|---|
apiUrl | string | 백엔드 API URL (예: 'https://tapapistaging.coxwave.link') |
tapUrl | string | iframe URL (내부 테스트용) |
environment | 'dev' | 'prod' | 'staging' | 'demo' | 환경 설정 |
Event Handlers:
| Property | Type | Description |
|---|---|---|
onReady | () => void | SDK 초기화 완료 시 호출 |
onError | (error: Error) => void | 오류 발생 시 호출 |
onTimelineSeek | (time: number, clipId: string) => void | 타임라인 이동 이벤트 |
onAlarmFadeIn | (info: unknown) => void | 알람 표시 이벤트 |
Return Value: TapKitFactoryControl
| Property/Method | Type | Description |
|---|---|---|
ready | Promise<void> | 초기화 완료 Promise |
isReady | boolean | 초기화 완료 여부 |
isOpen | boolean | 채팅 열림 상태 |
isMounted | boolean | DOM에 마운트 여부 |
mount(container?) | void | DOM에 추가 (필수) |
unmount() | void | DOM에서 제거 |
show() | void | 채팅 창 표시 |
hide() | void | 채팅 창 숨김 |
setCourse(course) | void | 코스 정보 업데이트 |
events | EventManager | 이벤트 API |
video | VideoController | 비디오 API |
element | TapKitElement | null | 내부 요소 접근 |
destroy() | void | 인스턴스 정리 |
Example (npm 패키지)
import { createTapKit } from '@coxwave/tap-kit';
const tapkit = createTapKit({
apiKey: 'your-api-key',
userId: 'user-123',
courseId: 'course-456',
clipId: 'clip-789',
// 환경 설정 (테스트용)
apiUrl: 'https://tapapistaging.coxwave.link',
environment: 'staging',
// 이벤트 핸들러
onReady: () => console.log('Ready!'),
onTimelineSeek: (time, clipId) => {
videoElement.currentTime = time;
},
});
// DOM에 추가 (필수)
tapkit.mount();
// 또는 특정 컨테이너에 추가
tapkit.mount(document.getElementById('chat-container'));
// 초기화 완료 대기
await tapkit.ready;
// 채팅 창 표시
tapkit.show();
// 정리
tapkit.destroy();Example (CDN)
<script src="https://files.edutap.ai/tap-sdk/loader.js"></script>
<script>
const kit = window.createTapKit({
apiKey: 'your-api-key',
userId: 'user-123',
courseId: 'course-456',
clipId: 'clip-789'
});
document.body.appendChild(kit);
kit.ready.then(() => kit.show());
</script>CSS Variables
UI 스타일링을 위한 CSS 변수는 스타일링 가이드를 참조하세요.
TypeScript Types
TapKitConfig
interface TapKitConfig {
apiKey: string;
userId?: string;
courseId?: string;
clipId?: string;
clipPlayHead?: number;
language?: 'ko' | 'en';
mode?: 'inline' | 'floating' | 'sidebar';
allowLayoutToggle?: boolean;
videoTarget?: HTMLVideoElement | VideoAdapter;
buttonId?: string;
debug?: boolean;
}TapKitElement
interface TapKitElement extends HTMLElement {
// Properties
apiKey: string;
userId?: string;
courseId?: string;
clipId?: string;
clipPlayHead?: number;
language?: 'ko' | 'en';
mode?: 'inline' | 'floating' | 'sidebar';
allowLayoutToggle: boolean;
videoTarget?: HTMLVideoElement | VideoAdapter;
buttonId?: string;
debug: boolean;
// Read-only
readonly isOpen: boolean;
readonly isInitialized: boolean;
readonly ready: Promise<void>;
// Methods
show(): void;
hide(): void;
setCourse(params: SetCourseParams): void;
// Sub-APIs
readonly events: {
seekTimeline(params: { clipPlayHead: number; clipId: string }): void;
onTimelineSeek(handler: (playHead: number, clipId: string) => void): () => void;
onAlarmFadeIn(handler: (messageInfo: AlarmMessageInfo) => void): () => void;
};
readonly video: {
bind(config: HTMLVideoElement | VideoAdapter, clipId?: string): void;
unbind(): void;
};
}VideoAdapter
interface VideoAdapter {
getCurrentTime: () => number;
/**
* @param time - 이동할 시간 (초)
* @param clipId - cross-clip seeking 시 대상 클립 ID (optional)
*/
setCurrentTime: (time: number, clipId?: string) => void;
}