@ct-player/embed 1.1.11 → 1.2.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/dist/index.cjs +197 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +963 -213
- package/dist/index.d.ts +963 -213
- package/dist/index.js +197 -74
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React__default from 'react';
|
|
2
|
+
import React__default__default from 'react';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import Hls from 'hls.js';
|
|
5
5
|
|
|
@@ -11,7 +11,7 @@ import Hls from 'hls.js';
|
|
|
11
11
|
/**
|
|
12
12
|
* All possible event types in the .ct format
|
|
13
13
|
*/
|
|
14
|
-
type CTEventType = 'init' | 'code' | 'code_edit' | 'language' | 'terminal' | 'terminal_input' | 'stroke_start' | 'whiteboard_points' | 'stroke_end' | 'whiteboard_stroke' | 'whiteboard_clear' | 'whiteboard_undo' | 'whiteboard' | 'whiteboard_point' | 'excalidraw_scene' | 'excalidraw_clear' | 'document_load' | 'document_page' | 'document_zoom' | 'document_scroll' | 'document_clear' | 'file_create' | 'file_update' | 'file_delete' | 'file_rename' | 'file_switch' | 'folder_create' | 'folder_delete' | 'file_select' | 'file_change' | 'file_creation_start' | 'file_creation_input' | 'file_creation_cancel' | 'file_rename_start' | 'file_rename_input' | 'file_rename_cancel' | 'folder_toggle' | 'cursor_move' | 'cursor_click' | 'cursor_enter' | 'cursor_leave' | 'file_hover' | 'text_select' | 'editor_cursor' | 'tool_switch' | 'tool' | 'marker';
|
|
14
|
+
type CTEventType = 'init' | 'code' | 'code_edit' | 'language' | 'terminal' | 'terminal_input' | 'stroke_start' | 'whiteboard_points' | 'stroke_end' | 'whiteboard_stroke' | 'whiteboard_clear' | 'whiteboard_undo' | 'whiteboard' | 'whiteboard_point' | 'excalidraw_scene' | 'excalidraw_clear' | 'excalidraw_pointer' | 'overlay_scene' | 'overlay_clear' | 'overlay_pointer' | 'document_load' | 'document_page' | 'document_zoom' | 'document_scroll' | 'document_clear' | 'file_create' | 'file_update' | 'file_delete' | 'file_rename' | 'file_switch' | 'folder_create' | 'folder_delete' | 'file_select' | 'file_change' | 'file_creation_start' | 'file_creation_input' | 'file_creation_cancel' | 'file_rename_start' | 'file_rename_input' | 'file_rename_cancel' | 'folder_toggle' | 'cursor_move' | 'cursor_click' | 'cursor_enter' | 'cursor_leave' | 'file_hover' | 'text_select' | 'editor_cursor' | 'tool_switch' | 'tool' | 'marker' | 'webcam_state' | 'content_dimensions';
|
|
15
15
|
/**
|
|
16
16
|
* Base event structure with generic type parameter
|
|
17
17
|
*/
|
|
@@ -27,7 +27,7 @@ interface CTEventBase<T extends CTEventType = CTEventType> {
|
|
|
27
27
|
* Discriminated union of all event types.
|
|
28
28
|
* This enables proper type narrowing in switch statements.
|
|
29
29
|
*/
|
|
30
|
-
type CTEvent = CTEventBase<'init'> | CTEventBase<'code'> | CTEventBase<'code_edit'> | CTEventBase<'language'> | CTEventBase<'terminal'> | CTEventBase<'terminal_input'> | CTEventBase<'stroke_start'> | CTEventBase<'whiteboard_points'> | CTEventBase<'stroke_end'> | CTEventBase<'whiteboard_stroke'> | CTEventBase<'whiteboard_clear'> | CTEventBase<'whiteboard_undo'> | CTEventBase<'whiteboard'> | CTEventBase<'whiteboard_point'> | CTEventBase<'excalidraw_scene'> | CTEventBase<'excalidraw_clear'> | CTEventBase<'document_load'> | CTEventBase<'document_page'> | CTEventBase<'document_zoom'> | CTEventBase<'document_scroll'> | CTEventBase<'document_clear'> | CTEventBase<'file_create'> | CTEventBase<'file_update'> | CTEventBase<'file_delete'> | CTEventBase<'file_rename'> | CTEventBase<'file_switch'> | CTEventBase<'folder_create'> | CTEventBase<'folder_delete'> | CTEventBase<'file_select'> | CTEventBase<'file_change'> | CTEventBase<'file_creation_start'> | CTEventBase<'file_creation_input'> | CTEventBase<'file_creation_cancel'> | CTEventBase<'file_rename_start'> | CTEventBase<'file_rename_input'> | CTEventBase<'file_rename_cancel'> | CTEventBase<'folder_toggle'> | CTEventBase<'cursor_move'> | CTEventBase<'cursor_click'> | CTEventBase<'cursor_enter'> | CTEventBase<'cursor_leave'> | CTEventBase<'file_hover'> | CTEventBase<'text_select'> | CTEventBase<'editor_cursor'> | CTEventBase<'tool_switch'> | CTEventBase<'tool'> | CTEventBase<'marker'>;
|
|
30
|
+
type CTEvent = CTEventBase<'init'> | CTEventBase<'code'> | CTEventBase<'code_edit'> | CTEventBase<'language'> | CTEventBase<'terminal'> | CTEventBase<'terminal_input'> | CTEventBase<'stroke_start'> | CTEventBase<'whiteboard_points'> | CTEventBase<'stroke_end'> | CTEventBase<'whiteboard_stroke'> | CTEventBase<'whiteboard_clear'> | CTEventBase<'whiteboard_undo'> | CTEventBase<'whiteboard'> | CTEventBase<'whiteboard_point'> | CTEventBase<'excalidraw_scene'> | CTEventBase<'excalidraw_clear'> | CTEventBase<'excalidraw_pointer'> | CTEventBase<'overlay_scene'> | CTEventBase<'overlay_clear'> | CTEventBase<'overlay_pointer'> | CTEventBase<'document_load'> | CTEventBase<'document_page'> | CTEventBase<'document_zoom'> | CTEventBase<'document_scroll'> | CTEventBase<'document_clear'> | CTEventBase<'file_create'> | CTEventBase<'file_update'> | CTEventBase<'file_delete'> | CTEventBase<'file_rename'> | CTEventBase<'file_switch'> | CTEventBase<'folder_create'> | CTEventBase<'folder_delete'> | CTEventBase<'file_select'> | CTEventBase<'file_change'> | CTEventBase<'file_creation_start'> | CTEventBase<'file_creation_input'> | CTEventBase<'file_creation_cancel'> | CTEventBase<'file_rename_start'> | CTEventBase<'file_rename_input'> | CTEventBase<'file_rename_cancel'> | CTEventBase<'folder_toggle'> | CTEventBase<'cursor_move'> | CTEventBase<'cursor_click'> | CTEventBase<'cursor_enter'> | CTEventBase<'cursor_leave'> | CTEventBase<'file_hover'> | CTEventBase<'text_select'> | CTEventBase<'editor_cursor'> | CTEventBase<'tool_switch'> | CTEventBase<'tool'> | CTEventBase<'marker'> | CTEventBase<'webcam_state'> | CTEventBase<'content_dimensions'>;
|
|
31
31
|
/**
|
|
32
32
|
* Mapping of event types to their data structures
|
|
33
33
|
*/
|
|
@@ -46,6 +46,10 @@ interface CTEventDataMap {
|
|
|
46
46
|
whiteboard_undo: WhiteboardUndoEventData;
|
|
47
47
|
excalidraw_scene: ExcalidrawSceneEventData;
|
|
48
48
|
excalidraw_clear: ExcalidrawClearEventData;
|
|
49
|
+
excalidraw_pointer: ExcalidrawPointerEventData;
|
|
50
|
+
overlay_scene: ExcalidrawSceneEventData;
|
|
51
|
+
overlay_clear: ExcalidrawClearEventData;
|
|
52
|
+
overlay_pointer: ExcalidrawPointerEventData;
|
|
49
53
|
document_load: DocumentLoadEventData;
|
|
50
54
|
document_page: DocumentPageEventData;
|
|
51
55
|
document_zoom: DocumentZoomEventData;
|
|
@@ -74,6 +78,8 @@ interface CTEventDataMap {
|
|
|
74
78
|
editor_cursor: EditorCursorEventData;
|
|
75
79
|
tool_switch: ToolSwitchEventData;
|
|
76
80
|
marker: MarkerEventData;
|
|
81
|
+
webcam_state: WebcamStateEventData;
|
|
82
|
+
content_dimensions: ContentDimensionsEventData;
|
|
77
83
|
tool: ToolEventData;
|
|
78
84
|
whiteboard: WhiteboardEventData;
|
|
79
85
|
whiteboard_point: WhiteboardPointEventData;
|
|
@@ -221,6 +227,10 @@ interface InitEventData {
|
|
|
221
227
|
x: number;
|
|
222
228
|
y: number;
|
|
223
229
|
};
|
|
230
|
+
contentDimensions?: {
|
|
231
|
+
width: number;
|
|
232
|
+
height: number;
|
|
233
|
+
};
|
|
224
234
|
}
|
|
225
235
|
/**
|
|
226
236
|
* Code content change
|
|
@@ -380,6 +390,15 @@ interface ExcalidrawSceneEventData {
|
|
|
380
390
|
*/
|
|
381
391
|
interface ExcalidrawClearEventData {
|
|
382
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Excalidraw pointer update (laser pointer, tool changes)
|
|
395
|
+
*/
|
|
396
|
+
interface ExcalidrawPointerEventData {
|
|
397
|
+
x: number;
|
|
398
|
+
y: number;
|
|
399
|
+
tool: 'pointer' | 'laser';
|
|
400
|
+
button: 'down' | 'up';
|
|
401
|
+
}
|
|
383
402
|
/**
|
|
384
403
|
* Load document
|
|
385
404
|
*/
|
|
@@ -587,7 +606,22 @@ interface ToolSwitchEventData {
|
|
|
587
606
|
interface MarkerEventData {
|
|
588
607
|
id: string;
|
|
589
608
|
label: string;
|
|
590
|
-
type: 'chapter' | '
|
|
609
|
+
type: 'chapter' | 'bookmark' | 'quiz' | 'note';
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Webcam state event for maximize/minimize during recording
|
|
613
|
+
*/
|
|
614
|
+
interface WebcamStateEventData {
|
|
615
|
+
/** Whether the webcam is maximized (full overlay) */
|
|
616
|
+
maximized: boolean;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Content dimensions event — captures the recording container size
|
|
620
|
+
* for accurate cursor alignment during playback
|
|
621
|
+
*/
|
|
622
|
+
interface ContentDimensionsEventData {
|
|
623
|
+
width: number;
|
|
624
|
+
height: number;
|
|
591
625
|
}
|
|
592
626
|
/**
|
|
593
627
|
* Legacy tool event (same as tool_switch)
|
|
@@ -683,6 +717,32 @@ interface PlaybackState$1 {
|
|
|
683
717
|
textSelection: TextSelectionState | null;
|
|
684
718
|
/** Editor typing cursor (caret) position */
|
|
685
719
|
editorCursor: EditorCursorState | null;
|
|
720
|
+
/** Whether webcam is in maximized (full overlay) mode */
|
|
721
|
+
webcamMaximized: boolean;
|
|
722
|
+
/** Content area dimensions from the recording session.
|
|
723
|
+
* Used to correctly position the cursor overlay during playback when
|
|
724
|
+
* the player container is a different size than the recording container.
|
|
725
|
+
* Without this, the cursor diverges from Excalidraw's absolute coordinates. */
|
|
726
|
+
contentDimensions: {
|
|
727
|
+
width: number;
|
|
728
|
+
height: number;
|
|
729
|
+
} | null;
|
|
730
|
+
/** Excalidraw pointer state (for laser pointer playback) */
|
|
731
|
+
excalidrawPointer: {
|
|
732
|
+
x: number;
|
|
733
|
+
y: number;
|
|
734
|
+
tool: 'pointer' | 'laser';
|
|
735
|
+
button: 'down' | 'up';
|
|
736
|
+
} | null;
|
|
737
|
+
/** Drawing overlay scene (floating overlay on non-whiteboard panels) */
|
|
738
|
+
overlayScene: ExcalidrawScene | null;
|
|
739
|
+
/** Drawing overlay pointer state (laser pointer on overlay) */
|
|
740
|
+
overlayPointer: {
|
|
741
|
+
x: number;
|
|
742
|
+
y: number;
|
|
743
|
+
tool: 'pointer' | 'laser';
|
|
744
|
+
button: 'down' | 'up';
|
|
745
|
+
} | null;
|
|
686
746
|
}
|
|
687
747
|
/**
|
|
688
748
|
* State for file/folder creation UI display during playback
|
|
@@ -1071,7 +1131,7 @@ interface CTManifest {
|
|
|
1071
1131
|
media: CTMediaInfo;
|
|
1072
1132
|
/** Events reference (chunked in v1.1.0+, single file in v1.0.0) */
|
|
1073
1133
|
events: CTEventsInfo;
|
|
1074
|
-
/** Chapter/
|
|
1134
|
+
/** Chapter/bookmark markers */
|
|
1075
1135
|
markers: CTMarker[];
|
|
1076
1136
|
/** Optional embedded assets */
|
|
1077
1137
|
assets?: CTAssets;
|
|
@@ -1144,7 +1204,7 @@ interface CTWaveformInfo {
|
|
|
1144
1204
|
samplesPerSecond: number;
|
|
1145
1205
|
}
|
|
1146
1206
|
/**
|
|
1147
|
-
* Chapter/
|
|
1207
|
+
* Chapter/bookmark marker
|
|
1148
1208
|
*/
|
|
1149
1209
|
interface CTMarker {
|
|
1150
1210
|
/** Unique identifier */
|
|
@@ -1155,13 +1215,16 @@ interface CTMarker {
|
|
|
1155
1215
|
label: string;
|
|
1156
1216
|
/** Marker type */
|
|
1157
1217
|
type: CTMarkerType;
|
|
1158
|
-
/**
|
|
1218
|
+
/**
|
|
1219
|
+
* Type-specific additional data.
|
|
1220
|
+
* When `type === 'quiz'`, this should conform to {@link MCQMarkerData}.
|
|
1221
|
+
*/
|
|
1159
1222
|
data?: Record<string, unknown>;
|
|
1160
1223
|
}
|
|
1161
1224
|
/**
|
|
1162
1225
|
* Marker types
|
|
1163
1226
|
*/
|
|
1164
|
-
type CTMarkerType = 'chapter' | '
|
|
1227
|
+
type CTMarkerType = 'chapter' | 'bookmark' | 'quiz' | 'note';
|
|
1165
1228
|
/**
|
|
1166
1229
|
* Embedded assets manifest
|
|
1167
1230
|
*/
|
|
@@ -1551,6 +1614,21 @@ interface IDEPanelProps extends BasePanelProps {
|
|
|
1551
1614
|
line: number;
|
|
1552
1615
|
column: number;
|
|
1553
1616
|
}) => void;
|
|
1617
|
+
/**
|
|
1618
|
+
* Called when user interacts with the IDE (clicks explorer, terminal, etc).
|
|
1619
|
+
* Use this to pause playback when user starts interacting.
|
|
1620
|
+
*/
|
|
1621
|
+
onInteractionStart?: () => void;
|
|
1622
|
+
/** Whether to show AI inline suggestions (recording mode only). Default: false */
|
|
1623
|
+
aiSuggestionsEnabled?: boolean;
|
|
1624
|
+
/** API endpoint URL for AI completions. Default: '/api/ai/complete' */
|
|
1625
|
+
aiSuggestionsEndpoint?: string;
|
|
1626
|
+
/** Debounce delay in ms before requesting a completion. Default: 300 */
|
|
1627
|
+
aiSuggestionsDebounceMs?: number;
|
|
1628
|
+
/** Whether the AI debug feature is available. Default: false */
|
|
1629
|
+
aiDebugEnabled?: boolean;
|
|
1630
|
+
/** API endpoint for AI debug analysis. Default: '/api/ai/debug' */
|
|
1631
|
+
aiDebugEndpoint?: string;
|
|
1554
1632
|
}
|
|
1555
1633
|
/**
|
|
1556
1634
|
* Excalidraw scene structure (simplified)
|
|
@@ -1570,6 +1648,22 @@ interface WhiteboardPanelProps extends BasePanelProps {
|
|
|
1570
1648
|
onSceneChange?: (scene: WhiteboardScene) => void;
|
|
1571
1649
|
/** Called when scene is cleared */
|
|
1572
1650
|
onSceneClear?: () => void;
|
|
1651
|
+
/** Called when pointer updates (laser pointer, drawing pointer) */
|
|
1652
|
+
onPointerUpdate?: (payload: {
|
|
1653
|
+
pointer: {
|
|
1654
|
+
x: number;
|
|
1655
|
+
y: number;
|
|
1656
|
+
tool: 'pointer' | 'laser';
|
|
1657
|
+
};
|
|
1658
|
+
button: 'down' | 'up';
|
|
1659
|
+
}) => void;
|
|
1660
|
+
/** Excalidraw pointer state for playback (laser trail rendering) */
|
|
1661
|
+
pointerState?: {
|
|
1662
|
+
x: number;
|
|
1663
|
+
y: number;
|
|
1664
|
+
tool: 'pointer' | 'laser';
|
|
1665
|
+
button: 'down' | 'up';
|
|
1666
|
+
} | null;
|
|
1573
1667
|
/** Show Excalidraw toolbar */
|
|
1574
1668
|
showToolbar?: boolean;
|
|
1575
1669
|
/** Background color */
|
|
@@ -1647,6 +1741,8 @@ interface DocumentPanelProps extends BasePanelProps {
|
|
|
1647
1741
|
allowMultiple?: boolean;
|
|
1648
1742
|
/** Background color */
|
|
1649
1743
|
backgroundColor?: string;
|
|
1744
|
+
/** Base URL for asset upload endpoint (e.g. '/api/assets'). PPTX files are uploaded here to get a public URL for iframe embedding. */
|
|
1745
|
+
assetUploadUrl?: string;
|
|
1650
1746
|
}
|
|
1651
1747
|
/**
|
|
1652
1748
|
* Terminal component props
|
|
@@ -1763,13 +1859,15 @@ interface ToolSidebarProps {
|
|
|
1763
1859
|
tools?: ToolType[];
|
|
1764
1860
|
/** Additional CSS classes */
|
|
1765
1861
|
className?: string;
|
|
1862
|
+
/** Inline styles (e.g. background override) */
|
|
1863
|
+
style?: React.CSSProperties;
|
|
1766
1864
|
}
|
|
1767
1865
|
|
|
1768
|
-
declare function ToolSidebar({ activeTool, onToolChange, tools, className, }: ToolSidebarProps): react_jsx_runtime.JSX.Element;
|
|
1866
|
+
declare function ToolSidebar({ activeTool, onToolChange, tools, className, style, }: ToolSidebarProps): react_jsx_runtime.JSX.Element;
|
|
1769
1867
|
|
|
1770
|
-
declare function WhiteboardPanel({ scene, onSceneChange, onSceneClear, mode, isPlaying, onInteract, showToolbar, backgroundColor, className, }: WhiteboardPanelProps): react_jsx_runtime.JSX.Element;
|
|
1868
|
+
declare function WhiteboardPanel({ scene, onSceneChange, onSceneClear, onPointerUpdate, pointerState, mode, isPlaying, onInteract, showToolbar, backgroundColor, className, }: WhiteboardPanelProps): react_jsx_runtime.JSX.Element;
|
|
1771
1869
|
|
|
1772
|
-
declare function DocumentPanel({ documentData, documents: externalDocuments, activeDocumentId: externalActiveId, currentPage, zoom, scrollPosition, onDocumentLoad, onDocumentSelect, onDocumentRemove, onPageChange, onZoomChange, onScrollChange, onDocumentClear, mode, isPlaying, onInteract, showTabBar, showToolbar, showPageIndicator, allowUpload, allowMultiple, backgroundColor, className, }: DocumentPanelProps): react_jsx_runtime.JSX.Element;
|
|
1870
|
+
declare function DocumentPanel({ documentData, documents: externalDocuments, activeDocumentId: externalActiveId, currentPage, zoom, scrollPosition, onDocumentLoad, onDocumentSelect, onDocumentRemove, onPageChange, onZoomChange, onScrollChange, onDocumentClear, mode, isPlaying, onInteract, showTabBar, showToolbar, showPageIndicator, allowUpload, allowMultiple, backgroundColor, assetUploadUrl, className, }: DocumentPanelProps): react_jsx_runtime.JSX.Element;
|
|
1773
1871
|
|
|
1774
1872
|
interface VirtualFileSystem {
|
|
1775
1873
|
getFileTree: () => FileSystemEntry;
|
|
@@ -1784,103 +1882,62 @@ interface VirtualFileSystem {
|
|
|
1784
1882
|
notifyChanged?: () => void;
|
|
1785
1883
|
mkdir?: (path: string) => void;
|
|
1786
1884
|
}
|
|
1787
|
-
declare function IDEPanel({ fileSystem, tree: externalTree, files: externalFiles, code: externalCode, language: externalLanguage, currentFile: externalCurrentFile, onCodeChange, onFileChange, onFileCreate, onFileDelete, onFileRename, onFileSelect, onFolderCreate, onFolderDelete, onTerminalCommand, onTerminalClear, onTerminalAddLines, fileCreationState, onFileCreationStart, onFileCreationInput, onFileCreationCancel, fileRenamingState, onFileRenameStart, onFileRenameInput, onFileRenameCancel, expandedFoldersState, onFolderToggle, terminalLines: externalTerminalLines, terminalInput: externalTerminalInput, onTerminalInputChange, onExecute, onTerminalExecute, mode, isPlaying, defaultShowExplorer, defaultShowTerminal, showRunButton, interactiveLabel, initialFiles, initialActiveFile, hoveredFile, onFileHover, textSelection, onTextSelect, editorCursor, onEditorCursorChange }: IDEPanelProps & {
|
|
1885
|
+
declare function IDEPanel({ fileSystem, tree: externalTree, files: externalFiles, code: externalCode, language: externalLanguage, currentFile: externalCurrentFile, onCodeChange, onFileChange, onFileCreate, onFileDelete, onFileRename, onFileSelect, onFolderCreate, onFolderDelete, onTerminalCommand, onTerminalClear, onTerminalAddLines, fileCreationState, onFileCreationStart, onFileCreationInput, onFileCreationCancel, fileRenamingState, onFileRenameStart, onFileRenameInput, onFileRenameCancel, expandedFoldersState, onFolderToggle, terminalLines: externalTerminalLines, terminalInput: externalTerminalInput, onTerminalInputChange, onExecute, onTerminalExecute, mode, isPlaying, defaultShowExplorer, defaultShowTerminal, showRunButton, interactiveLabel, initialFiles, initialActiveFile, hoveredFile, onFileHover, textSelection, onTextSelect, editorCursor, onEditorCursorChange, onInteractionStart, aiSuggestionsEnabled, aiSuggestionsEndpoint, aiSuggestionsDebounceMs, aiDebugEnabled, aiDebugEndpoint, }: IDEPanelProps & {
|
|
1788
1886
|
fileSystem?: VirtualFileSystem;
|
|
1789
1887
|
}): react_jsx_runtime.JSX.Element;
|
|
1790
1888
|
|
|
1791
1889
|
declare function FileExplorer({ tree, selectedFile, expandedFolders, fileCreation, fileRenaming, mode, isPlaying, hoveredFile, onFileHover, onFileSelect, onFileCreate, onFolderCreate, onFileDelete, onFileRename, onFolderToggle, onFileCreationStart, onFileCreationInput, onFileCreationCancel, onFileRenameStart, onFileRenameInput, onFileRenameCancel, className, }: FileExplorerProps): react_jsx_runtime.JSX.Element;
|
|
1792
1890
|
|
|
1793
|
-
declare const Terminal:
|
|
1891
|
+
declare const Terminal: React__default.ForwardRefExoticComponent<TerminalProps & React__default.RefAttributes<TerminalRef>>;
|
|
1794
1892
|
|
|
1795
1893
|
/**
|
|
1796
|
-
*
|
|
1894
|
+
* Learner Branch Types
|
|
1895
|
+
*
|
|
1896
|
+
* A branch is a saved snapshot of the learner's code edits at a specific
|
|
1897
|
+
* moment in the instructor's timeline. Branches are learner-side only —
|
|
1898
|
+
* they never modify the .ct file, events, or manifest.
|
|
1899
|
+
*
|
|
1900
|
+
* @packageDocumentation
|
|
1797
1901
|
*/
|
|
1798
|
-
type ActiveTool$1 = ToolType;
|
|
1799
1902
|
/**
|
|
1800
|
-
*
|
|
1903
|
+
* A point-in-time capture of the IDE state.
|
|
1904
|
+
* Used for both the instructor's original state and the learner's edited state.
|
|
1801
1905
|
*/
|
|
1802
|
-
interface
|
|
1803
|
-
/**
|
|
1804
|
-
|
|
1805
|
-
/**
|
|
1806
|
-
|
|
1807
|
-
/**
|
|
1808
|
-
|
|
1809
|
-
/**
|
|
1810
|
-
|
|
1811
|
-
/**
|
|
1812
|
-
|
|
1813
|
-
/**
|
|
1814
|
-
|
|
1815
|
-
/**
|
|
1816
|
-
|
|
1817
|
-
/** Theme setting */
|
|
1818
|
-
theme?: 'light' | 'dark' | 'system';
|
|
1819
|
-
/** Aspect ratio of the player */
|
|
1820
|
-
aspectRatio?: '16:9' | '4:3' | 'auto';
|
|
1821
|
-
/** Show playback controls toolbar */
|
|
1822
|
-
showToolbar?: boolean;
|
|
1823
|
-
/** Show timeline below player */
|
|
1824
|
-
showTimeline?: boolean;
|
|
1825
|
-
/** Show chapter markers */
|
|
1826
|
-
showChapters?: boolean;
|
|
1827
|
-
/** Show tool sidebar */
|
|
1828
|
-
showToolSidebar?: boolean;
|
|
1829
|
-
/** Auto-play when loaded */
|
|
1830
|
-
autoPlay?: boolean;
|
|
1831
|
-
/** Default playback speed */
|
|
1832
|
-
defaultSpeed?: number;
|
|
1833
|
-
/** Allow fullscreen mode */
|
|
1834
|
-
allowFullscreen?: boolean;
|
|
1835
|
-
/** Default active tool */
|
|
1836
|
-
defaultTool?: ActiveTool$1;
|
|
1837
|
-
/** Called when player is ready */
|
|
1838
|
-
onReady?: () => void;
|
|
1839
|
-
/** Called when playback starts */
|
|
1840
|
-
onPlay?: () => void;
|
|
1841
|
-
/** Called when playback pauses */
|
|
1842
|
-
onPause?: () => void;
|
|
1843
|
-
/** Called on progress update */
|
|
1844
|
-
onProgress?: (time: number, duration: number) => void;
|
|
1845
|
-
/** Called when playback completes */
|
|
1846
|
-
onComplete?: () => void;
|
|
1847
|
-
/** Called on error */
|
|
1848
|
-
onError?: (error: Error) => void;
|
|
1849
|
-
/** Called when entering interactive mode */
|
|
1850
|
-
onInteractionStart?: () => void;
|
|
1851
|
-
/** Called when exiting interactive mode */
|
|
1852
|
-
onInteractionEnd?: (code: string) => void;
|
|
1853
|
-
/** Called when tool changes */
|
|
1854
|
-
onToolChange?: (tool: string) => void;
|
|
1906
|
+
interface BranchSnapshot {
|
|
1907
|
+
/** Active file's code content */
|
|
1908
|
+
code: string;
|
|
1909
|
+
/** Programming language at snapshot time */
|
|
1910
|
+
language: string;
|
|
1911
|
+
/** Which file tab was active (null if single-file mode) */
|
|
1912
|
+
currentFile: string | null;
|
|
1913
|
+
/** Full file system snapshot — path → content */
|
|
1914
|
+
fileSystem: Record<string, string>;
|
|
1915
|
+
/** Terminal output lines if any existed */
|
|
1916
|
+
terminalOutput?: string[];
|
|
1917
|
+
/** Which tool panel was open (code / terminal / whiteboard / document) */
|
|
1918
|
+
activeTool: string;
|
|
1919
|
+
/** Folder paths created by the learner during interactive mode */
|
|
1920
|
+
folders?: string[];
|
|
1855
1921
|
}
|
|
1856
1922
|
/**
|
|
1857
|
-
*
|
|
1923
|
+
* A learner branch — a saved code snapshot at a point in the timeline.
|
|
1858
1924
|
*/
|
|
1859
|
-
interface
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1925
|
+
interface LearnerBranch {
|
|
1926
|
+
/** Unique branch ID (crypto.randomUUID) */
|
|
1927
|
+
id: string;
|
|
1928
|
+
/** Lesson/recording this branch belongs to */
|
|
1929
|
+
lessonId: string;
|
|
1930
|
+
/** Playback time in milliseconds where the learner paused */
|
|
1931
|
+
timeMs: number;
|
|
1932
|
+
/** Instructor's state at that moment (for comparison / restoring) */
|
|
1933
|
+
originalState: BranchSnapshot;
|
|
1934
|
+
/** Learner's edited state */
|
|
1935
|
+
learnerState: BranchSnapshot;
|
|
1936
|
+
/** ISO timestamp of when the branch was created */
|
|
1937
|
+
createdAt: string;
|
|
1938
|
+
/** User-provided label, defaults to "Branch at MM:SS" */
|
|
1939
|
+
label?: string;
|
|
1870
1940
|
}
|
|
1871
|
-
/**
|
|
1872
|
-
* CoursePlayer component
|
|
1873
|
-
*/
|
|
1874
|
-
declare const CoursePlayer: react.ForwardRefExoticComponent<CoursePlayerProps & react.RefAttributes<CoursePlayerRef>>;
|
|
1875
|
-
|
|
1876
|
-
/**
|
|
1877
|
-
* CT-Courses Player - Remote Streaming Types
|
|
1878
|
-
*
|
|
1879
|
-
* Types for streaming playback from a remote CDN/R2 storage.
|
|
1880
|
-
* These types match the streaming service manifest structure.
|
|
1881
|
-
*
|
|
1882
|
-
* @packageDocumentation
|
|
1883
|
-
*/
|
|
1884
1941
|
|
|
1885
1942
|
/**
|
|
1886
1943
|
* Audio quality level information
|
|
@@ -1908,6 +1965,40 @@ interface StreamingRecordingInfo {
|
|
|
1908
1965
|
/** Creation timestamp (ISO 8601) */
|
|
1909
1966
|
createdAt: string;
|
|
1910
1967
|
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Video quality level information
|
|
1970
|
+
*/
|
|
1971
|
+
interface VideoQuality {
|
|
1972
|
+
/** Quality name (low, medium, high) */
|
|
1973
|
+
name: string;
|
|
1974
|
+
/** Bitrate in bits per second */
|
|
1975
|
+
bitrate: number;
|
|
1976
|
+
/** Video width in pixels */
|
|
1977
|
+
width: number;
|
|
1978
|
+
/** Video height in pixels */
|
|
1979
|
+
height: number;
|
|
1980
|
+
/** URL to the quality-specific playlist */
|
|
1981
|
+
playlistUrl?: string;
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Video streaming configuration (webcam overlay)
|
|
1985
|
+
*/
|
|
1986
|
+
interface StreamingVideoConfig {
|
|
1987
|
+
/** Video type (always 'hls' for adaptive streaming) */
|
|
1988
|
+
type: 'hls';
|
|
1989
|
+
/** URL to the HLS master playlist */
|
|
1990
|
+
masterPlaylistUrl: string;
|
|
1991
|
+
/** Available quality levels */
|
|
1992
|
+
qualities: VideoQuality[];
|
|
1993
|
+
/** Video duration in seconds */
|
|
1994
|
+
duration: number;
|
|
1995
|
+
/** Video width in pixels */
|
|
1996
|
+
width: number;
|
|
1997
|
+
/** Video height in pixels */
|
|
1998
|
+
height: number;
|
|
1999
|
+
/** Video codec */
|
|
2000
|
+
codec: string;
|
|
2001
|
+
}
|
|
1911
2002
|
/**
|
|
1912
2003
|
* Audio streaming configuration
|
|
1913
2004
|
*/
|
|
@@ -1947,6 +2038,32 @@ interface StreamingConfig {
|
|
|
1947
2038
|
/** Maximum buffer to maintain (ms) */
|
|
1948
2039
|
maxBufferMs: number;
|
|
1949
2040
|
}
|
|
2041
|
+
/**
|
|
2042
|
+
* An interaction point from the streaming manifest (CDN-safe).
|
|
2043
|
+
* Options intentionally omit `isCorrect` — answers validated server-side only.
|
|
2044
|
+
*/
|
|
2045
|
+
interface InteractionPointManifest {
|
|
2046
|
+
/** Marker ID from the .ct manifest */
|
|
2047
|
+
id: string;
|
|
2048
|
+
/** Interaction type (only 'mcq' for now) */
|
|
2049
|
+
type: 'mcq';
|
|
2050
|
+
/** Time position in milliseconds */
|
|
2051
|
+
timeMs: number;
|
|
2052
|
+
/** Whether to pause playback when this point is reached */
|
|
2053
|
+
pausePlayback: boolean;
|
|
2054
|
+
/** MCQ question data (without isCorrect on options) */
|
|
2055
|
+
mcq: {
|
|
2056
|
+
question: string;
|
|
2057
|
+
options: {
|
|
2058
|
+
id: string;
|
|
2059
|
+
text: string;
|
|
2060
|
+
}[];
|
|
2061
|
+
explanation?: string;
|
|
2062
|
+
allowRetry: boolean;
|
|
2063
|
+
shuffleOptions: boolean;
|
|
2064
|
+
timeoutSeconds: number | null;
|
|
2065
|
+
};
|
|
2066
|
+
}
|
|
1950
2067
|
/**
|
|
1951
2068
|
* Complete streaming manifest structure
|
|
1952
2069
|
* This is the main entry point returned by the streaming service.
|
|
@@ -1960,10 +2077,18 @@ interface StreamingManifest {
|
|
|
1960
2077
|
recording: StreamingRecordingInfo;
|
|
1961
2078
|
/** Audio streaming configuration */
|
|
1962
2079
|
audio: StreamingAudioConfig;
|
|
2080
|
+
/** Video streaming configuration (present when webcam was recorded) */
|
|
2081
|
+
video?: StreamingVideoConfig;
|
|
1963
2082
|
/** Events streaming configuration */
|
|
1964
2083
|
events: StreamingEventsConfig;
|
|
1965
2084
|
/** Streaming playback hints */
|
|
1966
2085
|
streaming: StreamingConfig;
|
|
2086
|
+
/**
|
|
2087
|
+
* Interaction points extracted from .ct manifest quiz markers.
|
|
2088
|
+
* Options omit `isCorrect` — answers are validated server-side only.
|
|
2089
|
+
* Absent or empty when the recording has no quiz markers.
|
|
2090
|
+
*/
|
|
2091
|
+
interactionPoints?: InteractionPointManifest[];
|
|
1967
2092
|
}
|
|
1968
2093
|
/**
|
|
1969
2094
|
* Options for useRemoteStreamingPlayback hook
|
|
@@ -2038,8 +2163,10 @@ interface RemoteStreamingPlaybackState {
|
|
|
2038
2163
|
isPlaying: boolean;
|
|
2039
2164
|
/** Current playback speed */
|
|
2040
2165
|
speed: number;
|
|
2041
|
-
/** Whether the player is ready */
|
|
2166
|
+
/** Whether the player is ready (UI can render — audio+events loaded) */
|
|
2042
2167
|
isReady: boolean;
|
|
2168
|
+
/** Whether ALL sources are loaded and synced (audio+video+events) */
|
|
2169
|
+
allSourcesReady: boolean;
|
|
2043
2170
|
/** Whether currently buffering */
|
|
2044
2171
|
isBuffering: boolean;
|
|
2045
2172
|
/** Buffer health information */
|
|
@@ -2065,6 +2192,16 @@ interface RemoteStreamingPlaybackControls {
|
|
|
2065
2192
|
setSpeed(speed: number): void;
|
|
2066
2193
|
/** Get the audio element for custom controls */
|
|
2067
2194
|
getAudioElement(): HTMLAudioElement | null;
|
|
2195
|
+
/** Get the video element for webcam overlay (null if no video) */
|
|
2196
|
+
getVideoElement(): HTMLVideoElement | null;
|
|
2197
|
+
/** Attach HLS video player to a video element (from WebcamOverlay onVideoRef) */
|
|
2198
|
+
initVideoHls(videoElement: HTMLVideoElement | null): void;
|
|
2199
|
+
/** Get available webcam video quality levels */
|
|
2200
|
+
getVideoQualityLevels(): HLSQualityLevel[];
|
|
2201
|
+
/** Set webcam video quality level (-1 for auto) */
|
|
2202
|
+
setVideoQualityLevel(index: number): void;
|
|
2203
|
+
/** Get current webcam video quality level (-1 = auto) */
|
|
2204
|
+
getVideoQualityLevel(): number;
|
|
2068
2205
|
}
|
|
2069
2206
|
/**
|
|
2070
2207
|
* HLS player configuration
|
|
@@ -2089,81 +2226,12 @@ interface HLSQualityLevel {
|
|
|
2089
2226
|
bitrate: number;
|
|
2090
2227
|
/** Codec string */
|
|
2091
2228
|
codecs: string;
|
|
2229
|
+
/** Video width (0 if audio-only) */
|
|
2230
|
+
width?: number;
|
|
2231
|
+
/** Video height (0 if audio-only) */
|
|
2232
|
+
height?: number;
|
|
2092
2233
|
}
|
|
2093
2234
|
|
|
2094
|
-
type ActiveTool = ToolType;
|
|
2095
|
-
/**
|
|
2096
|
-
* Props for StreamingCoursePlayer
|
|
2097
|
-
*/
|
|
2098
|
-
interface StreamingCoursePlayerProps {
|
|
2099
|
-
/** URL to the streaming manifest.json */
|
|
2100
|
-
manifestUrl: string;
|
|
2101
|
-
/** Theme setting */
|
|
2102
|
-
theme?: 'light' | 'dark' | 'system';
|
|
2103
|
-
/** Aspect ratio of the player */
|
|
2104
|
-
aspectRatio?: '16:9' | '4:3' | 'auto';
|
|
2105
|
-
/** Show playback controls toolbar */
|
|
2106
|
-
showToolbar?: boolean;
|
|
2107
|
-
/** Show tool sidebar */
|
|
2108
|
-
showToolSidebar?: boolean;
|
|
2109
|
-
/** Auto-play when loaded */
|
|
2110
|
-
autoPlay?: boolean;
|
|
2111
|
-
/** Default playback speed */
|
|
2112
|
-
defaultSpeed?: number;
|
|
2113
|
-
/** Allow fullscreen mode */
|
|
2114
|
-
allowFullscreen?: boolean;
|
|
2115
|
-
/** Default active tool */
|
|
2116
|
-
defaultTool?: ActiveTool;
|
|
2117
|
-
/** Maximum chunks to cache */
|
|
2118
|
-
maxCacheSize?: number;
|
|
2119
|
-
/** Additional CSS class */
|
|
2120
|
-
className?: string;
|
|
2121
|
-
/** Called when player is ready */
|
|
2122
|
-
onReady?: () => void;
|
|
2123
|
-
/** Called when playback starts */
|
|
2124
|
-
onPlay?: () => void;
|
|
2125
|
-
/** Called when playback pauses */
|
|
2126
|
-
onPause?: () => void;
|
|
2127
|
-
/** Called on progress update */
|
|
2128
|
-
onProgress?: (time: number, duration: number) => void;
|
|
2129
|
-
/** Called when playback completes */
|
|
2130
|
-
onComplete?: () => void;
|
|
2131
|
-
/** Called on error */
|
|
2132
|
-
onError?: (error: Error) => void;
|
|
2133
|
-
/** Called when buffering state changes */
|
|
2134
|
-
onBuffering?: (isBuffering: boolean) => void;
|
|
2135
|
-
/** Called when tool changes */
|
|
2136
|
-
onToolChange?: (tool: string) => void;
|
|
2137
|
-
/** Go-Judge server URL */
|
|
2138
|
-
goJudgeUrl?: string;
|
|
2139
|
-
/** Go-Judge API key */
|
|
2140
|
-
goJudgeApiKey?: string;
|
|
2141
|
-
/** Show chapter markers */
|
|
2142
|
-
showChapters?: boolean;
|
|
2143
|
-
/** Called when entering interactive mode */
|
|
2144
|
-
onInteractionStart?: () => void;
|
|
2145
|
-
/** Called when exiting interactive mode */
|
|
2146
|
-
onInteractionEnd?: (code: string) => void;
|
|
2147
|
-
}
|
|
2148
|
-
/**
|
|
2149
|
-
* Imperative handle for StreamingCoursePlayer
|
|
2150
|
-
*/
|
|
2151
|
-
interface StreamingCoursePlayerRef {
|
|
2152
|
-
play(): void;
|
|
2153
|
-
pause(): void;
|
|
2154
|
-
seek(timeMs: number): Promise<void>;
|
|
2155
|
-
setSpeed(speed: number): void;
|
|
2156
|
-
getCurrentTime(): number;
|
|
2157
|
-
getDuration(): number;
|
|
2158
|
-
getState(): PlaybackState$1;
|
|
2159
|
-
enterInteractiveMode(): void;
|
|
2160
|
-
exitInteractiveMode(): void;
|
|
2161
|
-
setActiveTool(tool: ActiveTool): void;
|
|
2162
|
-
getManifest(): StreamingManifest | null;
|
|
2163
|
-
getBufferHealth(): RemoteBufferHealth;
|
|
2164
|
-
}
|
|
2165
|
-
declare const StreamingCoursePlayer: react.ForwardRefExoticComponent<StreamingCoursePlayerProps & react.RefAttributes<StreamingCoursePlayerRef>>;
|
|
2166
|
-
|
|
2167
2235
|
/**
|
|
2168
2236
|
* @ct-courses/player - Type Definitions
|
|
2169
2237
|
*/
|
|
@@ -2406,33 +2474,275 @@ interface VolumeControlProps {
|
|
|
2406
2474
|
onMuteToggle: () => void;
|
|
2407
2475
|
className?: string;
|
|
2408
2476
|
}
|
|
2409
|
-
|
|
2410
2477
|
/**
|
|
2411
|
-
*
|
|
2412
|
-
*
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2478
|
+
* Client-side interaction point (no isCorrect — answers validated server-side).
|
|
2479
|
+
* Mirrors InteractionPointManifest from streaming.ts but usable without a manifest.
|
|
2480
|
+
*/
|
|
2481
|
+
interface InteractionPoint {
|
|
2482
|
+
/** Unique identifier */
|
|
2483
|
+
id: string;
|
|
2484
|
+
/** Interaction type */
|
|
2485
|
+
type: 'mcq';
|
|
2486
|
+
/** Time position in milliseconds */
|
|
2487
|
+
timeMs: number;
|
|
2488
|
+
/** Whether to pause playback when this point is reached */
|
|
2489
|
+
pausePlayback: boolean;
|
|
2490
|
+
/** MCQ question data */
|
|
2491
|
+
mcq: {
|
|
2492
|
+
question: string;
|
|
2493
|
+
options: {
|
|
2494
|
+
id: string;
|
|
2495
|
+
text: string;
|
|
2496
|
+
}[];
|
|
2497
|
+
explanation?: string;
|
|
2498
|
+
allowRetry: boolean;
|
|
2499
|
+
shuffleOptions: boolean;
|
|
2500
|
+
timeoutSeconds: number | null;
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
/**
|
|
2504
|
+
* MCQ answer submission from the player
|
|
2505
|
+
*/
|
|
2506
|
+
interface MCQSubmission {
|
|
2507
|
+
/** The interaction point ID */
|
|
2508
|
+
pointId: string;
|
|
2509
|
+
/** Selected option IDs */
|
|
2510
|
+
selectedOptionIds: string[];
|
|
2511
|
+
}
|
|
2512
|
+
/**
|
|
2513
|
+
* MCQ answer result returned from the host app's callback
|
|
2420
2514
|
*/
|
|
2515
|
+
interface MCQResult {
|
|
2516
|
+
/** Whether the answer was correct */
|
|
2517
|
+
correct: boolean;
|
|
2518
|
+
/** Optional explanation text */
|
|
2519
|
+
explanation?: string;
|
|
2520
|
+
/** Correct option IDs (revealed after answering) */
|
|
2521
|
+
correctOptionIds?: string[];
|
|
2522
|
+
}
|
|
2421
2523
|
|
|
2422
2524
|
/**
|
|
2423
|
-
*
|
|
2525
|
+
* Active tool type - matches ToolType from @ct-courses/ui
|
|
2424
2526
|
*/
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
/**
|
|
2431
|
-
|
|
2432
|
-
/**
|
|
2433
|
-
|
|
2434
|
-
/**
|
|
2435
|
-
|
|
2527
|
+
type ActiveTool$1 = ToolType;
|
|
2528
|
+
/**
|
|
2529
|
+
* Props for the CoursePlayer component
|
|
2530
|
+
*/
|
|
2531
|
+
interface CoursePlayerProps {
|
|
2532
|
+
/** Pre-loaded recording data */
|
|
2533
|
+
recording?: CTRecording;
|
|
2534
|
+
/** URL to a .ct file */
|
|
2535
|
+
recordingUrl?: string;
|
|
2536
|
+
/** Recording ID to fetch from API */
|
|
2537
|
+
recordingId?: string;
|
|
2538
|
+
/** Base API URL for fetching recordings */
|
|
2539
|
+
apiUrl?: string;
|
|
2540
|
+
/** Authentication token */
|
|
2541
|
+
authToken?: string;
|
|
2542
|
+
/** Go-Judge server URL */
|
|
2543
|
+
goJudgeUrl?: string;
|
|
2544
|
+
/** Go-Judge API key */
|
|
2545
|
+
goJudgeApiKey?: string;
|
|
2546
|
+
/** Theme setting */
|
|
2547
|
+
theme?: "light" | "dark" | "system";
|
|
2548
|
+
/** Aspect ratio of the player */
|
|
2549
|
+
aspectRatio?: "16:9" | "4:3" | "auto";
|
|
2550
|
+
/** Show playback controls toolbar */
|
|
2551
|
+
showToolbar?: boolean;
|
|
2552
|
+
/** Show timeline below player */
|
|
2553
|
+
showTimeline?: boolean;
|
|
2554
|
+
/** Show chapter markers */
|
|
2555
|
+
showChapters?: boolean;
|
|
2556
|
+
/** Show tool sidebar */
|
|
2557
|
+
showToolSidebar?: boolean;
|
|
2558
|
+
/** Auto-play when loaded */
|
|
2559
|
+
autoPlay?: boolean;
|
|
2560
|
+
/** Default playback speed */
|
|
2561
|
+
defaultSpeed?: number;
|
|
2562
|
+
/** Allow fullscreen mode */
|
|
2563
|
+
allowFullscreen?: boolean;
|
|
2564
|
+
/** Default active tool */
|
|
2565
|
+
defaultTool?: ActiveTool$1;
|
|
2566
|
+
/** Called when player is ready */
|
|
2567
|
+
onReady?: () => void;
|
|
2568
|
+
/** Called when playback starts */
|
|
2569
|
+
onPlay?: () => void;
|
|
2570
|
+
/** Called when playback pauses */
|
|
2571
|
+
onPause?: () => void;
|
|
2572
|
+
/** Called on progress update */
|
|
2573
|
+
onProgress?: (time: number, duration: number) => void;
|
|
2574
|
+
/** Called when playback completes */
|
|
2575
|
+
onComplete?: () => void;
|
|
2576
|
+
/** Called on error */
|
|
2577
|
+
onError?: (error: Error) => void;
|
|
2578
|
+
/** Called when entering interactive mode */
|
|
2579
|
+
onInteractionStart?: () => void;
|
|
2580
|
+
/** Called when exiting interactive mode */
|
|
2581
|
+
onInteractionEnd?: (code: string) => void;
|
|
2582
|
+
/** Called when tool changes */
|
|
2583
|
+
onToolChange?: (tool: string) => void;
|
|
2584
|
+
/** Interaction points (MCQs) to display during playback */
|
|
2585
|
+
interactionPoints?: InteractionPoint[];
|
|
2586
|
+
/** Pre-answered point IDs (skip these MCQs) */
|
|
2587
|
+
answeredPointIds?: Set<string>;
|
|
2588
|
+
/** Called when a learner submits an MCQ answer. Host app validates server-side. */
|
|
2589
|
+
onSubmitAnswer?: (pointId: string, selectedOptionIds: string[]) => Promise<MCQResult>;
|
|
2590
|
+
/** Info about the next lesson for auto-advance overlay */
|
|
2591
|
+
nextLesson?: {
|
|
2592
|
+
id: string;
|
|
2593
|
+
title: string;
|
|
2594
|
+
} | null;
|
|
2595
|
+
/** Called when the player wants to navigate to the next lesson */
|
|
2596
|
+
onNavigateToLesson?: (lessonId: string) => void;
|
|
2597
|
+
/** Called when the current lesson completes (before transition) */
|
|
2598
|
+
onLessonComplete?: () => void;
|
|
2599
|
+
/** Lesson ID used to scope saved branches in localStorage */
|
|
2600
|
+
lessonId?: string;
|
|
2601
|
+
/** Enable the branch save feature (default: true) */
|
|
2602
|
+
enableBranches?: boolean;
|
|
2603
|
+
/** Called after a branch is saved */
|
|
2604
|
+
onBranchSave?: (branch: LearnerBranch) => void;
|
|
2605
|
+
/** Called when a learner restores a saved branch */
|
|
2606
|
+
onBranchRestore?: (branch: LearnerBranch) => void;
|
|
2607
|
+
/** Called after a branch is deleted */
|
|
2608
|
+
onBranchDelete?: (branchId: string) => void;
|
|
2609
|
+
/** Maximum branches per lesson (default: 50) */
|
|
2610
|
+
maxBranches?: number;
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Imperative handle for CoursePlayer
|
|
2614
|
+
*/
|
|
2615
|
+
interface CoursePlayerRef {
|
|
2616
|
+
play(): void;
|
|
2617
|
+
pause(): void;
|
|
2618
|
+
seek(timeMs: number): void;
|
|
2619
|
+
setSpeed(speed: number): void;
|
|
2620
|
+
getCurrentTime(): number;
|
|
2621
|
+
getDuration(): number;
|
|
2622
|
+
getState(): PlaybackState$1;
|
|
2623
|
+
enterInteractiveMode(): void;
|
|
2624
|
+
exitInteractiveMode(): void;
|
|
2625
|
+
setActiveTool(tool: ActiveTool$1): void;
|
|
2626
|
+
}
|
|
2627
|
+
/**
|
|
2628
|
+
* CoursePlayer component
|
|
2629
|
+
*/
|
|
2630
|
+
declare const CoursePlayer: React__default.ForwardRefExoticComponent<CoursePlayerProps & React__default.RefAttributes<CoursePlayerRef>>;
|
|
2631
|
+
|
|
2632
|
+
type ActiveTool = ToolType;
|
|
2633
|
+
/**
|
|
2634
|
+
* Props for StreamingCoursePlayer
|
|
2635
|
+
*/
|
|
2636
|
+
interface StreamingCoursePlayerProps {
|
|
2637
|
+
/** URL to the streaming manifest.json */
|
|
2638
|
+
manifestUrl: string;
|
|
2639
|
+
/** Theme setting */
|
|
2640
|
+
theme?: "light" | "dark" | "system";
|
|
2641
|
+
/** Aspect ratio of the player */
|
|
2642
|
+
aspectRatio?: "16:9" | "4:3" | "auto";
|
|
2643
|
+
/** Show playback controls toolbar */
|
|
2644
|
+
showToolbar?: boolean;
|
|
2645
|
+
/** Show tool sidebar */
|
|
2646
|
+
showToolSidebar?: boolean;
|
|
2647
|
+
/** Auto-play when loaded */
|
|
2648
|
+
autoPlay?: boolean;
|
|
2649
|
+
/** Default playback speed */
|
|
2650
|
+
defaultSpeed?: number;
|
|
2651
|
+
/** Allow fullscreen mode */
|
|
2652
|
+
allowFullscreen?: boolean;
|
|
2653
|
+
/** Default active tool */
|
|
2654
|
+
defaultTool?: ActiveTool;
|
|
2655
|
+
/** Maximum chunks to cache */
|
|
2656
|
+
maxCacheSize?: number;
|
|
2657
|
+
/** Additional CSS class */
|
|
2658
|
+
className?: string;
|
|
2659
|
+
/** Called when player is ready */
|
|
2660
|
+
onReady?: () => void;
|
|
2661
|
+
/** Called when playback starts */
|
|
2662
|
+
onPlay?: () => void;
|
|
2663
|
+
/** Called when playback pauses */
|
|
2664
|
+
onPause?: () => void;
|
|
2665
|
+
/** Called on progress update */
|
|
2666
|
+
onProgress?: (time: number, duration: number) => void;
|
|
2667
|
+
/** Called when playback completes */
|
|
2668
|
+
onComplete?: () => void;
|
|
2669
|
+
/** Called on error */
|
|
2670
|
+
onError?: (error: Error) => void;
|
|
2671
|
+
/** Called when buffering state changes */
|
|
2672
|
+
onBuffering?: (isBuffering: boolean) => void;
|
|
2673
|
+
/** Called when tool changes */
|
|
2674
|
+
onToolChange?: (tool: string) => void;
|
|
2675
|
+
/** Go-Judge server URL */
|
|
2676
|
+
goJudgeUrl?: string;
|
|
2677
|
+
/** Go-Judge API key */
|
|
2678
|
+
goJudgeApiKey?: string;
|
|
2679
|
+
/** Show chapter markers */
|
|
2680
|
+
showChapters?: boolean;
|
|
2681
|
+
/** Called when entering interactive mode */
|
|
2682
|
+
onInteractionStart?: () => void;
|
|
2683
|
+
/** Called when exiting interactive mode */
|
|
2684
|
+
onInteractionEnd?: (code: string) => void;
|
|
2685
|
+
/** Interaction points (MCQs) to display during playback */
|
|
2686
|
+
interactionPoints?: InteractionPoint[];
|
|
2687
|
+
/** Pre-answered point IDs (skip these MCQs) */
|
|
2688
|
+
answeredPointIds?: Set<string>;
|
|
2689
|
+
/** Called when a learner submits an MCQ answer. Host app validates server-side. */
|
|
2690
|
+
onSubmitAnswer?: (pointId: string, selectedOptionIds: string[]) => Promise<MCQResult>;
|
|
2691
|
+
/** Info about the next lesson for auto-advance overlay */
|
|
2692
|
+
nextLesson?: {
|
|
2693
|
+
id: string;
|
|
2694
|
+
title: string;
|
|
2695
|
+
} | null;
|
|
2696
|
+
/** Called when the player wants to navigate to the next lesson */
|
|
2697
|
+
onNavigateToLesson?: (lessonId: string) => void;
|
|
2698
|
+
/** Called when the current lesson completes (before transition) */
|
|
2699
|
+
onLessonComplete?: () => void;
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Imperative handle for StreamingCoursePlayer
|
|
2703
|
+
*/
|
|
2704
|
+
interface StreamingCoursePlayerRef {
|
|
2705
|
+
play(): void;
|
|
2706
|
+
pause(): void;
|
|
2707
|
+
seek(timeMs: number): Promise<void>;
|
|
2708
|
+
setSpeed(speed: number): void;
|
|
2709
|
+
getCurrentTime(): number;
|
|
2710
|
+
getDuration(): number;
|
|
2711
|
+
getState(): PlaybackState$1;
|
|
2712
|
+
enterInteractiveMode(): void;
|
|
2713
|
+
exitInteractiveMode(): void;
|
|
2714
|
+
setActiveTool(tool: ActiveTool): void;
|
|
2715
|
+
getManifest(): StreamingManifest | null;
|
|
2716
|
+
getBufferHealth(): RemoteBufferHealth;
|
|
2717
|
+
}
|
|
2718
|
+
declare const StreamingCoursePlayer: React__default.ForwardRefExoticComponent<StreamingCoursePlayerProps & React__default.RefAttributes<StreamingCoursePlayerRef>>;
|
|
2719
|
+
|
|
2720
|
+
/**
|
|
2721
|
+
* usePlayback Hook
|
|
2722
|
+
*
|
|
2723
|
+
* Core playback engine hook using @ct-courses/core StateEngine.
|
|
2724
|
+
* Supports audio synchronization as master clock (no video/webcam).
|
|
2725
|
+
*
|
|
2726
|
+
* CRITICAL SYNC ARCHITECTURE:
|
|
2727
|
+
* - AUDIO is the MASTER CLOCK when media exists
|
|
2728
|
+
* - Events are applied based on audio.currentTime
|
|
2729
|
+
* - Without media, use requestAnimationFrame timing
|
|
2730
|
+
*/
|
|
2731
|
+
|
|
2732
|
+
/**
|
|
2733
|
+
* Playback state returned by the hook
|
|
2734
|
+
*/
|
|
2735
|
+
interface PlaybackHookState {
|
|
2736
|
+
/** Current playback state */
|
|
2737
|
+
state: PlaybackState$1;
|
|
2738
|
+
/** Current time in milliseconds */
|
|
2739
|
+
currentTime: number;
|
|
2740
|
+
/** Total duration in milliseconds */
|
|
2741
|
+
duration: number;
|
|
2742
|
+
/** Whether currently playing */
|
|
2743
|
+
isPlaying: boolean;
|
|
2744
|
+
/** Current playback speed */
|
|
2745
|
+
speed: number;
|
|
2436
2746
|
/** Whether recording is loaded */
|
|
2437
2747
|
isLoaded: boolean;
|
|
2438
2748
|
/** Volume level (0-1) */
|
|
@@ -2453,6 +2763,7 @@ interface PlaybackControls {
|
|
|
2453
2763
|
setVolume(volume: number): void;
|
|
2454
2764
|
setMuted(muted: boolean): void;
|
|
2455
2765
|
setAudioElement(audio: HTMLAudioElement | null): void;
|
|
2766
|
+
setVideoElement(video: HTMLVideoElement | null): void;
|
|
2456
2767
|
enterInteractiveMode(): void;
|
|
2457
2768
|
exitInteractiveMode(): void;
|
|
2458
2769
|
setInteractiveCode(code: string): void;
|
|
@@ -2466,6 +2777,10 @@ interface PlaybackControls {
|
|
|
2466
2777
|
x: number;
|
|
2467
2778
|
y: number;
|
|
2468
2779
|
}): void;
|
|
2780
|
+
/** Inject a full branch snapshot into the interactive state. Only works when isInteracting is true. */
|
|
2781
|
+
injectInteractiveState(snapshot: BranchSnapshot): void;
|
|
2782
|
+
/** Get the engine's (instructor's) state at a given time, without affecting playback position. */
|
|
2783
|
+
getEngineStateAtTime(timeMs: number): PlaybackState$1 | null;
|
|
2469
2784
|
}
|
|
2470
2785
|
/**
|
|
2471
2786
|
* Options for usePlayback hook
|
|
@@ -2712,21 +3027,233 @@ declare function useAudioSync(options: UseAudioSyncOptions): AudioSyncState & {
|
|
|
2712
3027
|
* Hook for managing audio element lifecycle
|
|
2713
3028
|
*/
|
|
2714
3029
|
declare function useAudioElement(src: string | null): {
|
|
2715
|
-
audioRef:
|
|
3030
|
+
audioRef: React__default.MutableRefObject<HTMLAudioElement | null>;
|
|
3031
|
+
isLoaded: boolean;
|
|
3032
|
+
error: Error | null;
|
|
3033
|
+
duration: number;
|
|
3034
|
+
};
|
|
3035
|
+
|
|
3036
|
+
/**
|
|
3037
|
+
* useVideoSync Hook
|
|
3038
|
+
*
|
|
3039
|
+
* Synchronizes video playback with event state.
|
|
3040
|
+
* Handles video/event drift and maintains sync within tolerance.
|
|
3041
|
+
*
|
|
3042
|
+
* @packageDocumentation
|
|
3043
|
+
*/
|
|
3044
|
+
/**
|
|
3045
|
+
* Video sync state
|
|
3046
|
+
*/
|
|
3047
|
+
interface VideoSyncState {
|
|
3048
|
+
/** Current video time in ms */
|
|
3049
|
+
videoTime: number;
|
|
3050
|
+
/** Current event time in ms */
|
|
3051
|
+
eventTime: number;
|
|
3052
|
+
/** Drift between video and events (ms) */
|
|
3053
|
+
drift: number;
|
|
3054
|
+
/** Is sync healthy (within tolerance) */
|
|
3055
|
+
isSynced: boolean;
|
|
3056
|
+
/** Is video loaded */
|
|
3057
|
+
isVideoReady: boolean;
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* Video sync controls
|
|
3061
|
+
*/
|
|
3062
|
+
interface VideoSyncControls {
|
|
3063
|
+
/** Sync events to video time */
|
|
3064
|
+
syncToVideo(): void;
|
|
3065
|
+
/** Sync video to event time */
|
|
3066
|
+
syncVideoTo(timeMs: number): void;
|
|
3067
|
+
/** Force resync */
|
|
3068
|
+
forceResync(): void;
|
|
3069
|
+
}
|
|
3070
|
+
/**
|
|
3071
|
+
* Options for useVideoSync hook
|
|
3072
|
+
*/
|
|
3073
|
+
interface UseVideoSyncOptions {
|
|
3074
|
+
/** Reference to video element */
|
|
3075
|
+
videoRef: React.RefObject<HTMLVideoElement>;
|
|
3076
|
+
/** Current event time */
|
|
3077
|
+
eventTime: number;
|
|
3078
|
+
/** Is currently playing */
|
|
3079
|
+
isPlaying: boolean;
|
|
3080
|
+
/** Playback speed */
|
|
3081
|
+
speed: number;
|
|
3082
|
+
/** Maximum allowed drift in ms before resync (default: 500ms) */
|
|
3083
|
+
driftTolerance?: number;
|
|
3084
|
+
/** Callback when video time updates */
|
|
3085
|
+
onVideoTimeUpdate?: (timeMs: number) => void;
|
|
3086
|
+
/** Callback when sync is lost */
|
|
3087
|
+
onSyncLost?: (drift: number) => void;
|
|
3088
|
+
/** Callback when sync is restored */
|
|
3089
|
+
onSyncRestored?: () => void;
|
|
3090
|
+
}
|
|
3091
|
+
/**
|
|
3092
|
+
* Hook for synchronizing video playback with event state
|
|
3093
|
+
*/
|
|
3094
|
+
declare function useVideoSync(options: UseVideoSyncOptions): VideoSyncState & {
|
|
3095
|
+
controls: VideoSyncControls;
|
|
3096
|
+
};
|
|
3097
|
+
/**
|
|
3098
|
+
* Hook for managing video element lifecycle
|
|
3099
|
+
*/
|
|
3100
|
+
declare function useVideoElement(src: string | null): {
|
|
3101
|
+
videoRef: React__default.MutableRefObject<HTMLVideoElement | null>;
|
|
2716
3102
|
isLoaded: boolean;
|
|
2717
3103
|
error: Error | null;
|
|
2718
3104
|
duration: number;
|
|
2719
3105
|
};
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
3106
|
+
|
|
3107
|
+
/**
|
|
3108
|
+
* useInteractionPoints — monitors playback time and triggers MCQ pauses.
|
|
3109
|
+
*
|
|
3110
|
+
* The hook is player-mode agnostic: it only needs the current time (ms),
|
|
3111
|
+
* a pause callback, and a play callback. Both CoursePlayer and
|
|
3112
|
+
* StreamingCoursePlayer can use it.
|
|
3113
|
+
*
|
|
3114
|
+
* Edge cases handled:
|
|
3115
|
+
* - Seek past unanswered MCQ → still triggers (first unanswered point ≤ currentTime)
|
|
3116
|
+
* - Seek backwards past a triggered-but-unanswered point → re-evaluates
|
|
3117
|
+
* - Multiple MCQs at exact same time → triggers in array order
|
|
3118
|
+
* - Race: activePoint takes priority — no duplicate triggers while overlay is open
|
|
3119
|
+
*
|
|
3120
|
+
* @packageDocumentation
|
|
3121
|
+
*/
|
|
3122
|
+
|
|
3123
|
+
interface UseInteractionPointsOptions {
|
|
3124
|
+
/** Sorted interaction points (ascending by timeMs) */
|
|
3125
|
+
interactionPoints: InteractionPoint[];
|
|
3126
|
+
/** Current playback time in milliseconds */
|
|
3127
|
+
currentTimeMs: number;
|
|
3128
|
+
/** Callback to pause playback */
|
|
3129
|
+
pause: () => void;
|
|
3130
|
+
/** Callback to resume playback */
|
|
3131
|
+
play: () => void;
|
|
3132
|
+
/** Pre-loaded set of already-answered point IDs */
|
|
3133
|
+
initialAnsweredPointIds?: Set<string>;
|
|
3134
|
+
}
|
|
3135
|
+
interface UseInteractionPointsResult {
|
|
3136
|
+
/** The interaction point currently requiring attention, or null */
|
|
3137
|
+
activePoint: InteractionPoint | null;
|
|
3138
|
+
/** Dismiss the active point (adds to answered, resumes playback) */
|
|
3139
|
+
dismissPoint: () => void;
|
|
3140
|
+
/** Mark a point as answered without dismissing (for pre-loading state) */
|
|
3141
|
+
markAnswered: (pointId: string) => void;
|
|
3142
|
+
/** Set of all answered point IDs */
|
|
3143
|
+
answeredPointIds: Set<string>;
|
|
3144
|
+
}
|
|
3145
|
+
declare function useInteractionPoints({ interactionPoints, currentTimeMs, pause, play, initialAnsweredPointIds, }: UseInteractionPointsOptions): UseInteractionPointsResult;
|
|
3146
|
+
|
|
3147
|
+
/**
|
|
3148
|
+
* useBranching — manages lesson-to-lesson transition with auto-advance countdown.
|
|
3149
|
+
*
|
|
3150
|
+
* @packageDocumentation
|
|
3151
|
+
*/
|
|
3152
|
+
interface UseBranchingOptions {
|
|
3153
|
+
/** Next lesson info (null = course complete) */
|
|
3154
|
+
nextLesson: {
|
|
3155
|
+
id: string;
|
|
3156
|
+
title: string;
|
|
3157
|
+
} | null;
|
|
3158
|
+
/** Seconds before auto-navigating (default 5) */
|
|
3159
|
+
autoAdvanceSeconds?: number;
|
|
3160
|
+
/** Called when auto-advance or manual skip triggers navigation */
|
|
3161
|
+
onNavigate: (lessonId: string) => void;
|
|
3162
|
+
}
|
|
3163
|
+
interface UseBranchingResult {
|
|
3164
|
+
/** Whether the transition overlay is active */
|
|
3165
|
+
isTransitioning: boolean;
|
|
3166
|
+
/** Current countdown value (seconds remaining, 0 = done) */
|
|
3167
|
+
countdown: number;
|
|
3168
|
+
/** Start the transition overlay + countdown */
|
|
3169
|
+
startTransition: () => void;
|
|
3170
|
+
/** Skip the countdown and navigate immediately */
|
|
3171
|
+
skipToNext: () => void;
|
|
3172
|
+
/** Pause the auto-advance but keep the overlay visible */
|
|
3173
|
+
cancelAutoAdvance: () => void;
|
|
3174
|
+
}
|
|
3175
|
+
declare function useBranching({ nextLesson, autoAdvanceSeconds, onNavigate, }: UseBranchingOptions): UseBranchingResult;
|
|
3176
|
+
|
|
3177
|
+
/**
|
|
3178
|
+
* useBranches — manages learner branch state for a single lesson.
|
|
3179
|
+
*
|
|
3180
|
+
* Handles save / delete / rename / restore of learner code snapshots,
|
|
3181
|
+
* persisted to localStorage via branchStorage utilities.
|
|
3182
|
+
*
|
|
3183
|
+
* @packageDocumentation
|
|
3184
|
+
*/
|
|
3185
|
+
|
|
3186
|
+
interface UseBranchesOptions {
|
|
3187
|
+
/** Lesson/recording ID — branches are scoped to this. Undefined = feature disabled. */
|
|
3188
|
+
lessonId: string | undefined;
|
|
3189
|
+
/** Returns current playback time in milliseconds */
|
|
3190
|
+
getCurrentTimeMs: () => number;
|
|
3191
|
+
/** Captures the learner's current IDE state (interactive mode state) */
|
|
3192
|
+
getCurrentState: () => BranchSnapshot;
|
|
3193
|
+
/** Captures the instructor's state at the current time from the engine */
|
|
3194
|
+
getOriginalState: () => BranchSnapshot;
|
|
3195
|
+
/** Called when the learner wants to restore a branch (parent orchestrates seek + inject) */
|
|
3196
|
+
onRestoreBranch?: (branch: LearnerBranch) => void;
|
|
3197
|
+
/** Called after a branch is successfully saved (for analytics / callbacks) */
|
|
3198
|
+
onBranchSaved?: (branch: LearnerBranch) => void;
|
|
3199
|
+
/** Called after a branch is deleted */
|
|
3200
|
+
onBranchDeleted?: (branchId: string) => void;
|
|
3201
|
+
/** Maximum branches per lesson (default 50) */
|
|
3202
|
+
maxBranches?: number;
|
|
3203
|
+
}
|
|
3204
|
+
interface UseBranchesResult {
|
|
3205
|
+
/** All branches for the current lesson, sorted oldest-first */
|
|
3206
|
+
branches: LearnerBranch[];
|
|
3207
|
+
/** Number of saved branches */
|
|
3208
|
+
branchCount: number;
|
|
3209
|
+
/** Whether the feature is enabled (lessonId is defined) */
|
|
3210
|
+
enabled: boolean;
|
|
3211
|
+
/** Save a new branch from the current interactive state. Returns the created branch, or null if disabled / duplicate. */
|
|
3212
|
+
saveBranch: (label?: string) => LearnerBranch | null;
|
|
3213
|
+
/** Delete a branch by ID */
|
|
3214
|
+
deleteBranch: (branchId: string) => void;
|
|
3215
|
+
/** Rename a branch */
|
|
3216
|
+
renameBranch: (branchId: string, label: string) => void;
|
|
3217
|
+
/** Restore a branch — delegates to parent via onRestoreBranch callback */
|
|
3218
|
+
restoreBranch: (branchId: string) => void;
|
|
3219
|
+
/** Check if a branch at this timeMs with this code already exists (duplicate detection) */
|
|
3220
|
+
isDuplicate: (timeMs: number, code: string) => boolean;
|
|
3221
|
+
}
|
|
3222
|
+
declare function useBranches(options: UseBranchesOptions): UseBranchesResult;
|
|
3223
|
+
|
|
3224
|
+
/**
|
|
3225
|
+
* Branch Storage — localStorage CRUD helpers
|
|
3226
|
+
*
|
|
3227
|
+
* Persists learner branches as JSON arrays keyed by lesson ID.
|
|
3228
|
+
* Key format: `ct-branches:<lessonId>`
|
|
3229
|
+
*
|
|
3230
|
+
* Pure functions — no React, no hooks.
|
|
3231
|
+
*
|
|
3232
|
+
* @packageDocumentation
|
|
3233
|
+
*/
|
|
3234
|
+
|
|
3235
|
+
/**
|
|
3236
|
+
* Load all branches for a lesson from localStorage.
|
|
3237
|
+
* Returns empty array if nothing stored or on parse error.
|
|
3238
|
+
* Sorted by `createdAt` ascending (oldest first).
|
|
3239
|
+
*/
|
|
3240
|
+
declare function loadBranches(lessonId: string): LearnerBranch[];
|
|
3241
|
+
/**
|
|
3242
|
+
* Persist a new branch. Caps at `maxBranches` per lesson (drops oldest).
|
|
3243
|
+
*/
|
|
3244
|
+
declare function saveBranch(lessonId: string, branch: LearnerBranch, maxBranches?: number): void;
|
|
3245
|
+
/**
|
|
3246
|
+
* Delete a single branch by ID.
|
|
3247
|
+
*/
|
|
3248
|
+
declare function deleteBranch(lessonId: string, branchId: string): void;
|
|
3249
|
+
/**
|
|
3250
|
+
* Update the label of an existing branch.
|
|
3251
|
+
*/
|
|
3252
|
+
declare function updateBranchLabel(lessonId: string, branchId: string, label: string): void;
|
|
3253
|
+
/**
|
|
3254
|
+
* Format milliseconds as "MM:SS" for default branch labels.
|
|
3255
|
+
*/
|
|
3256
|
+
declare function formatBranchTime(ms: number): string;
|
|
2730
3257
|
|
|
2731
3258
|
/**
|
|
2732
3259
|
* HLS Loader Utility
|
|
@@ -2757,6 +3284,29 @@ interface HLSPlayerInstance {
|
|
|
2757
3284
|
/** Remove event listener */
|
|
2758
3285
|
off: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
2759
3286
|
}
|
|
3287
|
+
/**
|
|
3288
|
+
* HLS video player instance (mirrors HLSPlayerInstance but for video elements)
|
|
3289
|
+
*/
|
|
3290
|
+
interface HLSVideoPlayerInstance {
|
|
3291
|
+
/** The HLS.js instance (null if using native HLS) */
|
|
3292
|
+
hls: Hls | null;
|
|
3293
|
+
/** The video element */
|
|
3294
|
+
videoElement: HTMLVideoElement;
|
|
3295
|
+
/** Whether this is using native HLS (Safari) */
|
|
3296
|
+
isNative: boolean;
|
|
3297
|
+
/** Destroy and cleanup */
|
|
3298
|
+
destroy: () => void;
|
|
3299
|
+
/** Get current quality levels */
|
|
3300
|
+
getQualityLevels: () => HLSQualityLevel[];
|
|
3301
|
+
/** Set quality level (-1 for auto) */
|
|
3302
|
+
setQualityLevel: (index: number) => void;
|
|
3303
|
+
/** Get current quality level */
|
|
3304
|
+
getCurrentQualityLevel: () => number;
|
|
3305
|
+
/** Add event listener for HLS events */
|
|
3306
|
+
on: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
3307
|
+
/** Remove event listener */
|
|
3308
|
+
off: (event: string, callback: (...args: unknown[]) => void) => void;
|
|
3309
|
+
}
|
|
2760
3310
|
interface HLSEvents {
|
|
2761
3311
|
/** Manifest has been parsed and is ready */
|
|
2762
3312
|
MANIFEST_PARSED: 'hlsManifestParsed';
|
|
@@ -2795,12 +3345,19 @@ declare function createHlsPlayer(audioElement: HTMLAudioElement, masterPlaylistU
|
|
|
2795
3345
|
/**
|
|
2796
3346
|
* Destroy an HLS player instance safely
|
|
2797
3347
|
*/
|
|
2798
|
-
declare function destroyHlsPlayer(player: HLSPlayerInstance | null): void;
|
|
3348
|
+
declare function destroyHlsPlayer(player: HLSPlayerInstance | HLSVideoPlayerInstance | null): void;
|
|
2799
3349
|
|
|
2800
3350
|
interface Marker$1 {
|
|
2801
3351
|
time: number;
|
|
2802
3352
|
label?: string;
|
|
2803
|
-
type?:
|
|
3353
|
+
type?: "chapter" | "bookmark" | "quiz";
|
|
3354
|
+
}
|
|
3355
|
+
interface VideoQualityLevel {
|
|
3356
|
+
index: number;
|
|
3357
|
+
bitrate: number;
|
|
3358
|
+
codecs: string;
|
|
3359
|
+
width?: number;
|
|
3360
|
+
height?: number;
|
|
2804
3361
|
}
|
|
2805
3362
|
interface PlayerControlsProps {
|
|
2806
3363
|
isPlaying: boolean;
|
|
@@ -2811,6 +3368,9 @@ interface PlayerControlsProps {
|
|
|
2811
3368
|
playbackSpeed: number;
|
|
2812
3369
|
markers?: Marker$1[];
|
|
2813
3370
|
isFullscreen?: boolean;
|
|
3371
|
+
videoQualityLevels?: VideoQualityLevel[];
|
|
3372
|
+
videoQualityLevel?: number;
|
|
3373
|
+
onVideoQualityChange?: (index: number) => void;
|
|
2814
3374
|
onPlayPause: () => void;
|
|
2815
3375
|
onSeek: (timeMs: number) => void;
|
|
2816
3376
|
onSeekStart?: () => void;
|
|
@@ -2821,11 +3381,28 @@ interface PlayerControlsProps {
|
|
|
2821
3381
|
onMuteToggle: () => void;
|
|
2822
3382
|
onSpeedChange: (speed: number) => void;
|
|
2823
3383
|
onFullscreenToggle?: () => void;
|
|
3384
|
+
/** Called when the user interacts with the code editor area while playing.
|
|
3385
|
+
* The parent should pause playback when this fires. */
|
|
3386
|
+
onEditorInteraction?: () => void;
|
|
3387
|
+
/** Interaction points — purple dots rendered on the seek bar */
|
|
3388
|
+
interactionPoints?: InteractionPoint[];
|
|
3389
|
+
/** Saved learner branches — green diamond markers on the progress bar */
|
|
3390
|
+
branches?: LearnerBranch[];
|
|
3391
|
+
/** Callback when a branch marker is clicked */
|
|
3392
|
+
onBranchClick?: (branch: LearnerBranch) => void;
|
|
3393
|
+
/** Number of saved branches (for badge) */
|
|
3394
|
+
branchCount?: number;
|
|
3395
|
+
/** Whether the branch panel is currently open */
|
|
3396
|
+
isBranchPanelOpen?: boolean;
|
|
3397
|
+
/** Toggle the branch panel */
|
|
3398
|
+
onBranchPanelToggle?: () => void;
|
|
3399
|
+
/** Whether the learner is in interactive/editing mode */
|
|
3400
|
+
isInteractive?: boolean;
|
|
2824
3401
|
showMarkers?: boolean;
|
|
2825
3402
|
compact?: boolean;
|
|
2826
|
-
containerRef?:
|
|
3403
|
+
containerRef?: React__default__default.RefObject<HTMLElement>;
|
|
2827
3404
|
}
|
|
2828
|
-
declare function PlayerControls({ isPlaying, currentTime, duration, volume, muted, playbackSpeed, markers, isFullscreen, onPlayPause, onSeek, onSeekStart, onSeekEnd, onSkip, onRestart, onVolumeChange, onMuteToggle, onSpeedChange, onFullscreenToggle, showMarkers, compact, }: PlayerControlsProps): react_jsx_runtime.JSX.Element;
|
|
3405
|
+
declare function PlayerControls({ isPlaying, currentTime, duration, volume, muted, playbackSpeed, markers, isFullscreen, videoQualityLevels, videoQualityLevel, onVideoQualityChange, onPlayPause, onSeek, onSeekStart, onSeekEnd, onSkip, onRestart, onVolumeChange, onMuteToggle, onSpeedChange, onFullscreenToggle, onEditorInteraction, interactionPoints, branches, onBranchClick, branchCount, isBranchPanelOpen, onBranchPanelToggle, isInteractive, showMarkers, compact, }: PlayerControlsProps): react_jsx_runtime.JSX.Element;
|
|
2829
3406
|
|
|
2830
3407
|
/**
|
|
2831
3408
|
* Timeline Component
|
|
@@ -2842,7 +3419,7 @@ interface Marker {
|
|
|
2842
3419
|
id: string;
|
|
2843
3420
|
time: number;
|
|
2844
3421
|
label: string;
|
|
2845
|
-
type: 'chapter' | '
|
|
3422
|
+
type: 'chapter' | 'bookmark' | 'quiz' | 'note' | 'error';
|
|
2846
3423
|
description?: string;
|
|
2847
3424
|
}
|
|
2848
3425
|
/**
|
|
@@ -2897,6 +3474,128 @@ interface TimelineProps {
|
|
|
2897
3474
|
*/
|
|
2898
3475
|
declare function Timeline({ currentTime, duration, markers, chunks, buffered, onSeek, onMarkerClick, theme, showChapterLabels, showBufferStatus, showChunkIndicators, compact, }: TimelineProps): JSX.Element;
|
|
2899
3476
|
|
|
3477
|
+
/**
|
|
3478
|
+
* MCQOverlay — full-area overlay that renders a multiple-choice question
|
|
3479
|
+
* on top of the player content.
|
|
3480
|
+
*
|
|
3481
|
+
* Phases: Question → Loading → Feedback (with optional retry).
|
|
3482
|
+
* Handles timeout countdown, focus trapping, and keyboard navigation.
|
|
3483
|
+
*
|
|
3484
|
+
* @packageDocumentation
|
|
3485
|
+
*/
|
|
3486
|
+
|
|
3487
|
+
interface MCQOverlayProps {
|
|
3488
|
+
/** The interaction point to display */
|
|
3489
|
+
point: InteractionPoint;
|
|
3490
|
+
/** Called when the learner submits an answer. Returns result from host app. */
|
|
3491
|
+
onSubmit: (selectedOptionIds: string[]) => Promise<MCQResult>;
|
|
3492
|
+
/** Called when the learner is done (correct answer, or gave up) */
|
|
3493
|
+
onDismiss: () => void;
|
|
3494
|
+
/** Optional extra class name for the outer container */
|
|
3495
|
+
className?: string;
|
|
3496
|
+
}
|
|
3497
|
+
declare const MCQOverlay: React__default__default.FC<MCQOverlayProps>;
|
|
3498
|
+
|
|
3499
|
+
/**
|
|
3500
|
+
* BranchTransition — end-of-lesson overlay with auto-advance countdown.
|
|
3501
|
+
*
|
|
3502
|
+
* Shows "Next: [title]" with countdown + skip/cancel, or a "Course Complete"
|
|
3503
|
+
* message when there's no next lesson.
|
|
3504
|
+
*
|
|
3505
|
+
* @packageDocumentation
|
|
3506
|
+
*/
|
|
3507
|
+
|
|
3508
|
+
interface BranchTransitionProps {
|
|
3509
|
+
/** Title of the next lesson */
|
|
3510
|
+
nextLessonTitle: string;
|
|
3511
|
+
/** Countdown seconds remaining */
|
|
3512
|
+
countdown: number;
|
|
3513
|
+
/** Skip countdown and navigate immediately */
|
|
3514
|
+
onSkip: () => void;
|
|
3515
|
+
/** Stop auto-advance (stay on current lesson) */
|
|
3516
|
+
onCancel: () => void;
|
|
3517
|
+
/** If true, show "Course Complete" instead of next lesson */
|
|
3518
|
+
isComplete?: boolean;
|
|
3519
|
+
}
|
|
3520
|
+
declare const BranchTransition: React__default__default.FC<BranchTransitionProps>;
|
|
3521
|
+
|
|
3522
|
+
/**
|
|
3523
|
+
* SaveBranchButton — floating pill button shown in the top-right of the IDE
|
|
3524
|
+
* panel when the learner is in interactive mode and has made code changes.
|
|
3525
|
+
*
|
|
3526
|
+
* @packageDocumentation
|
|
3527
|
+
*/
|
|
3528
|
+
|
|
3529
|
+
interface SaveBranchButtonProps {
|
|
3530
|
+
/** Whether the button should be visible */
|
|
3531
|
+
visible: boolean;
|
|
3532
|
+
/** Called when the learner clicks "Save Branch" */
|
|
3533
|
+
onSave: () => void;
|
|
3534
|
+
/** Whether the max branch limit has been reached */
|
|
3535
|
+
limitReached?: boolean;
|
|
3536
|
+
}
|
|
3537
|
+
declare const SaveBranchButton: React__default__default.FC<SaveBranchButtonProps>;
|
|
3538
|
+
|
|
3539
|
+
/**
|
|
3540
|
+
* BranchSavedToast — brief confirmation toast shown after saving a branch.
|
|
3541
|
+
*
|
|
3542
|
+
* Slides up, holds, then fades out automatically.
|
|
3543
|
+
*
|
|
3544
|
+
* @packageDocumentation
|
|
3545
|
+
*/
|
|
3546
|
+
|
|
3547
|
+
interface BranchSavedToastProps {
|
|
3548
|
+
/** Whether to show the toast */
|
|
3549
|
+
visible: boolean;
|
|
3550
|
+
/** Called when the toast fully disappears */
|
|
3551
|
+
onDismiss: () => void;
|
|
3552
|
+
/** Optional message override (defaults to "Branch saved") */
|
|
3553
|
+
message?: string;
|
|
3554
|
+
/** Show as a duplicate/error toast instead of success */
|
|
3555
|
+
variant?: "success" | "duplicate";
|
|
3556
|
+
}
|
|
3557
|
+
declare const BranchSavedToast: React__default__default.FC<BranchSavedToastProps>;
|
|
3558
|
+
|
|
3559
|
+
/**
|
|
3560
|
+
* UnsavedBranchPrompt — tooltip-style popup that appears near the play button
|
|
3561
|
+
* when the learner exits interactive mode with unsaved code changes.
|
|
3562
|
+
*
|
|
3563
|
+
* Offers "Save & Resume" or "Discard & Resume". Auto-dismisses after 5 seconds.
|
|
3564
|
+
*
|
|
3565
|
+
* @packageDocumentation
|
|
3566
|
+
*/
|
|
3567
|
+
|
|
3568
|
+
interface UnsavedBranchPromptProps {
|
|
3569
|
+
/** Whether to show the prompt */
|
|
3570
|
+
visible: boolean;
|
|
3571
|
+
/** Called when the user chooses "Save & Resume" */
|
|
3572
|
+
onSaveAndResume: () => void;
|
|
3573
|
+
/** Called when the user chooses "Discard & Resume" or prompt auto-dismisses */
|
|
3574
|
+
onDiscardAndResume: () => void;
|
|
3575
|
+
}
|
|
3576
|
+
declare const UnsavedBranchPrompt: React__default__default.FC<UnsavedBranchPromptProps>;
|
|
3577
|
+
|
|
3578
|
+
interface BranchPanelProps {
|
|
3579
|
+
/** Whether the panel is visible */
|
|
3580
|
+
visible: boolean;
|
|
3581
|
+
/** All branches for the current lesson */
|
|
3582
|
+
branches: LearnerBranch[];
|
|
3583
|
+
/** Close the panel */
|
|
3584
|
+
onClose: () => void;
|
|
3585
|
+
/** Restore a branch (seek + interactive + inject) */
|
|
3586
|
+
onRestore: (branch: LearnerBranch) => void;
|
|
3587
|
+
/** Delete a branch by id */
|
|
3588
|
+
onDelete: (branchId: string) => void;
|
|
3589
|
+
/** Rename a branch */
|
|
3590
|
+
onRename: (branchId: string, newLabel: string) => void;
|
|
3591
|
+
/** Maximum branches per lesson (for limit warning) */
|
|
3592
|
+
maxBranches?: number;
|
|
3593
|
+
/** Ref to the anchor element for fixed positioning */
|
|
3594
|
+
anchorRef?: React__default__default.RefObject<HTMLDivElement>;
|
|
3595
|
+
}
|
|
3596
|
+
declare function BranchPanelInner({ visible, branches, onClose, onRestore, onDelete, onRename, maxBranches, anchorRef, }: BranchPanelProps): react_jsx_runtime.JSX.Element | null;
|
|
3597
|
+
declare const BranchPanel: React__default__default.MemoExoticComponent<typeof BranchPanelInner>;
|
|
3598
|
+
|
|
2900
3599
|
/**
|
|
2901
3600
|
* AudioOverlay Component
|
|
2902
3601
|
*
|
|
@@ -2908,11 +3607,11 @@ declare function Timeline({ currentTime, duration, markers, chunks, buffered, on
|
|
|
2908
3607
|
/**
|
|
2909
3608
|
* Overlay position presets
|
|
2910
3609
|
*/
|
|
2911
|
-
type OverlayPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'custom';
|
|
3610
|
+
type OverlayPosition$1 = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'custom';
|
|
2912
3611
|
/**
|
|
2913
3612
|
* Custom position
|
|
2914
3613
|
*/
|
|
2915
|
-
interface CustomPosition {
|
|
3614
|
+
interface CustomPosition$1 {
|
|
2916
3615
|
x: number;
|
|
2917
3616
|
y: number;
|
|
2918
3617
|
}
|
|
@@ -2929,9 +3628,9 @@ interface AudioOverlayProps {
|
|
|
2929
3628
|
/** Playback rate */
|
|
2930
3629
|
playbackRate?: number;
|
|
2931
3630
|
/** Overlay position preset */
|
|
2932
|
-
position?: OverlayPosition;
|
|
3631
|
+
position?: OverlayPosition$1;
|
|
2933
3632
|
/** Custom position (when position='custom') */
|
|
2934
|
-
customPosition?: CustomPosition;
|
|
3633
|
+
customPosition?: CustomPosition$1;
|
|
2935
3634
|
/** Whether to show the overlay */
|
|
2936
3635
|
visible?: boolean;
|
|
2937
3636
|
/** Enable dragging */
|
|
@@ -2941,7 +3640,7 @@ interface AudioOverlayProps {
|
|
|
2941
3640
|
/** Opacity (0-1) */
|
|
2942
3641
|
opacity?: number;
|
|
2943
3642
|
/** On position change callback */
|
|
2944
|
-
onPositionChange?: (position: CustomPosition) => void;
|
|
3643
|
+
onPositionChange?: (position: CustomPosition$1) => void;
|
|
2945
3644
|
/** Callback to pass audio element reference for sync */
|
|
2946
3645
|
onAudioRef?: (audio: HTMLAudioElement | null) => void;
|
|
2947
3646
|
/** Whether audio is muted */
|
|
@@ -2960,4 +3659,55 @@ interface AudioOverlayProps {
|
|
|
2960
3659
|
*/
|
|
2961
3660
|
declare function AudioOverlay({ src, currentTime: _currentTime, isPlaying: _isPlaying, playbackRate: _playbackRate, position, customPosition, visible, draggable, showControls, opacity, onPositionChange, onAudioRef, muted: _muted, volume: _volume, syncTolerance: _syncTolerance, }: AudioOverlayProps): JSX.Element | null;
|
|
2962
3661
|
|
|
2963
|
-
|
|
3662
|
+
/**
|
|
3663
|
+
* WebcamOverlay Component v3
|
|
3664
|
+
*
|
|
3665
|
+
* Clean webcam video overlay with:
|
|
3666
|
+
* - Draggable circular bubble
|
|
3667
|
+
* - Maximize on hover click
|
|
3668
|
+
* - Smooth animations
|
|
3669
|
+
*
|
|
3670
|
+
* @packageDocumentation
|
|
3671
|
+
*/
|
|
3672
|
+
type OverlayPosition = "top-right" | "top-left" | "bottom-right" | "bottom-left" | "custom";
|
|
3673
|
+
type OverlaySize = "small" | "medium" | "large" | "custom";
|
|
3674
|
+
interface CustomPosition {
|
|
3675
|
+
x: number;
|
|
3676
|
+
y: number;
|
|
3677
|
+
}
|
|
3678
|
+
interface CustomSize {
|
|
3679
|
+
width: number;
|
|
3680
|
+
height: number;
|
|
3681
|
+
}
|
|
3682
|
+
interface WebcamOverlayProps {
|
|
3683
|
+
src: string | null;
|
|
3684
|
+
currentTime: number;
|
|
3685
|
+
isPlaying: boolean;
|
|
3686
|
+
playbackRate?: number;
|
|
3687
|
+
position?: OverlayPosition;
|
|
3688
|
+
customPosition?: CustomPosition;
|
|
3689
|
+
size?: OverlaySize;
|
|
3690
|
+
customSize?: CustomSize;
|
|
3691
|
+
visible?: boolean;
|
|
3692
|
+
draggable?: boolean;
|
|
3693
|
+
resizable?: boolean;
|
|
3694
|
+
showControls?: boolean;
|
|
3695
|
+
borderRadius?: number | "circle";
|
|
3696
|
+
opacity?: number;
|
|
3697
|
+
onPositionChange?: (position: CustomPosition) => void;
|
|
3698
|
+
onSizeChange?: (size: CustomSize) => void;
|
|
3699
|
+
onVisibilityToggle?: () => void;
|
|
3700
|
+
onVideoRef?: (video: HTMLVideoElement | null) => void;
|
|
3701
|
+
muted?: boolean;
|
|
3702
|
+
volume?: number;
|
|
3703
|
+
syncTolerance?: number;
|
|
3704
|
+
/** Whether webcam is in maximized (full overlay) mode - from playback events */
|
|
3705
|
+
maximized?: boolean;
|
|
3706
|
+
/** Callback when user clicks minimize button */
|
|
3707
|
+
onMinimize?: () => void;
|
|
3708
|
+
/** Callback when user clicks maximize button */
|
|
3709
|
+
onMaximize?: () => void;
|
|
3710
|
+
}
|
|
3711
|
+
declare function WebcamOverlay({ src, currentTime: _currentTime, isPlaying: _isPlaying, playbackRate: _playbackRate, position, customPosition, size, customSize, visible, draggable, resizable: _resizable, showControls: _showControls, borderRadius, opacity, onPositionChange, onSizeChange: _onSizeChange, onVisibilityToggle: _onVisibilityToggle, onVideoRef, muted: _muted, volume: _volume, syncTolerance: _syncTolerance, maximized, onMinimize, onMaximize, }: WebcamOverlayProps): JSX.Element | null;
|
|
3712
|
+
|
|
3713
|
+
export { AudioOverlay, type AudioOverlayProps, type AudioQuality, type AudioSyncControls, type AudioSyncState, type BackendAdapter, BranchPanel, type BranchPanelProps, BranchSavedToast, type BranchSavedToastProps, type BranchSnapshot, BranchTransition, type BranchTransitionProps, type BufferHealth, type CTEvent, type CTManifest, type CTMarker, type CTReadOptions, type CTRecording, CoursePlayer, type CoursePlayerProps, type CoursePlayerRef, type CursorPosition, type CustomPosition$1 as CustomPosition, DocumentPanel, type DocumentPanelProps, FileExplorer, type FileExplorerProps, type FileSystemSnapshot, type HLSPlayerInstance, HLS_EVENTS, IDEPanel, type IDEPanelProps, type InteractionPoint, type InternalEvent, type InternalRecording, type LearnerBranch, MCQOverlay, type MCQOverlayProps, type MCQResult, type MCQSubmission, type OverlayPosition$1 as OverlayPosition, type PanelMode, type PlaybackControls$1 as PlaybackControls, type PlaybackEngineConfig, type PlaybackHookState, type PlaybackState, PlayerControls, type PlayerControlsProps$1 as PlayerControlsProps, type PlayerProps, type PlayerRef, type RecordingMarker, type RemoteBufferHealth, type RemoteStreamingMetrics, type RemoteStreamingPlaybackControls, type RemoteStreamingPlaybackState, SaveBranchButton, type SaveBranchButtonProps, type SpeedSelectorProps, type StreamingAudioConfig, type StreamingConfig, StreamingCoursePlayer, type StreamingCoursePlayerProps, type StreamingCoursePlayerRef, type StreamingEventsConfig, type StreamingManifest, type StreamingMetrics, type StreamingPlaybackControls, type StreamingPlaybackState, type StreamingRecordingInfo, Terminal, type TerminalLineData, type TerminalProps, Timeline, type TimelineProps$1 as TimelineProps, ToolSidebar, type ToolSidebarProps, type ToolType, UnsavedBranchPrompt, type UnsavedBranchPromptProps, type UseAudioSyncOptions, type UseBranchesOptions, type UseBranchesResult, type UseBranchingOptions, type UseBranchingResult, type UseInteractionPointsOptions, type UseInteractionPointsResult, type UsePlaybackEngineResult, type UsePlaybackOptions, type UseRemoteStreamingPlaybackOptions, type UseVideoSyncOptions, type ValidationResult$1 as ValidationResult, type VideoSyncControls, type VideoSyncState, type VolumeControlProps, WebcamOverlay, type WebcamOverlayProps, WhiteboardPanel, type WhiteboardPanelProps, type WriteCTOptions, canPlayHls, createEmptyRecording, createHlsPlayer, deleteBranch as deleteBranchFromStorage, destroyHlsPlayer, formatBranchTime, hasNativeHlsSupport, isHlsSupported, loadBranches, readCTFile, readCTManifest, saveBranch as saveBranchToStorage, updateBranchLabel, useAudioElement, useAudioSync, useBranches, useBranching, useInteractionPoints, useInteractiveMode, usePlayback, usePlayback as usePlaybackEngine, useRemoteStreamingPlayback, useStreamingPlayback, useVideoElement, useVideoSync, validateCTFile, writeCTFile };
|