interview-widget 1.0.8 → 1.0.10

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.
Files changed (36) hide show
  1. package/dist/assets/bolt-icon.d.ts +1 -0
  2. package/dist/assets/camera-off-icon.d.ts +1 -0
  3. package/dist/assets/index.d.ts +4 -0
  4. package/dist/assets/info-icon.d.ts +1 -0
  5. package/dist/assets/scan-face-icon.d.ts +1 -0
  6. package/dist/assets/target-icon.d.ts +1 -0
  7. package/dist/assets/users-icon.d.ts +1 -0
  8. package/dist/components/interview/interview-content.d.ts +4 -0
  9. package/dist/components/interview/interview-controller.d.ts +2 -0
  10. package/dist/components/interview/proctoring/face-data-permission-modal.d.ts +7 -0
  11. package/dist/components/interview/proctoring/gaze-detection/components/gaze-controls.d.ts +15 -0
  12. package/dist/components/interview/proctoring/gaze-detection/components/video-controls.d.ts +21 -0
  13. package/dist/components/interview/proctoring/gaze-detection/config/gaze-modal-config.d.ts +10 -0
  14. package/dist/components/interview/proctoring/gaze-detection/hooks/index.d.ts +9 -0
  15. package/dist/components/interview/proctoring/gaze-detection/hooks/use-camera-setup.d.ts +3 -0
  16. package/dist/components/interview/proctoring/gaze-detection/hooks/use-canvas-drawing.d.ts +11 -0
  17. package/dist/components/interview/proctoring/gaze-detection/hooks/use-face-analysis.d.ts +8 -0
  18. package/dist/components/interview/proctoring/gaze-detection/hooks/use-fps-counter.d.ts +4 -0
  19. package/dist/components/interview/proctoring/gaze-detection/hooks/use-gaze-analysis.d.ts +11 -0
  20. package/dist/components/interview/proctoring/gaze-detection/hooks/use-model-loader.d.ts +10 -0
  21. package/dist/components/interview/proctoring/gaze-detection/hooks/use-reference-manager.d.ts +11 -0
  22. package/dist/components/interview/proctoring/gaze-detection/hooks/use-render-loop.d.ts +5 -0
  23. package/dist/components/interview/proctoring/gaze-detection/hooks/use-warning-manager.d.ts +10 -0
  24. package/dist/components/interview/proctoring/gaze-detection/utils/types.d.ts +54 -0
  25. package/dist/components/media/video-feed.d.ts +6 -2
  26. package/dist/components/modals/gaze-warning-modal.d.ts +8 -0
  27. package/dist/components/modals/onboarding-modal.d.ts +4 -0
  28. package/dist/context/proctoring-context.d.ts +27 -0
  29. package/dist/services/api/interview-api.d.ts +9 -1
  30. package/dist/services/stt/stt-service.d.ts +4 -0
  31. package/dist/types.d.ts +15 -0
  32. package/dist/utils/constants.d.ts +1 -0
  33. package/dist/widget.css +1 -1
  34. package/dist/widget.es.js +6663 -1791
  35. package/dist/widget.umd.js +19 -5
  36. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ export declare const BoltIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const CameraOffIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -10,3 +10,7 @@ export * from './monitor-icon';
10
10
  export * from './mouse-pointer-click-icon';
11
11
  export * from './shield-icon';
12
12
  export * from './speak-icon';
13
+ export * from './bolt-icon';
14
+ export * from './camera-off-icon';
15
+ export * from './target-icon';
16
+ export * from './users-icon';
@@ -0,0 +1 @@
1
+ export declare const InfoIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const ScanFaceIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const TargetIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export declare const UsersIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
@@ -1,11 +1,15 @@
1
1
  import { default as React, ReactNode } from 'react';
2
2
  import { TimerPhase } from '../../services/timer/timer-service';
3
3
  import { InterviewQuestionData } from '../../types';
4
+ import { VideoFeedHandle } from '../media/video-feed';
4
5
  interface InterviewContentProps {
5
6
  currentQuestion: InterviewQuestionData | null;
6
7
  phase: TimerPhase;
7
8
  className?: string;
8
9
  children: ReactNode;
10
+ interviewId?: string;
11
+ interview_duration?: number | undefined;
12
+ videoFeedRef?: React.Ref<VideoFeedHandle> | undefined;
9
13
  }
10
14
  export declare const InterviewContent: React.FC<InterviewContentProps>;
11
15
  export {};
@@ -1,10 +1,12 @@
1
1
  import { default as React } from 'react';
2
+ import { VideoFeedHandle } from '../media/video-feed';
2
3
  interface InterviewControllerProps {
3
4
  interviewTitle: string;
4
5
  interviewId: string;
5
6
  onComplete?: (() => void) | undefined;
6
7
  onDisqualify?: (() => void) | undefined;
7
8
  className?: string;
9
+ videoFeedRef?: React.Ref<VideoFeedHandle>;
8
10
  }
9
11
  declare const InterviewController: React.FC<InterviewControllerProps>;
10
12
  export default InterviewController;
@@ -0,0 +1,7 @@
1
+ interface FaceDataPermissionModalProps {
2
+ isOpen: boolean;
3
+ onDecline: () => void;
4
+ onContinue: () => void;
5
+ }
6
+ export declare function FaceDataPermissionModal({ isOpen, onDecline, onContinue, }: FaceDataPermissionModalProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,15 @@
1
+ interface Props {
2
+ gazeAnalysisEnabled: boolean;
3
+ isModelLoaded: boolean;
4
+ stats: {
5
+ fps: number;
6
+ engagement: number;
7
+ isLookingAway: boolean;
8
+ multipleFacesDetected: boolean;
9
+ referenceFaceNotDetected: boolean;
10
+ };
11
+ statusMessage: string;
12
+ loadingProgress: number;
13
+ }
14
+ export declare const GazeControls: ({ gazeAnalysisEnabled, isModelLoaded, stats, statusMessage, loadingProgress, }: Props) => import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,21 @@
1
+ import { Stats } from '../utils/types';
2
+ interface VideoControlsProps {
3
+ showControls: boolean;
4
+ isBubbleOpen: boolean;
5
+ setIsBubbleOpen: (open: boolean) => void;
6
+ setReference: () => void;
7
+ clearCache: () => void;
8
+ isModelLoaded: boolean;
9
+ gazeAnalysisEnabled: boolean;
10
+ referenceSet: boolean;
11
+ showLandmarks: boolean;
12
+ setShowLandmarks: (show: boolean) => void;
13
+ showEngagementBar: boolean;
14
+ setShowEngagementBar: (show: boolean) => void;
15
+ handleToggleGazeAnalysis: (enabled: boolean) => void;
16
+ stats: Stats;
17
+ statusMessage: string;
18
+ loadingProgress: number;
19
+ }
20
+ export declare const VideoControls: React.FC<VideoControlsProps>;
21
+ export {};
@@ -0,0 +1,10 @@
1
+ import { GazeWarningConfig } from '../utils/types';
2
+ export declare const GazeWarningType: {
3
+ readonly FACE_DETECTED: "face_detected";
4
+ readonly NO_FACE: "no_face_detected";
5
+ readonly MULTIPLE_FACES: "multiple_faces";
6
+ readonly LOOKING_AWAY: "looking_away";
7
+ readonly CAMERA_ERROR: "camera_error";
8
+ };
9
+ export type GazeWarningTypeValue = (typeof GazeWarningType)[keyof typeof GazeWarningType];
10
+ export declare const warningConfigs: Record<GazeWarningTypeValue, GazeWarningConfig>;
@@ -0,0 +1,9 @@
1
+ export { useModelLoader } from './use-model-loader';
2
+ export { useFpsCounter } from './use-fps-counter';
3
+ export { useCanvasDrawing } from './use-canvas-drawing';
4
+ export { useGazeAnalysis } from './use-gaze-analysis';
5
+ export { useFaceAnalysis } from './use-face-analysis';
6
+ export { useWarningManager } from './use-warning-manager';
7
+ export { useCameraSetup } from './use-camera-setup';
8
+ export { useRenderLoop } from './use-render-loop';
9
+ export { useReferenceManager } from './use-reference-manager';
@@ -0,0 +1,3 @@
1
+ export declare const useCameraSetup: (videoRef: React.RefObject<HTMLVideoElement | null>, isModelLoaded: boolean, renderLoop: () => void, setStatusMessage: (message: string) => void) => {
2
+ animationFrameRef: import('react').RefObject<number | null>;
3
+ };
@@ -0,0 +1,11 @@
1
+ import { Landmark } from '../utils/types';
2
+ export declare const useCanvasDrawing: () => {
3
+ drawLandmarks: (canvas: HTMLCanvasElement, video: HTMLVideoElement, landmarks: Landmark[], showLandmarks: boolean) => void;
4
+ drawEngagementBar: (ctx: CanvasRenderingContext2D) => void;
5
+ drawWithEngagementBar: (canvas: HTMLCanvasElement, video: HTMLVideoElement, landmarks: Landmark[], showLandmarks: boolean, showEngagementBar: boolean, gazeAnalysisEnabled: boolean, referenceSet: boolean) => void;
6
+ clearCanvas: (canvas: HTMLCanvasElement, video: HTMLVideoElement) => void;
7
+ engagementRef: import('react').RefObject<{
8
+ value: number;
9
+ isLookingAway: boolean;
10
+ }>;
11
+ };
@@ -0,0 +1,8 @@
1
+ import { Landmark, FaceDetectionResult } from '../utils/types';
2
+ export declare const useFaceAnalysis: () => {
3
+ multipleFacesDetected: boolean;
4
+ referenceFaceNotDetected: boolean;
5
+ analyzeFace: (results: FaceDetectionResult, referenceSet: boolean, referenceRef: Landmark[], setStatusMessage: (message: string) => void) => Landmark[] | null;
6
+ setMultipleFacesDetected: import('react').Dispatch<import('react').SetStateAction<boolean>>;
7
+ setReferenceFaceNotDetected: import('react').Dispatch<import('react').SetStateAction<boolean>>;
8
+ };
@@ -0,0 +1,4 @@
1
+ export declare const useFpsCounter: () => {
2
+ fps: number;
3
+ updateFPS: () => void;
4
+ };
@@ -0,0 +1,11 @@
1
+ import { Landmark, ReferenceData } from '../utils/types';
2
+ export declare const useGazeAnalysis: () => {
3
+ engagement: number;
4
+ isLookingAway: boolean;
5
+ analyzeGaze: (landmarks: Landmark[], reference: ReferenceData, gazeAnalysisEnabled: boolean) => {
6
+ engagement: number;
7
+ isLookingAway: boolean;
8
+ } | undefined;
9
+ setEngagement: import('react').Dispatch<import('react').SetStateAction<number>>;
10
+ setIsLookingAway: import('react').Dispatch<import('react').SetStateAction<boolean>>;
11
+ };
@@ -0,0 +1,10 @@
1
+ import { FaceLandmarker } from '@mediapipe/tasks-vision';
2
+ export declare const useModelLoader: () => {
3
+ faceLandmarkerRef: import('react').RefObject<FaceLandmarker | null>;
4
+ isModelLoaded: boolean;
5
+ statusMessage: string;
6
+ setStatusMessage: import('react').Dispatch<import('react').SetStateAction<string>>;
7
+ loadingProgress: number;
8
+ permissionDenied: boolean;
9
+ clearCache: () => Promise<void>;
10
+ };
@@ -0,0 +1,11 @@
1
+ export declare const useReferenceManager: (faceLandmarkerRef: React.RefObject<any>, videoRef: React.RefObject<HTMLVideoElement | null>, setStatusMessage: (message: string) => void, onSetReference?: () => void) => {
2
+ referenceSet: boolean;
3
+ referenceRef: import('react').RefObject<{
4
+ x: number;
5
+ y: number;
6
+ noseX: number;
7
+ noseY: number;
8
+ }>;
9
+ setReference: () => void;
10
+ syncReference: () => void;
11
+ };
@@ -0,0 +1,5 @@
1
+ import { Landmark } from '../utils/types';
2
+ export declare const useRenderLoop: (videoRef: React.RefObject<HTMLVideoElement | null>, canvasRef: React.RefObject<HTMLCanvasElement | null>, faceLandmarkerRef: React.RefObject<any>, updateFPS: () => void, analyzeFace: (results: any, referenceSet: boolean, referenceRef: Landmark[], setStatusMessage: (message: string) => void) => Landmark[] | null, drawWithEngagementBar: (canvas: HTMLCanvasElement, video: HTMLVideoElement, landmarks: Landmark[], showLandmarks: boolean, showEngagementBar: boolean, gazeAnalysisEnabled: boolean, referenceSet: boolean) => void, clearCanvas: (canvas: HTMLCanvasElement, video: HTMLVideoElement) => void, analyzeGaze: (landmarks: Landmark[], reference: any, gazeAnalysisEnabled: boolean) => void, referenceSet: boolean, referenceRef: React.RefObject<any>, showLandmarks: boolean, showEngagementBar: boolean, gazeAnalysisEnabled: boolean, setStatusMessage: (message: string) => void, setReferenceFaceNotDetected: (detected: boolean) => void) => {
3
+ renderLoop: () => void;
4
+ animationFrameRef: import('react').RefObject<number | null>;
5
+ };
@@ -0,0 +1,10 @@
1
+ import { WarningStates } from '../utils/types';
2
+ import { GazeWarningTypeValue } from '../config/gaze-modal-config';
3
+ export declare const useWarningManager: (warningStates: WarningStates, gazeAnalysisEnabled: boolean) => {
4
+ showGazeWarningModal: boolean;
5
+ faceDetectionState: GazeWarningTypeValue;
6
+ getWarningType: () => GazeWarningTypeValue;
7
+ closeWarningModal: () => void;
8
+ setShowGazeWarningModal: import('react').Dispatch<import('react').SetStateAction<boolean>>;
9
+ setFaceDetectionState: import('react').Dispatch<import('react').SetStateAction<GazeWarningTypeValue>>;
10
+ };
@@ -0,0 +1,54 @@
1
+ export interface Landmark {
2
+ x: number;
3
+ y: number;
4
+ z?: number;
5
+ }
6
+ export interface ReferenceData {
7
+ x: number;
8
+ y: number;
9
+ noseX: number;
10
+ noseY: number;
11
+ }
12
+ export interface FaceDetectionResult {
13
+ faceLandmarks: Landmark[][];
14
+ }
15
+ export interface WarningStates {
16
+ multipleFacesDetected: boolean;
17
+ referenceFaceNotDetected: boolean;
18
+ isLookingAway: boolean;
19
+ }
20
+ export interface Stats {
21
+ engagement: number;
22
+ fps: number;
23
+ isLookingAway: boolean;
24
+ multipleFacesDetected: boolean;
25
+ referenceFaceNotDetected: boolean;
26
+ }
27
+ export type GazeViolationType = 'looking_away' | 'no_face_detected' | 'multiple_faces';
28
+ export interface GazeViolationCounters {
29
+ lookingAwayCount: number;
30
+ noFaceDetectedCount: number;
31
+ multipleFacesCount: number;
32
+ totalGazeViolations: number;
33
+ }
34
+ export interface GazeAnalysisState {
35
+ referenceSet: boolean;
36
+ referenceRef: {
37
+ x: number;
38
+ y: number;
39
+ noseX: number;
40
+ noseY: number;
41
+ };
42
+ }
43
+ export interface GazeWarningConfig {
44
+ icon: React.ComponentType<{
45
+ className?: string;
46
+ }>;
47
+ iconColor: string;
48
+ iconBg: string;
49
+ iconBorder: string;
50
+ title: string;
51
+ subtitle: string;
52
+ description: string;
53
+ buttonText: string;
54
+ }
@@ -1,6 +1,10 @@
1
- import { default as React } from 'react';
1
+ export interface VideoFeedHandle {
2
+ setReference: () => void;
3
+ }
2
4
  interface VideoFeedProps {
3
5
  className?: string;
6
+ interviewId?: string;
7
+ interview_duration?: number | undefined;
4
8
  }
5
- declare const VideoFeed: React.FC<VideoFeedProps>;
9
+ declare const VideoFeed: import('react').ForwardRefExoticComponent<VideoFeedProps & import('react').RefAttributes<VideoFeedHandle>>;
6
10
  export default VideoFeed;
@@ -0,0 +1,8 @@
1
+ import { GazeWarningTypeValue } from '../interview/proctoring/gaze-detection/config/gaze-modal-config';
2
+ interface GazeWarningModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ warningType: GazeWarningTypeValue;
6
+ }
7
+ export declare function GazeWarningModal({ isOpen, onClose, warningType, }: GazeWarningModalProps): import("react/jsx-runtime").JSX.Element | null;
8
+ export {};
@@ -1,8 +1,12 @@
1
1
  import { default as React } from 'react';
2
+ import { VideoFeedHandle } from '../media/video-feed';
2
3
  interface PermissionModalProps {
3
4
  isOpen: boolean;
4
5
  onStart: () => void;
6
+ onRequestCalibration?: () => void;
5
7
  onClose?: () => void;
8
+ gazeEnabled?: boolean;
9
+ videoFeedRef?: React.Ref<VideoFeedHandle>;
6
10
  }
7
11
  declare const OnboardingModal: React.FC<PermissionModalProps>;
8
12
  export default OnboardingModal;
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
2
  import { ViolationLogger } from '../types';
3
+ import { GazeViolationCounters, GazeViolationType } from '../components/interview/proctoring/gaze-detection/utils/types';
3
4
  export declare const ProctoringProvider: React.FC<{
4
5
  children: React.ReactNode;
5
6
  }>;
@@ -8,9 +9,35 @@ export declare const useProctoringStore: () => {
8
9
  totalViolations: number;
9
10
  addViolation: (violation: ViolationLogger) => void;
10
11
  clearViolations: () => void;
12
+ gazeViolationCounters: GazeViolationCounters;
13
+ referenceSet: boolean;
14
+ referenceRef: {
15
+ x: number;
16
+ y: number;
17
+ noseX: number;
18
+ noseY: number;
19
+ };
20
+ incrementGazeViolation: (type: GazeViolationType) => void;
21
+ clearGazeViolationCounters: () => void;
22
+ setReferenceData: (referenceSet: boolean, referenceRef: {
23
+ x: number;
24
+ y: number;
25
+ noseX: number;
26
+ noseY: number;
27
+ }) => void;
11
28
  };
12
29
  export declare const useViolations: () => ViolationLogger[];
13
30
  export declare const useTotalViolations: () => number;
31
+ export declare const useGazeViolationCounters: () => GazeViolationCounters;
32
+ export declare const useReferenceData: () => {
33
+ referenceSet: boolean;
34
+ referenceRef: {
35
+ x: number;
36
+ y: number;
37
+ noseX: number;
38
+ noseY: number;
39
+ };
40
+ };
14
41
  export declare const useProctoringActions: () => {
15
42
  addViolation: (violation: ViolationLogger) => void;
16
43
  clearViolations: () => void;
@@ -1,4 +1,4 @@
1
- import { InterviewQuestionPayload, InterviewQuestionResponse, InterviewWidgetConfig } from '../../types';
1
+ import { InterviewQuestionPayload, InterviewQuestionResponse, InterviewWidgetConfig, ScreenshotUploadRequestResponse } from '../../types';
2
2
  declare class InterviewAPI {
3
3
  private config;
4
4
  constructor(config?: InterviewWidgetConfig["api"]);
@@ -18,6 +18,14 @@ declare class InterviewAPI {
18
18
  * Get questions for an interview
19
19
  */
20
20
  generateQuestion({ interviewId, isInterviewDone, qnaId, question, answer, answerDuration, }: InterviewQuestionPayload): Promise<InterviewQuestionResponse>;
21
+ /**
22
+ * Request a signed URL for uploading a screenshot
23
+ */
24
+ requestScreenshotUploadUrl(interviewId: string, filename?: string): Promise<ScreenshotUploadRequestResponse>;
25
+ /**
26
+ * Upload screenshot to the provided signed URL
27
+ */
28
+ uploadScreenshot(uploadUrl: string, imageBlob: Blob): Promise<void>;
21
29
  }
22
30
  export declare const interviewAPI: InterviewAPI;
23
31
  export { InterviewAPI };
@@ -71,6 +71,10 @@ declare class STTService {
71
71
  * Get supported MIME type for recording
72
72
  */
73
73
  private getSupportedMimeType;
74
+ /**
75
+ * Get the current recording stream
76
+ */
77
+ getRecordingStream(): MediaStream | null;
74
78
  /**
75
79
  * Clean up recording resources
76
80
  */
package/dist/types.d.ts CHANGED
@@ -6,6 +6,7 @@ export interface InterviewQuestionData {
6
6
  audio_length_in_milliseconds: number;
7
7
  estimated_answering_duration: string;
8
8
  is_interview_done: boolean;
9
+ interview_duration?: number;
9
10
  }
10
11
  export interface InterviewQuestionPayload {
11
12
  interviewId: string;
@@ -59,6 +60,10 @@ export interface InterviewWidgetConfig {
59
60
  };
60
61
  proctoring?: {
61
62
  enabled?: boolean;
63
+ gazeAnalysisEnabled?: boolean;
64
+ showLandmarks?: boolean;
65
+ showEngagementBar?: boolean;
66
+ showControls?: boolean;
62
67
  };
63
68
  };
64
69
  }
@@ -89,3 +94,13 @@ export interface ViolationLogger extends Violation {
89
94
  timestamp: number;
90
95
  }
91
96
  export type ViolationType = "tab_switch" | "fullscreen_exit" | "focus_loss" | "blocked_shortcut" | "right_click_attempt" | "alt_tab_attempt" | "blocked_function_key";
97
+ export interface ScreenshotUploadRequestResponse {
98
+ success: boolean;
99
+ message: string;
100
+ data: {
101
+ upload_url: string;
102
+ file_path: string;
103
+ };
104
+ error?: string | null;
105
+ code?: number;
106
+ }
@@ -7,3 +7,4 @@ export declare const STORAGE_KEY = "iw-storage";
7
7
  */
8
8
  export declare function getEncryptionSeed(): string;
9
9
  export declare const ENCRYPTION_SEED: string;
10
+ export declare const INTERVIEW_TOTAL_DURATION_MIN = 5;