interview-widget 3.2.22 → 3.2.24-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/dist/assets/index.d.ts +5 -1
- package/dist/assets/net-cross-icon.d.ts +1 -0
- package/dist/assets/wifi-icon.d.ts +1 -0
- package/dist/assets/wifi-low-icon.d.ts +1 -0
- package/dist/assets/wifi-off-icon.d.ts +1 -0
- package/dist/components/interview/proctoring/gaze-detection/hooks/use-camera-setup.d.ts +1 -0
- package/dist/components/interview/proctoring/gaze-detection/hooks/use-gaze-analysis.d.ts +1 -1
- package/dist/components/interview/proctoring/gaze-detection/hooks/use-render-loop.d.ts +1 -1
- package/dist/components/media/video-feed.d.ts +2 -0
- package/dist/components/network/network-quality-bar.d.ts +6 -0
- package/dist/components/network/network-quality-config.d.ts +21 -0
- package/dist/components/network/network-warning-modal.d.ts +12 -0
- package/dist/context/proctoring-context.d.ts +13 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-network-quality.d.ts +10 -0
- package/dist/hooks/use-video-recording.d.ts +6 -0
- package/dist/services/api/endpoints.d.ts +1 -0
- package/dist/services/api/interview-api.d.ts +15 -7
- package/dist/types.d.ts +12 -0
- package/dist/utils/safari-audio-utils.d.ts +49 -0
- package/dist/{widget.3.2.22.css → widget.3.2.24-beta.0.css} +1 -1
- package/dist/{widget.es.3.2.22.js → widget.es.3.2.24-beta.0.js} +3421 -2950
- package/dist/widget.umd.3.2.24-beta.0.js +179 -0
- package/package.json +9 -9
- package/dist/widget.umd.3.2.22.js +0 -179
package/README.md
CHANGED
|
@@ -208,14 +208,15 @@ Pass this object to `InterviewWidgetProvider` via the `config` prop. Tables list
|
|
|
208
208
|
|
|
209
209
|
### Interview
|
|
210
210
|
|
|
211
|
-
| Prop | Type | Default
|
|
212
|
-
| -------------------- | --------- |
|
|
213
|
-
| allow_answer_editing | `boolean` | true
|
|
214
|
-
| capture_screenshots | `boolean` | false
|
|
215
|
-
|
|
|
216
|
-
|
|
|
217
|
-
|
|
|
218
|
-
|
|
|
211
|
+
| Prop | Type | Default | Description |
|
|
212
|
+
| -------------------- | --------- | -------------------------------- | ------------------------------------------- |
|
|
213
|
+
| allow_answer_editing | `boolean` | true | Enable/disable answer editing phase |
|
|
214
|
+
| capture_screenshots | `boolean` | false | Enable/disable periodic screenshot captures |
|
|
215
|
+
| record_video | `boolean` | false | Enable/disable video recording |
|
|
216
|
+
| timers | `object` | [see below](#timers) | Per-phase and global timing configuration |
|
|
217
|
+
| stt | `object` | [see below](#stt-speech-to-text) | Speech-to-Text provider settings |
|
|
218
|
+
| tts | `object` | [see below](#tts-text-to-speech) | Text-to-Speech provider settings |
|
|
219
|
+
| proctoring | `object` | [see below](#proctoring) | Proctoring settings and cheating detection |
|
|
219
220
|
|
|
220
221
|
#### Timers
|
|
221
222
|
|
package/dist/assets/index.d.ts
CHANGED
|
@@ -17,11 +17,15 @@ export * from './mic-icon';
|
|
|
17
17
|
export * from './mic-off-icon';
|
|
18
18
|
export * from './monitor-icon';
|
|
19
19
|
export * from './mouse-pointer-click-icon';
|
|
20
|
+
export * from './net-cross-icon';
|
|
20
21
|
export * from './shield-icon';
|
|
21
22
|
export * from './speak-icon';
|
|
23
|
+
export * from './speech-icon';
|
|
22
24
|
export * from './target-icon';
|
|
23
25
|
export * from './users-icon';
|
|
24
26
|
export * from './video-icon';
|
|
25
27
|
export * from './video-off-icon';
|
|
26
28
|
export * from './volumn-icon';
|
|
27
|
-
export * from './
|
|
29
|
+
export * from './wifi-icon';
|
|
30
|
+
export * from './wifi-low-icon';
|
|
31
|
+
export * from './wifi-off-icon';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const NetCrossIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WifiIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WifiLowIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WifiOffIcon: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const useCameraSetup: (videoRef: React.RefObject<HTMLVideoElement | null>, isModelLoaded: boolean, renderLoop: () => void, setStatusMessage: (message: string) => void) => {
|
|
2
2
|
animationFrameRef: import('react').RefObject<number | null>;
|
|
3
|
+
stream: MediaStream | null;
|
|
3
4
|
};
|
|
@@ -2,7 +2,7 @@ import { Landmark, ReferenceData } from '../utils/types';
|
|
|
2
2
|
export declare const useGazeAnalysis: () => {
|
|
3
3
|
engagement: number;
|
|
4
4
|
isLookingAway: boolean;
|
|
5
|
-
analyzeGaze: (landmarks: Landmark[], reference: ReferenceData, gazeAnalysisEnabled: boolean) => {
|
|
5
|
+
analyzeGaze: (landmarks: Landmark[] | null, reference: ReferenceData, gazeAnalysisEnabled: boolean) => {
|
|
6
6
|
engagement: number;
|
|
7
7
|
isLookingAway: boolean;
|
|
8
8
|
} | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
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) => {
|
|
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[] | null, 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
3
|
renderLoop: () => void;
|
|
4
4
|
animationFrameRef: import('react').RefObject<number | null>;
|
|
5
5
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NetworkQualityLevel } from './network-quality-config';
|
|
2
|
+
interface NetworkQualityBarProps {
|
|
3
|
+
quality: NetworkQualityLevel;
|
|
4
|
+
}
|
|
5
|
+
export declare function NetworkQualityBar({ quality }: NetworkQualityBarProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export type NetworkQualityLevel = "good" | "fair" | "poor" | "disconnected";
|
|
3
|
+
export interface NetworkQualityConfig {
|
|
4
|
+
/** Tailwind bar fill color class */
|
|
5
|
+
barColor: string;
|
|
6
|
+
/** Number of lit bars out of 3 */
|
|
7
|
+
activeBars: number;
|
|
8
|
+
/** Short label for tooltip */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Whether to trigger the warning modal */
|
|
11
|
+
showModal: boolean;
|
|
12
|
+
/** Icon component for the warning modal */
|
|
13
|
+
modalIcon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
|
|
14
|
+
modalIconColor: string;
|
|
15
|
+
modalIconBg: string;
|
|
16
|
+
modalIconBorder: string;
|
|
17
|
+
modalTitle: string;
|
|
18
|
+
modalSubtitle: string;
|
|
19
|
+
modalDescription?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const networkQualityConfigs: Record<NetworkQualityLevel, NetworkQualityConfig>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NetworkQualityLevel } from './network-quality-config';
|
|
2
|
+
interface NetworkWarningModalProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
quality: NetworkQualityLevel;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Shown when network quality drops to "poor" or "disconnected".
|
|
9
|
+
* Styled identically to GazeWarningModal.
|
|
10
|
+
*/
|
|
11
|
+
export declare function NetworkWarningModal({ isOpen, quality, onClose, }: NetworkWarningModalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
12
|
+
export {};
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { ViolationLogger } from '../types';
|
|
3
3
|
import { GazeViolationCounters, GazeViolationType } from '../components/interview/proctoring/gaze-detection/utils/types';
|
|
4
|
+
export type ProctoringState = {
|
|
5
|
+
logViolations: ViolationLogger[];
|
|
6
|
+
totalViolations: number;
|
|
7
|
+
gazeViolationCounters: GazeViolationCounters;
|
|
8
|
+
referenceSet: boolean;
|
|
9
|
+
referenceRef: {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
noseX: number;
|
|
13
|
+
noseY: number;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
4
16
|
export declare const ProctoringProvider: React.FC<{
|
|
5
17
|
children: React.ReactNode;
|
|
18
|
+
interviewId?: string;
|
|
6
19
|
}>;
|
|
7
20
|
export declare const useProctoringStore: () => {
|
|
8
21
|
logViolations: ViolationLogger[];
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './use-dialog';
|
|
|
3
3
|
export * from './use-full-screen';
|
|
4
4
|
export * from './use-interview-api';
|
|
5
5
|
export * from './use-keyboard-prevention';
|
|
6
|
+
export * from './use-network-quality';
|
|
6
7
|
export * from './use-stt';
|
|
7
8
|
export * from './use-tab-switch';
|
|
8
9
|
export * from './use-text-selection-prevention';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type NetworkQualityLevel = "good" | "fair" | "poor" | "disconnected";
|
|
2
|
+
export interface NetworkQualityState {
|
|
3
|
+
quality: NetworkQualityLevel;
|
|
4
|
+
isOnline: boolean;
|
|
5
|
+
effectiveType?: string | undefined;
|
|
6
|
+
rtt?: number | undefined;
|
|
7
|
+
downlink?: number | undefined;
|
|
8
|
+
isInitialising: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function useNetworkQuality(): NetworkQualityState;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InterviewConfigResponse, InterviewQuestionPayload, InterviewQuestionResponse, InterviewSubmitAnswerPayload, InterviewTranscriptResponse, InterviewWidgetConfig, ScreenshotUploadRequestResponse } from '../../types';
|
|
1
|
+
import { InterviewConfigResponse, InterviewQuestionPayload, InterviewQuestionResponse, InterviewSubmitAnswerPayload, InterviewTranscriptResponse, InterviewViolationsPayload, InterviewViolationsResponse, InterviewWidgetConfig, ScreenshotUploadRequestResponse } from '../../types';
|
|
2
2
|
declare class InterviewAPI {
|
|
3
3
|
private config;
|
|
4
4
|
constructor(config?: InterviewWidgetConfig["api"]);
|
|
@@ -31,21 +31,29 @@ declare class InterviewAPI {
|
|
|
31
31
|
*/
|
|
32
32
|
getInterviewConfig(interviewId: string): Promise<InterviewConfigResponse>;
|
|
33
33
|
/**
|
|
34
|
-
* Request a signed URL for uploading
|
|
34
|
+
* Request a signed URL for uploading an asset
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
requestUploadUrl(interviewId: string, filename: string | undefined, mimeType: string, assetType: string): Promise<ScreenshotUploadRequestResponse>;
|
|
37
37
|
/**
|
|
38
|
-
* Upload
|
|
38
|
+
* Upload asset to the provided signed URL
|
|
39
39
|
*/
|
|
40
|
-
|
|
40
|
+
uploadAsset(uploadUrl: string, blob: Blob, mimeType: string): Promise<void>;
|
|
41
41
|
/**
|
|
42
|
-
* Confirm
|
|
42
|
+
* Confirm asset upload
|
|
43
43
|
*/
|
|
44
|
-
|
|
44
|
+
confirmAssetUpload(assetId: string): Promise<void>;
|
|
45
45
|
/**
|
|
46
46
|
* Get interview transcription
|
|
47
47
|
*/
|
|
48
48
|
getInterviewTranscription(interviewId: string): Promise<InterviewTranscriptResponse>;
|
|
49
|
+
/**
|
|
50
|
+
* Get violations snapshot for an interview
|
|
51
|
+
*/
|
|
52
|
+
getViolations(interviewId: string): Promise<InterviewViolationsResponse>;
|
|
53
|
+
/**
|
|
54
|
+
* Update violations snapshot for an interview
|
|
55
|
+
*/
|
|
56
|
+
updateViolations({ interviewId, violations, }: InterviewViolationsPayload): Promise<InterviewViolationsResponse>;
|
|
49
57
|
}
|
|
50
58
|
export declare const interviewAPI: InterviewAPI;
|
|
51
59
|
export { InterviewAPI };
|
package/dist/types.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export interface InterviewWidgetConfig {
|
|
|
50
50
|
interview?: {
|
|
51
51
|
allow_answer_editing?: boolean;
|
|
52
52
|
capture_screenshots?: boolean;
|
|
53
|
+
record_video?: boolean;
|
|
53
54
|
timers?: {
|
|
54
55
|
thinkingDuration?: number;
|
|
55
56
|
answeringDuration?: number;
|
|
@@ -135,3 +136,14 @@ export interface TranscriptMessage {
|
|
|
135
136
|
question_generated_at: string;
|
|
136
137
|
answer_submitted_at: string | null;
|
|
137
138
|
}
|
|
139
|
+
export interface InterviewViolationsResponse {
|
|
140
|
+
success: boolean;
|
|
141
|
+
message: string;
|
|
142
|
+
data: any;
|
|
143
|
+
error?: string | null;
|
|
144
|
+
code?: number;
|
|
145
|
+
}
|
|
146
|
+
export interface InterviewViolationsPayload {
|
|
147
|
+
interviewId: string;
|
|
148
|
+
violations: any;
|
|
149
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safari Audio Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralises all Safari-specific audio quirks so every call site stays clean.
|
|
5
|
+
* Each function is a transparent no-op / pass-through on non-Safari browsers.
|
|
6
|
+
*
|
|
7
|
+
* Safari-specific lines are tagged with // [SAFARI] for easy auditing.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Returns true only for genuine Safari (desktop + iOS).
|
|
11
|
+
* Chrome/Edge on iOS report as Safari in the UA, but they also advertise
|
|
12
|
+
* "Chrome" or "CriOS" / "EdgA" — we exclude those. [SAFARI]
|
|
13
|
+
*/
|
|
14
|
+
export declare function isSafari(): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the best supported MIME type for MediaRecorder.
|
|
17
|
+
*
|
|
18
|
+
* Safari only supports audio/mp4 (AAC-LC). Offering audio/webm first causes
|
|
19
|
+
* MediaRecorder construction to throw a NotSupportedError on Safari. [SAFARI]
|
|
20
|
+
*/
|
|
21
|
+
export declare function getSupportedMimeType(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Strips constraints that throw OverconstrainedError on Safari.
|
|
24
|
+
*
|
|
25
|
+
* Safari rejects `sampleRate` and `channelCount` as MediaTrackConstraints,
|
|
26
|
+
* raising an OverconstrainedError that blocks mic access entirely. [SAFARI]
|
|
27
|
+
* All other browsers receive the full constraint set unchanged.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getSafariSafeAudioConstraints(base?: MediaTrackConstraints): MediaTrackConstraints;
|
|
30
|
+
/**
|
|
31
|
+
* Returns the timeslice argument (ms) to pass to MediaRecorder.start().
|
|
32
|
+
*
|
|
33
|
+
* Safari silently suppresses `ondataavailable` events when a timeslice is
|
|
34
|
+
* provided — it will only emit one blob when stop() is called. [SAFARI]
|
|
35
|
+
* Returning `undefined` causes the caller to call `start()` with no argument,
|
|
36
|
+
* which is the correct Safari behaviour.
|
|
37
|
+
*
|
|
38
|
+
* Other browsers get 100 ms streaming chunks for real-time processing.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getMediaRecorderStartArg(): number | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Stops a MediaRecorder, flushing the final chunk on Safari first.
|
|
43
|
+
*
|
|
44
|
+
* Safari sometimes fails to include the last audio segment in the blob
|
|
45
|
+
* unless requestData() is explicitly called just before stop(). [SAFARI]
|
|
46
|
+
* On other browsers requestData() is already called at the stop-promise
|
|
47
|
+
* setup site, so we only call stop() here.
|
|
48
|
+
*/
|
|
49
|
+
export declare function safariSafeStop(recorder: MediaRecorder): void;
|