interview-widget 0.0.7 → 0.0.9

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 (33) hide show
  1. package/README.md +197 -101
  2. package/dist/components/interview/interview-controller.d.ts +8 -0
  3. package/dist/components/interview/interview-header.d.ts +1 -0
  4. package/dist/components/interview/question-display.d.ts +3 -2
  5. package/dist/components/modals/exit-confirmation-modal.d.ts +7 -0
  6. package/dist/components/timer/timer-display.d.ts +13 -0
  7. package/dist/components/ui/dialog.d.ts +13 -0
  8. package/dist/context/interview-widget-context.d.ts +34 -0
  9. package/dist/hooks/use-api.d.ts +26 -0
  10. package/dist/hooks/use-dialog.d.ts +6 -0
  11. package/dist/hooks/use-interview-api.d.ts +5 -0
  12. package/dist/hooks/use-stt.d.ts +20 -0
  13. package/dist/hooks/use-timer.d.ts +12 -0
  14. package/dist/hooks/use-tts.d.ts +15 -0
  15. package/dist/index.d.ts +3 -2
  16. package/dist/services/api/index.d.ts +2 -0
  17. package/dist/services/api/interview-api.d.ts +23 -0
  18. package/dist/services/stt/index.d.ts +1 -0
  19. package/dist/services/stt/stt-service.d.ts +78 -0
  20. package/dist/services/timer/index.d.ts +6 -0
  21. package/dist/services/timer/timer-service.d.ts +81 -0
  22. package/dist/services/tts/index.d.ts +1 -0
  23. package/dist/services/tts/tts-service.d.ts +43 -0
  24. package/dist/types.d.ts +69 -14
  25. package/dist/utils/api-error-classifier.d.ts +2 -0
  26. package/dist/utils/constants.d.ts +3 -0
  27. package/dist/utils/helper.d.ts +6 -0
  28. package/dist/utils/resilient-fetch.d.ts +9 -0
  29. package/dist/widget.css +1 -1
  30. package/dist/widget.es.js +1714 -250
  31. package/dist/widget.umd.js +2 -2
  32. package/package.json +1 -1
  33. /package/dist/components/{onboarding-modal.d.ts → modals/onboarding-modal.d.ts} +0 -0
package/dist/widget.es.js CHANGED
@@ -1,5 +1,9 @@
1
- import { useRef as j, useState as d, useEffect as C, useMemo as A } from "react";
2
- var E = { exports: {} }, y = {};
1
+ var me = Object.defineProperty;
2
+ var ge = (i, t, e) => t in i ? me(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
3
+ var I = (i, t, e) => ge(i, typeof t != "symbol" ? t + "" : t, e);
4
+ import { createContext as he, useContext as fe, useEffect as A, useState as y, useRef as D, useCallback as v, useMemo as xe } from "react";
5
+ import { createPortal as pe } from "react-dom";
6
+ var X = { exports: {} }, U = {};
3
7
  /**
4
8
  * @license React
5
9
  * react-jsx-runtime.production.js
@@ -9,56 +13,281 @@ var E = { exports: {} }, y = {};
9
13
  * This source code is licensed under the MIT license found in the
10
14
  * LICENSE file in the root directory of this source tree.
11
15
  */
12
- var D = Symbol.for("react.transitional.element"), z = Symbol.for("react.fragment");
13
- function $(r, s, i) {
16
+ var be = Symbol.for("react.transitional.element"), ye = Symbol.for("react.fragment");
17
+ function Z(i, t, e) {
14
18
  var a = null;
15
- if (i !== void 0 && (a = "" + i), s.key !== void 0 && (a = "" + s.key), "key" in s) {
16
- i = {};
17
- for (var t in s)
18
- t !== "key" && (i[t] = s[t]);
19
- } else i = s;
20
- return s = i.ref, {
21
- $$typeof: D,
22
- type: r,
19
+ if (e !== void 0 && (a = "" + e), t.key !== void 0 && (a = "" + t.key), "key" in t) {
20
+ e = {};
21
+ for (var s in t)
22
+ s !== "key" && (e[s] = t[s]);
23
+ } else e = t;
24
+ return t = e.ref, {
25
+ $$typeof: be,
26
+ type: i,
23
27
  key: a,
24
- ref: s !== void 0 ? s : null,
25
- props: i
28
+ ref: t !== void 0 ? t : null,
29
+ props: e
26
30
  };
27
31
  }
28
- y.Fragment = z;
29
- y.jsx = $;
30
- y.jsxs = $;
31
- E.exports = y;
32
- var e = E.exports;
33
- const k = ({
34
- children: r,
35
- variant: s = "primary",
36
- size: i = "md",
32
+ U.Fragment = ye;
33
+ U.jsx = Z;
34
+ U.jsxs = Z;
35
+ X.exports = U;
36
+ var r = X.exports;
37
+ const C = {
38
+ api: {
39
+ baseUrl: "/api",
40
+ retryConfig: {
41
+ attempts: 3,
42
+ backoff: "exponential",
43
+ baseDelay: 1e3
44
+ }
45
+ },
46
+ ui: {
47
+ baseColor: "#3B82F6",
48
+ borderRadius: "8px"
49
+ },
50
+ interview: {
51
+ timers: {
52
+ thinkingDuration: 30,
53
+ answeringDuration: 120,
54
+ editingDuration: 30
55
+ },
56
+ stt: {
57
+ provider: "groq",
58
+ model: "whisper-large-v3-turbo",
59
+ language: "en"
60
+ },
61
+ tts: {
62
+ provider: "piper"
63
+ }
64
+ }
65
+ }, ee = he(
66
+ null
67
+ );
68
+ function Ne({
69
+ config: i = {},
70
+ children: t
71
+ }) {
72
+ var a, s, c, n;
73
+ const e = {
74
+ api: {
75
+ ...C.api,
76
+ ...i.api,
77
+ retryConfig: {
78
+ ...C.api.retryConfig,
79
+ ...(a = i.api) == null ? void 0 : a.retryConfig
80
+ }
81
+ },
82
+ ui: {
83
+ ...C.ui,
84
+ ...i.ui
85
+ },
86
+ interview: {
87
+ ...C.interview,
88
+ ...i.interview,
89
+ timers: {
90
+ ...C.interview.timers,
91
+ ...(s = i.interview) == null ? void 0 : s.timers
92
+ },
93
+ stt: {
94
+ ...C.interview.stt,
95
+ ...(c = i.interview) == null ? void 0 : c.stt
96
+ },
97
+ tts: {
98
+ ...C.interview.tts,
99
+ ...(n = i.interview) == null ? void 0 : n.tts
100
+ }
101
+ }
102
+ };
103
+ return /* @__PURE__ */ r.jsx(ee.Provider, { value: e, children: t });
104
+ }
105
+ function q() {
106
+ const i = fe(ee);
107
+ if (!i)
108
+ throw new Error(
109
+ "useInterviewConfig must be used within an InterviewWidgetProvider. Wrap your component tree with <InterviewWidgetProvider config={...}>"
110
+ );
111
+ return i;
112
+ }
113
+ function Te() {
114
+ return q().api || C.api;
115
+ }
116
+ function F() {
117
+ return q().ui || C.ui;
118
+ }
119
+ function Ie() {
120
+ return q().interview || C.interview;
121
+ }
122
+ const ve = ({
123
+ isOpen: i,
124
+ onClose: t,
125
+ children: e,
126
+ title: a,
127
+ showCloseButton: s = !0,
128
+ closeOnOverlayClick: c = !0,
129
+ closeOnEscape: n = !0,
130
+ className: o = ""
131
+ }) => {
132
+ if (A(() => {
133
+ if (!i || !n) return;
134
+ const d = (u) => {
135
+ u.key === "Escape" && t();
136
+ };
137
+ return document.addEventListener("keydown", d), () => document.removeEventListener("keydown", d);
138
+ }, [i, n, t]), A(() => (i ? (document.body.style.overflow = "hidden", document.body.classList.add("interview-widget-container")) : (document.body.style.overflow = "unset", document.body.classList.remove("interview-widget-container")), () => {
139
+ document.body.style.overflow = "unset";
140
+ }), [i]), !i) return null;
141
+ const m = (d) => {
142
+ c && d.target === d.currentTarget && t();
143
+ }, g = /* @__PURE__ */ r.jsxs("div", { className: "iw-fixed iw-inset-0 iw-z-50 iw-flex iw-items-center iw-justify-center", children: [
144
+ /* @__PURE__ */ r.jsx(
145
+ "div",
146
+ {
147
+ className: "iw-fixed iw-inset-0 iw-bg-black iw-bg-opacity-50 iw-transition-opacity",
148
+ onClick: m
149
+ }
150
+ ),
151
+ /* @__PURE__ */ r.jsxs(
152
+ "div",
153
+ {
154
+ className: `iw-relative iw-bg-white iw-rounded-lg iw-shadow-xl iw-max-w-md iw-w-full iw-mx-4 iw-max-h-[90vh] iw-overflow-hidden ${o}`,
155
+ role: "dialog",
156
+ "aria-modal": "true",
157
+ "aria-labelledby": a ? "dialog-title" : void 0,
158
+ children: [
159
+ (a || s) && /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-p-4 iw-border-b iw-border-gray-200", children: [
160
+ a && /* @__PURE__ */ r.jsx(
161
+ "h2",
162
+ {
163
+ id: "dialog-title",
164
+ className: "iw-text-lg iw-font-semibold iw-text-gray-900",
165
+ children: a
166
+ }
167
+ ),
168
+ s && /* @__PURE__ */ r.jsx(
169
+ "button",
170
+ {
171
+ onClick: t,
172
+ className: "iw-p-1 iw-text-gray-400 iw-hover:text-gray-600 iw-transition-colors iw-rounded iw-hover:bg-gray-100",
173
+ "aria-label": "Close dialog",
174
+ children: /* @__PURE__ */ r.jsx(
175
+ "svg",
176
+ {
177
+ className: "iw-w-5 iw-h-5",
178
+ fill: "none",
179
+ stroke: "currentColor",
180
+ viewBox: "0 0 24 24",
181
+ children: /* @__PURE__ */ r.jsx(
182
+ "path",
183
+ {
184
+ strokeLinecap: "round",
185
+ strokeLinejoin: "round",
186
+ strokeWidth: 2,
187
+ d: "M6 18L18 6M6 6l12 12"
188
+ }
189
+ )
190
+ }
191
+ )
192
+ }
193
+ )
194
+ ] }),
195
+ /* @__PURE__ */ r.jsx("div", { className: "iw-p-4 iw-overflow-y-auto", children: e })
196
+ ]
197
+ }
198
+ )
199
+ ] });
200
+ return pe(g, document.body);
201
+ }, Ee = ({
202
+ confirmExitInterview: i,
203
+ isOpen: t,
204
+ onClose: e
205
+ }) => /* @__PURE__ */ r.jsx(ve, { isOpen: t, onClose: e, title: "Exit Interview", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-space-y-4", children: [
206
+ /* @__PURE__ */ r.jsx("p", { className: "iw-text-base iw-text-gray-700", children: "Are you sure you want to exit the interview? All progress will be lost and you will not be able to resume." }),
207
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-justify-end iw-space-x-2", children: [
208
+ /* @__PURE__ */ r.jsx(
209
+ "button",
210
+ {
211
+ className: "iw-px-4 iw-py-2 iw-bg-gray-200 iw-rounded iw-text-gray-700 iw-font-medium",
212
+ onClick: e,
213
+ children: "Cancel"
214
+ }
215
+ ),
216
+ /* @__PURE__ */ r.jsx(
217
+ "button",
218
+ {
219
+ className: "iw-px-4 iw-py-2 iw-bg-red-600 iw-text-white iw-rounded iw-font-medium",
220
+ onClick: i,
221
+ children: "Confirm Exit"
222
+ }
223
+ )
224
+ ] })
225
+ ] }) }), je = ({ title: i, onExit: t }) => {
226
+ const { baseColor: e } = F(), [a, s] = y(!1);
227
+ return /* @__PURE__ */ r.jsxs("header", { className: "iw-w-full iw-text-gray-900", children: [
228
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-mx-auto iw-flex iw-items-center iw-justify-between iw-px-4 iw-py-3", children: [
229
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
230
+ /* @__PURE__ */ r.jsx(
231
+ "div",
232
+ {
233
+ className: "iw-h-7 iw-w-7 iw-rounded-md iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold",
234
+ style: { backgroundColor: e },
235
+ children: "N"
236
+ }
237
+ ),
238
+ /* @__PURE__ */ r.jsx("p", { className: "iw-text-sm iw-font-medium", children: "Novara" })
239
+ ] }),
240
+ /* @__PURE__ */ r.jsx("h1", { className: "iw-text-base iw-font-medium", children: i }),
241
+ /* @__PURE__ */ r.jsx(
242
+ "button",
243
+ {
244
+ className: "iw-text-sm iw-text-gray-500 hover:iw-text-gray-700",
245
+ onClick: () => s(!0),
246
+ children: "Exit Interview"
247
+ }
248
+ )
249
+ ] }),
250
+ /* @__PURE__ */ r.jsx("div", { className: "iw-h-px iw-bg-gray-200" }),
251
+ /* @__PURE__ */ r.jsx(
252
+ Ee,
253
+ {
254
+ isOpen: a,
255
+ confirmExitInterview: () => {
256
+ t(), s(!1);
257
+ },
258
+ onClose: () => s(!1)
259
+ }
260
+ )
261
+ ] });
262
+ }, $ = ({
263
+ children: i,
264
+ variant: t = "primary",
265
+ size: e = "md",
37
266
  fullWidth: a = !1,
38
- isLoading: t = !1,
39
- disabled: l,
40
- className: w = "",
41
- ...c
267
+ isLoading: s = !1,
268
+ disabled: c,
269
+ className: n = "",
270
+ ...o
42
271
  }) => {
43
- const x = "iw-inline-flex iw-items-center iw-justify-center iw-rounded-md iw-font-medium iw-transition-colors iw-focus:outline-none iw-focus:ring-2 iw-focus:ring-primary-500 iw-focus:ring-offset-2", m = {
272
+ const m = "iw-inline-flex iw-items-center iw-justify-center iw-rounded-md iw-font-medium iw-transition-colors iw-focus:outline-none iw-focus:ring-2 iw-focus:ring-primary-500 iw-focus:ring-offset-2", g = {
44
273
  primary: "iw-bg-primary-600 iw-text-white iw-hover:bg-primary-700 iw-border iw-border-transparent",
45
274
  secondary: "iw-bg-primary-100 iw-text-primary-700 iw-hover:bg-primary-200 iw-border iw-border-transparent",
46
275
  outline: "iw-bg-transparent iw-text-primary-700 iw-border iw-border-primary-500 iw-hover:bg-primary-50",
47
276
  text: "iw-bg-transparent iw-text-primary-600 iw-hover:bg-primary-50 iw-border iw-border-transparent",
48
277
  gradient: "iw-text-white iw-border iw-border-transparent iw-bg-gradient-to-r iw-from-purple-500 iw-to-indigo-500 hover:iw-from-purple-600 hover:iw-to-indigo-600"
49
- }, o = {
278
+ }, d = {
50
279
  sm: "iw-px-3 iw-py-1.5 iw-text-sm",
51
280
  md: "iw-px-4 iw-py-2 iw-text-sm",
52
281
  lg: "iw-px-5 iw-py-2.5 iw-text-base"
53
- }, u = "iw-disabled:opacity-50 iw-disabled:cursor-not-allowed iw-disabled:pointer-events-none", f = a ? "iw-w-full" : "";
54
- return /* @__PURE__ */ e.jsxs(
282
+ }, u = "iw-disabled:opacity-50 iw-disabled:cursor-not-allowed iw-disabled:pointer-events-none", h = a ? "iw-w-full" : "";
283
+ return /* @__PURE__ */ r.jsxs(
55
284
  "button",
56
285
  {
57
- className: `${x} ${m[s]} ${o[i]} ${f} ${u} ${w}`,
58
- disabled: l || t,
59
- ...c,
286
+ className: `${m} ${g[t]} ${d[e]} ${h} ${u} ${n}`,
287
+ disabled: c || s,
288
+ ...o,
60
289
  children: [
61
- t && /* @__PURE__ */ e.jsxs(
290
+ s && /* @__PURE__ */ r.jsxs(
62
291
  "svg",
63
292
  {
64
293
  className: "iw-animate-spin iw-mr-2 iw-h-4 iw-w-4 iw-text-white",
@@ -66,7 +295,7 @@ const k = ({
66
295
  fill: "none",
67
296
  viewBox: "0 0 24 24",
68
297
  children: [
69
- /* @__PURE__ */ e.jsx(
298
+ /* @__PURE__ */ r.jsx(
70
299
  "circle",
71
300
  {
72
301
  className: "iw-opacity-25",
@@ -77,7 +306,7 @@ const k = ({
77
306
  strokeWidth: "4"
78
307
  }
79
308
  ),
80
- /* @__PURE__ */ e.jsx(
309
+ /* @__PURE__ */ r.jsx(
81
310
  "path",
82
311
  {
83
312
  className: "iw-opacity-75",
@@ -88,63 +317,63 @@ const k = ({
88
317
  ]
89
318
  }
90
319
  ),
91
- r
320
+ i
92
321
  ]
93
322
  }
94
323
  );
95
- }, F = ({
96
- isOpen: r,
97
- onStart: s,
98
- onClose: i
324
+ }, Se = ({
325
+ isOpen: i,
326
+ onStart: t,
327
+ onClose: e
99
328
  }) => {
100
- var g;
101
- const a = j(null), t = j(null), [l, w] = d(!1), [c, x] = d(null), [m, o] = d(!1), u = () => {
102
- t.current && (t.current.getTracks().forEach((n) => n.stop()), t.current = null);
103
- }, f = async () => {
104
- o(!0), x(null);
329
+ var N;
330
+ const a = D(null), s = D(null), { baseColor: c, borderRadius: n } = F(), [o, m] = y(!1), [g, d] = y(null), [u, h] = y(!1), x = () => {
331
+ s.current && (s.current.getTracks().forEach((w) => w.stop()), s.current = null);
332
+ }, k = async () => {
333
+ h(!0), d(null);
105
334
  try {
106
- const n = await navigator.mediaDevices.getUserMedia({
335
+ const w = await navigator.mediaDevices.getUserMedia({
107
336
  video: { width: { ideal: 1280 }, height: { ideal: 720 } },
108
337
  audio: !0
109
338
  });
110
- t.current = n, a.current && (a.current.srcObject = n), w(!0);
111
- } catch (n) {
112
- console.error("Media permission error:", n);
113
- let h = "Unable to access camera or microphone.";
114
- (n == null ? void 0 : n.name) === "NotAllowedError" ? h = "Permissions denied. Please allow access to camera and microphone." : (n == null ? void 0 : n.name) === "NotFoundError" ? h = "No camera/microphone found. Please connect a device and retry." : n != null && n.message && (h = n.message), w(!1), x(h);
339
+ s.current = w, a.current && (a.current.srcObject = w), m(!0);
340
+ } catch (w) {
341
+ console.error("Media permission error:", w);
342
+ let p = "Unable to access camera or microphone.";
343
+ (w == null ? void 0 : w.name) === "NotAllowedError" ? p = "Permissions denied. Please allow access to camera and microphone." : (w == null ? void 0 : w.name) === "NotFoundError" ? p = "No camera/microphone found. Please connect a device and retry." : w != null && w.message && (p = w.message), m(!1), d(p);
115
344
  } finally {
116
- o(!1);
345
+ h(!1);
117
346
  }
118
347
  };
119
- if (C(() => {
120
- if (!r) {
121
- u();
348
+ if (A(() => {
349
+ if (!i) {
350
+ x();
122
351
  return;
123
352
  }
124
- return f(), () => {
125
- u();
353
+ return k(), () => {
354
+ x();
126
355
  };
127
- }, [r]), !r) return null;
128
- const N = () => {
129
- s(), u();
356
+ }, [i]), !i) return null;
357
+ const j = () => {
358
+ t(), x();
130
359
  };
131
- return /* @__PURE__ */ e.jsx("div", { className: "iw-fixed iw-inset-0 iw-z-50 iw-flex iw-items-center iw-justify-center iw-bg-black/50 iw-backdrop-blur-sm", children: /* @__PURE__ */ e.jsxs("div", { className: "iw-bg-white iw-rounded-xl iw-shadow-2xl iw-w-full iw-max-w-3xl iw-mx-4", children: [
132
- /* @__PURE__ */ e.jsxs("div", { className: "iw-px-5 iw-py-4 iw-border-b iw-border-gray-200 iw-flex iw-items-center iw-justify-between", children: [
133
- /* @__PURE__ */ e.jsx("h2", { className: "iw-text-base iw-font-semibold", children: "Camera & Microphone Check" }),
134
- i && /* @__PURE__ */ e.jsx(
360
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-fixed iw-inset-0 iw-z-50 iw-flex iw-items-center iw-justify-center iw-bg-black/50 iw-backdrop-blur-sm", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-bg-white iw-rounded-xl iw-shadow-2xl iw-w-full iw-max-w-3xl iw-mx-4", children: [
361
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-px-5 iw-py-4 iw-border-b iw-border-gray-200 iw-flex iw-items-center iw-justify-between", children: [
362
+ /* @__PURE__ */ r.jsx("h2", { className: "iw-text-base iw-font-semibold", children: "Camera & Microphone Check" }),
363
+ e && /* @__PURE__ */ r.jsx(
135
364
  "button",
136
365
  {
137
366
  "aria-label": "Close",
138
367
  className: "iw-text-gray-500 hover:iw-text-gray-700",
139
368
  onClick: () => {
140
- u(), i == null || i();
369
+ x(), e == null || e();
141
370
  },
142
371
  children: "✕"
143
372
  }
144
373
  )
145
374
  ] }),
146
- /* @__PURE__ */ e.jsxs("div", { className: "iw-p-4 iw-grid iw-grid-cols-2 iw-gap-4", children: [
147
- /* @__PURE__ */ e.jsx("div", { className: "iw-border iw-border-gray-200 iw-rounded-lg iw-overflow-hidden iw-bg-gray-900", children: /* @__PURE__ */ e.jsx(
375
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-grid iw-grid-cols-2 iw-gap-4", children: [
376
+ /* @__PURE__ */ r.jsx("div", { className: "iw-border iw-border-gray-200 iw-rounded-lg iw-overflow-hidden iw-bg-gray-900", children: /* @__PURE__ */ r.jsx(
148
377
  "video",
149
378
  {
150
379
  ref: a,
@@ -154,183 +383,1107 @@ const k = ({
154
383
  className: "iw-w-full iw-h-64 iw-object-cover"
155
384
  }
156
385
  ) }),
157
- /* @__PURE__ */ e.jsxs("div", { className: "iw-flex iw-flex-col iw-gap-3", children: [
158
- /* @__PURE__ */ e.jsx("p", { className: "iw-text-sm iw-text-gray-700", children: "We will need access to your camera and microphone. Grant permission to preview your setup and to enable the Start Interview button." }),
159
- !((g = navigator.mediaDevices) != null && g.getUserMedia) && /* @__PURE__ */ e.jsx("div", { className: "iw-text-xs iw-text-red-600", children: "Your browser does not support media devices. Please use a modern browser like Chrome, Edge, or Firefox." }),
160
- c && /* @__PURE__ */ e.jsx("div", { className: "iw-text-xs iw-text-red-600", children: c }),
161
- /* @__PURE__ */ e.jsxs("div", { className: "iw-flex iw-items-center iw-gap-2", children: [
162
- /* @__PURE__ */ e.jsx(
163
- k,
386
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-flex-col iw-gap-3", children: [
387
+ /* @__PURE__ */ r.jsx("p", { className: "iw-text-sm iw-text-gray-700", children: "We will need access to your camera and microphone. Grant permission to preview your setup and to enable the Start Interview button." }),
388
+ !((N = navigator.mediaDevices) != null && N.getUserMedia) && /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-red-600", children: "Your browser does not support media devices. Please use a modern browser like Chrome, Edge, or Firefox." }),
389
+ g && /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-red-600", children: g }),
390
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-gap-2", children: [
391
+ /* @__PURE__ */ r.jsx(
392
+ $,
164
393
  {
165
- onClick: f,
166
- isLoading: m,
394
+ onClick: k,
395
+ isLoading: u,
167
396
  variant: "outline",
168
397
  size: "sm",
169
- children: l ? "Recheck Permissions" : "Enable Camera & Mic"
398
+ style: {
399
+ borderColor: c,
400
+ borderRadius: n,
401
+ color: c
402
+ },
403
+ children: o ? "Recheck Permissions" : "Enable Camera & Mic"
170
404
  }
171
405
  ),
172
- /* @__PURE__ */ e.jsx(
173
- k,
406
+ /* @__PURE__ */ r.jsx(
407
+ $,
174
408
  {
175
- onClick: N,
176
- disabled: !l,
409
+ onClick: j,
410
+ disabled: !o,
177
411
  size: "sm",
178
- children: "Start Interview"
412
+ style: { backgroundColor: c, borderRadius: n },
413
+ children: "Proceed"
179
414
  }
180
415
  )
181
416
  ] }),
182
- /* @__PURE__ */ e.jsxs("ul", { className: "iw-text-xs iw-text-gray-500 iw-pt-2 iw-list-disc iw-pl-4", children: [
183
- /* @__PURE__ */ e.jsx("li", { children: "Your preview is muted to avoid echo." }),
184
- /* @__PURE__ */ e.jsx("li", { children: "You can change devices from your browser’s site settings." })
417
+ /* @__PURE__ */ r.jsxs("ul", { className: "iw-text-xs iw-text-gray-500 iw-pt-2 iw-list-disc iw-pl-4", children: [
418
+ /* @__PURE__ */ r.jsx("li", { children: "Your preview is muted to avoid echo." }),
419
+ /* @__PURE__ */ r.jsx("li", { children: "You can change devices from your browser’s site settings." })
185
420
  ] })
186
421
  ] })
187
422
  ] })
188
423
  ] }) });
189
- }, G = ({ title: r }) => /* @__PURE__ */ e.jsxs("header", { className: "iw-w-full iw-text-gray-900", children: [
190
- /* @__PURE__ */ e.jsxs("div", { className: "iw-mx-auto iw-flex iw-items-center iw-justify-between iw-px-4 iw-py-3", children: [
191
- /* @__PURE__ */ e.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
192
- /* @__PURE__ */ e.jsx(
193
- "div",
194
- {
195
- className: "iw-h-7 iw-w-7 iw-rounded-md iw-bg-purple-500 iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold",
196
- children: "N"
197
- }
198
- ),
199
- /* @__PURE__ */ e.jsx("p", { className: "iw-text-sm iw-font-medium", children: "Novara" })
200
- ] }),
201
- /* @__PURE__ */ e.jsx("h1", { className: "iw-text-base iw-font-medium", children: r }),
202
- /* @__PURE__ */ e.jsx("button", { className: "iw-text-sm iw-text-gray-500 hover:iw-text-gray-700", children: "Exit Interview" })
203
- ] }),
204
- /* @__PURE__ */ e.jsx("div", { className: "iw-h-px iw-bg-gray-200" })
205
- ] }), Q = ({ question: r }) => /* @__PURE__ */ e.jsxs(
206
- "div",
207
- {
208
- className: "iw-rounded-xl iw-mb-4 message-animation iw-bg-gradient-to-b iw-from-indigo-50 iw-to-white iw-text-gray-800 iw-border iw-border-indigo-100 iw-p-5",
209
- style: {
210
- // Fallback styles in case CSS classes don't load properly
211
- background: "linear-gradient(to bottom, #eef2ff, #ffffff)",
212
- border: "1px solid #e0e7ff",
213
- color: "#1f2937"
424
+ };
425
+ var l = /* @__PURE__ */ ((i) => (i.IDLE = "idle", i.FETCHING_QUESTION = "fetching_question", i.READING_QUESTION = "reading_question", i.THINKING = "thinking", i.ANSWERING = "answering", i.TRANSCRIBING = "transcribing", i.EDITING = "editing", i.SUBMITTING = "submitting", i.COMPLETED = "completed", i))(l || {});
426
+ const Re = {
427
+ thinkingDuration: 30,
428
+ answeringDuration: 120,
429
+ editingDuration: 30,
430
+ totalInterviewDuration: 600,
431
+ minimumTimeForNextQuestion: 120
432
+ }, Ce = {
433
+ idle: {
434
+ next: "fetching_question"
435
+ /* FETCHING_QUESTION */
436
+ },
437
+ fetching_question: {
438
+ next: "reading_question"
439
+ /* READING_QUESTION */
440
+ },
441
+ reading_question: {
442
+ next: "thinking"
443
+ /* THINKING */
444
+ },
445
+ thinking: { next: "answering", duration: 30 },
446
+ answering: { next: "transcribing", duration: 120 },
447
+ transcribing: {
448
+ next: "editing"
449
+ /* EDITING */
450
+ },
451
+ editing: { next: "submitting", duration: 30 },
452
+ submitting: {
453
+ next: "completed"
454
+ /* COMPLETED */
455
+ },
456
+ completed: {
457
+ next: "completed"
458
+ /* COMPLETED */
459
+ }
460
+ };
461
+ class ke {
462
+ constructor(t = {}, e = {}) {
463
+ I(this, "config");
464
+ I(this, "state");
465
+ I(this, "phaseIntervalId", null);
466
+ I(this, "globalIntervalId", null);
467
+ I(this, "callbacks");
468
+ this.config = { ...Re, ...t }, this.callbacks = e, this.state = {
469
+ phase: "idle",
470
+ currentPhaseTimeRemaining: 0,
471
+ totalTimeRemaining: this.config.totalInterviewDuration,
472
+ totalTimeElapsed: 0,
473
+ currentQuestionNumber: 0
474
+ };
475
+ }
476
+ /**
477
+ * Get current state
478
+ */
479
+ getState() {
480
+ return { ...this.state };
481
+ }
482
+ /**
483
+ * Start a new question cycle
484
+ */
485
+ startQuestion() {
486
+ var t, e;
487
+ if (this.state.totalTimeRemaining < this.config.minimumTimeForNextQuestion) {
488
+ this.state.phase = "completed", this.stopGlobalTimer(), this.stopPhaseTimer(), (e = (t = this.callbacks).onInterviewEnd) == null || e.call(t), this.notifyChange();
489
+ return;
490
+ }
491
+ this.state.currentQuestionNumber === 0 && this.startGlobalTimer(), this.state.currentQuestionNumber = this.state.currentQuestionNumber + 1, this.state.phase = "fetching_question", this.notifyChange();
492
+ }
493
+ /**
494
+ * Move to next phase
495
+ */
496
+ nextPhase() {
497
+ const t = this.state.phase, e = Ce[t];
498
+ if (!e) return;
499
+ this.stopPhaseTimer(), this.state.phase = e.next;
500
+ const a = this.getDurationForPhase(e.next);
501
+ a > 0 ? (this.state.currentPhaseTimeRemaining = a, this.startPhaseTimer()) : this.state.currentPhaseTimeRemaining = 0, this.notifyChange();
502
+ }
503
+ /**
504
+ * Cleanup
505
+ */
506
+ destroy() {
507
+ this.stopPhaseTimer(), this.stopGlobalTimer();
508
+ }
509
+ /**
510
+ * Get duration for a phase
511
+ */
512
+ getDurationForPhase(t) {
513
+ switch (t) {
514
+ case "thinking":
515
+ return this.config.thinkingDuration;
516
+ case "answering":
517
+ return this.config.answeringDuration;
518
+ case "editing":
519
+ return this.config.editingDuration;
520
+ default:
521
+ return 0;
522
+ }
523
+ }
524
+ /**
525
+ * Start global timer (runs continuously during entire interview)
526
+ */
527
+ startGlobalTimer() {
528
+ this.globalIntervalId = setInterval(() => {
529
+ var t, e, a, s;
530
+ this.state.totalTimeRemaining--, this.state.totalTimeElapsed++, (e = (t = this.callbacks).onTick) == null || e.call(t, this.getState()), this.state.totalTimeRemaining <= 0 && (this.stopGlobalTimer(), this.stopPhaseTimer(), this.state.phase = "completed", (s = (a = this.callbacks).onInterviewEnd) == null || s.call(a), this.notifyChange());
531
+ }, 1e3);
532
+ }
533
+ /**
534
+ * Stop global timer
535
+ */
536
+ stopGlobalTimer() {
537
+ this.globalIntervalId && (clearInterval(this.globalIntervalId), this.globalIntervalId = null);
538
+ }
539
+ /**
540
+ * Start phase timer (only for timed phases)
541
+ */
542
+ startPhaseTimer() {
543
+ this.phaseIntervalId = setInterval(() => {
544
+ this.state.currentPhaseTimeRemaining--, this.state.currentPhaseTimeRemaining <= 0 && this.nextPhase();
545
+ }, 1e3);
546
+ }
547
+ /**
548
+ * Stop phase timer
549
+ */
550
+ stopPhaseTimer() {
551
+ this.phaseIntervalId && (clearInterval(this.phaseIntervalId), this.phaseIntervalId = null);
552
+ }
553
+ /**
554
+ * Notify phase change
555
+ */
556
+ notifyChange() {
557
+ var t, e;
558
+ (e = (t = this.callbacks).onPhaseChange) == null || e.call(t, this.state.phase, this.getState());
559
+ }
560
+ }
561
+ function De(i = {}) {
562
+ const { config: t = {}, callbacks: e = {} } = i, a = D(null);
563
+ a.current || (a.current = new ke(t, {}));
564
+ const s = a.current, [c, n] = y(s.getState()), o = v(() => {
565
+ n(s.getState());
566
+ }, [s]);
567
+ A(() => {
568
+ const d = {
569
+ onPhaseChange: (u, h) => {
570
+ var x;
571
+ o(), (x = e.onPhaseChange) == null || x.call(e, u, h);
572
+ },
573
+ onTick: (u) => {
574
+ var h;
575
+ o(), (h = e.onTick) == null || h.call(e, u);
576
+ },
577
+ onInterviewEnd: () => {
578
+ var u;
579
+ o(), (u = e.onInterviewEnd) == null || u.call(e);
580
+ }
581
+ };
582
+ s.callbacks = d;
583
+ }, [s, e, o]), A(() => () => {
584
+ s.destroy();
585
+ }, [s]);
586
+ const m = v(() => {
587
+ s.startQuestion(), o();
588
+ }, [s, o]), g = v(() => {
589
+ s.nextPhase(), o();
590
+ }, [s, o]);
591
+ return {
592
+ state: c,
593
+ startQuestion: m,
594
+ nextPhase: g,
595
+ timerService: s
596
+ };
597
+ }
598
+ function Pe(i, t = {}) {
599
+ const [e, a] = y({
600
+ data: null,
601
+ loading: !1,
602
+ error: null
603
+ }), s = v(
604
+ async (...c) => {
605
+ var n, o, m, g;
606
+ a((d) => ({ ...d, loading: !0, error: null }));
607
+ try {
608
+ const d = await i(...c);
609
+ a((u) => ({
610
+ ...u,
611
+ data: d,
612
+ loading: !1,
613
+ error: null
614
+ })), (n = t.onSuccess) == null || n.call(t, d), (o = t.onSettled) == null || o.call(t, d, null);
615
+ } catch (d) {
616
+ const u = d.type ? d : {
617
+ type: "unknown",
618
+ message: d.message || "Unknown error",
619
+ retryable: !0,
620
+ userMessage: "Something went wrong. Please try again.",
621
+ originalError: d
622
+ };
623
+ a((h) => ({
624
+ ...h,
625
+ loading: !1,
626
+ error: u
627
+ })), (m = t.onError) == null || m.call(t, u), (g = t.onSettled) == null || g.call(t, null, u);
628
+ }
214
629
  },
215
- children: [
216
- /* @__PURE__ */ e.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-3 iw-mb-3", children: [
217
- /* @__PURE__ */ e.jsx(
218
- "div",
219
- {
220
- className: "iw-h-12 iw-w-12 iw-rounded-lg iw-bg-purple-500 iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold",
221
- children: "N"
222
- }
223
- ),
224
- /* @__PURE__ */ e.jsxs("div", { children: [
225
- /* @__PURE__ */ e.jsx("div", { className: "iw-text-sm iw-font-semibold", children: "Novara" }),
226
- /* @__PURE__ */ e.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Assistant" })
227
- ] })
228
- ] }),
229
- /* @__PURE__ */ e.jsx("p", { className: "iw-text-[15px] iw-leading-6", children: r.text }),
230
- r.type === "multiple-choice" && r.options && /* @__PURE__ */ e.jsx("div", { className: "iw-mt-3 iw-space-y-2", children: r.options.map((s, i) => /* @__PURE__ */ e.jsx(
231
- "div",
630
+ [i, t]
631
+ );
632
+ return {
633
+ ...e,
634
+ execute: s
635
+ };
636
+ }
637
+ function Ae(i) {
638
+ var t;
639
+ if (!navigator.onLine)
640
+ return {
641
+ type: "network",
642
+ message: "No internet connection",
643
+ retryable: !0,
644
+ userMessage: "Please check your internet connection and try again."
645
+ };
646
+ if (i.name === "AbortError" || (t = i.message) != null && t.includes("timeout"))
647
+ return {
648
+ type: "timeout",
649
+ message: "Request timed out",
650
+ retryable: !0,
651
+ userMessage: "The request is taking longer than expected. Please try again."
652
+ };
653
+ if (i.status) {
654
+ const { status: e } = i;
655
+ if (e === 401 || e === 403)
656
+ return {
657
+ type: "auth",
658
+ status: e,
659
+ message: "Authentication failed",
660
+ retryable: !1,
661
+ userMessage: "Your session has expired. Please refresh the page."
662
+ };
663
+ if (e === 429)
664
+ return {
665
+ type: "rate-limit",
666
+ status: e,
667
+ message: "Too many requests",
668
+ retryable: !0,
669
+ userMessage: "Please wait a moment before trying again."
670
+ };
671
+ if (e >= 500)
672
+ return {
673
+ type: "server",
674
+ status: e,
675
+ message: `Server error: ${e}`,
676
+ retryable: !0,
677
+ userMessage: "Our servers are experiencing issues. Please try again in a few moments."
678
+ };
679
+ if (e >= 400)
680
+ return {
681
+ type: "client",
682
+ status: e,
683
+ message: `Client error: ${e}`,
684
+ retryable: !1,
685
+ userMessage: "There was an issue with your request. Please check your input."
686
+ };
687
+ }
688
+ return {
689
+ type: "unknown",
690
+ message: i.message || "Unknown error occurred",
691
+ retryable: !0,
692
+ userMessage: "Something unexpected happened. Please try again.",
693
+ originalError: i
694
+ };
695
+ }
696
+ async function H(i, t = {}, e = {
697
+ attempts: 3,
698
+ backoff: "exponential",
699
+ baseDelay: 1e3,
700
+ maxDelay: 1e4,
701
+ jitter: !0
702
+ }) {
703
+ let a;
704
+ for (let s = 1; s <= e.attempts; s++)
705
+ try {
706
+ const c = new AbortController(), n = setTimeout(() => c.abort(), 6e4), o = await fetch(i, {
707
+ ...t,
708
+ signal: c.signal
709
+ });
710
+ if (clearTimeout(n), o.status >= 400 && o.status < 500 && o.status !== 429)
711
+ return o;
712
+ if (!o.ok)
713
+ throw new Error(`HTTP ${o.status}: ${o.statusText}`);
714
+ return o;
715
+ } catch (c) {
716
+ a = c;
717
+ const n = Ae(c);
718
+ if (!n.retryable || s === e.attempts)
719
+ throw n;
720
+ const o = Ge(s, e);
721
+ console.warn(
722
+ `API request failed (attempt ${s}/${e.attempts}), retrying in ${o}ms:`,
723
+ n.message
724
+ ), await new Promise((m) => setTimeout(m, o));
725
+ }
726
+ throw a;
727
+ }
728
+ function Ge(i, t) {
729
+ let e;
730
+ return t.backoff === "exponential" ? e = t.baseDelay * Math.pow(2, i - 1) : e = t.baseDelay, e = Math.min(e, t.maxDelay), t.jitter && (e = e * (0.5 + Math.random() * 0.5)), Math.round(e);
731
+ }
732
+ class Me {
733
+ constructor(t = {}) {
734
+ I(this, "config");
735
+ this.config = t;
736
+ }
737
+ /**
738
+ * Update configuration
739
+ */
740
+ updateConfig(t) {
741
+ this.config = { ...this.config, ...t };
742
+ }
743
+ /**
744
+ * Get default headers for API requests
745
+ */
746
+ getHeaders() {
747
+ var e;
748
+ const t = {
749
+ "Content-Type": "application/json",
750
+ "X-Auth-Token": "appkey"
751
+ };
752
+ return (e = this.config) != null && e.authToken && (t.Authorization = `Bearer ${this.config.authToken}`), t;
753
+ }
754
+ /**
755
+ * Get base URL from config with fallback
756
+ */
757
+ getBaseUrl() {
758
+ var t;
759
+ return ((t = this.config) == null ? void 0 : t.baseUrl) || "/api";
760
+ }
761
+ /**
762
+ * Get questions for an interview
763
+ */
764
+ async generateQuestion({
765
+ interviewId: t,
766
+ isInterviewDone: e = !1,
767
+ qnaId: a,
768
+ question: s,
769
+ answer: c,
770
+ answerDuration: n
771
+ }) {
772
+ const o = await H(
773
+ `${this.getBaseUrl()}/interview/generate-question`,
774
+ {
775
+ method: "POST",
776
+ headers: this.getHeaders(),
777
+ body: JSON.stringify({
778
+ interview_id: t,
779
+ is_interview_done: e,
780
+ qna_id: a,
781
+ question: s,
782
+ answer: c,
783
+ // TODO: Hardcoded for now, will be dynamic later
784
+ answer_duration: n ?? "00:00:30"
785
+ })
786
+ }
787
+ );
788
+ if (!o.ok)
789
+ throw new Error(`Failed to get questions: ${o.status}`);
790
+ return await o.json();
791
+ }
792
+ }
793
+ function Oe() {
794
+ const i = q();
795
+ return xe(() => {
796
+ const e = i.api || {};
797
+ return new Me(e);
798
+ }, [i.api]);
799
+ }
800
+ class b extends Error {
801
+ constructor(t, e, a = !1) {
802
+ super(t), this.code = e, this.recoverable = a, this.name = "STTError";
803
+ }
804
+ }
805
+ class $e {
806
+ constructor(t = {}) {
807
+ I(this, "config");
808
+ I(this, "mediaRecorder", null);
809
+ I(this, "audioChunks", []);
810
+ I(this, "recordingStream", null);
811
+ I(this, "autoStopTimeoutId", null);
812
+ this.config = {
813
+ baseUrl: "http://localhost:8000",
814
+ provider: "groq",
815
+ model: "whisper-large-v3-turbo",
816
+ language: "en",
817
+ includeTimestamps: !1,
818
+ temperature: 0,
819
+ ...t
820
+ };
821
+ }
822
+ /**
823
+ * Update STT configuration
824
+ */
825
+ updateConfig(t) {
826
+ this.config = { ...this.config, ...t };
827
+ }
828
+ /**
829
+ * Check if browser supports audio recording
830
+ */
831
+ isRecordingSupported() {
832
+ return !!(navigator.mediaDevices && typeof navigator.mediaDevices.getUserMedia == "function" && window.MediaRecorder);
833
+ }
834
+ /**
835
+ * Start recording audio from user's microphone
836
+ */
837
+ async startRecording(t, e) {
838
+ var a;
839
+ if (!this.isRecordingSupported())
840
+ throw new b(
841
+ "Audio recording is not supported in this browser",
842
+ "RECORDING_NOT_SUPPORTED",
843
+ !1
844
+ );
845
+ if (this.isRecording())
846
+ throw new b(
847
+ "Recording is already in progress",
848
+ "ALREADY_RECORDING",
849
+ !0
850
+ );
851
+ try {
852
+ this.recordingStream = await navigator.mediaDevices.getUserMedia({
853
+ audio: {
854
+ echoCancellation: !0,
855
+ noiseSuppression: !0,
856
+ sampleRate: 44100
857
+ }
858
+ }), this.audioChunks = [];
859
+ const s = this.getSupportedMimeType();
860
+ this.mediaRecorder = new MediaRecorder(this.recordingStream, {
861
+ mimeType: s
862
+ }), this.mediaRecorder.ondataavailable = (c) => {
863
+ var n;
864
+ c.data.size > 0 && (this.audioChunks.push(c.data), (n = e == null ? void 0 : e.onDataAvailable) == null || n.call(e, c.data));
865
+ }, this.mediaRecorder.onstop = () => {
866
+ var c;
867
+ (c = e == null ? void 0 : e.onStop) == null || c.call(e);
868
+ }, this.mediaRecorder.onerror = (c) => {
869
+ var o;
870
+ const n = new b(
871
+ `Recording failed: ${c.error}`,
872
+ "RECORDING_ERROR",
873
+ !0
874
+ );
875
+ (o = e == null ? void 0 : e.onError) == null || o.call(e, n), this.cleanup();
876
+ }, this.mediaRecorder.start(100), (a = e == null ? void 0 : e.onStart) == null || a.call(e), t && t > 0 && (this.autoStopTimeoutId = setTimeout(() => {
877
+ this.isRecording() && this.stopRecording();
878
+ }, t * 1e3));
879
+ } catch (s) {
880
+ if (this.cleanup(), s instanceof Error) {
881
+ if (s.name === "NotAllowedError" || s.name === "PermissionDeniedError")
882
+ throw new b(
883
+ "Microphone permission was denied",
884
+ "PERMISSION_DENIED",
885
+ !1
886
+ );
887
+ if (s.name === "NotFoundError")
888
+ throw new b("No microphone found", "NO_MICROPHONE", !1);
889
+ }
890
+ throw new b(
891
+ `Failed to start recording: ${s instanceof Error ? s.message : String(s)}`,
892
+ "START_RECORDING_FAILED",
893
+ !0
894
+ );
895
+ }
896
+ }
897
+ /**
898
+ * Stop recording and return the audio blob
899
+ */
900
+ async stopRecording() {
901
+ if (this.autoStopTimeoutId && (clearTimeout(this.autoStopTimeoutId), this.autoStopTimeoutId = null), !this.mediaRecorder || !this.isRecording())
902
+ throw new b(
903
+ "No active recording to stop",
904
+ "NO_ACTIVE_RECORDING",
905
+ !1
906
+ );
907
+ return new Promise((t, e) => {
908
+ if (!this.mediaRecorder) {
909
+ e(
910
+ new b("MediaRecorder is null", "MEDIARECORDER_NULL", !1)
911
+ );
912
+ return;
913
+ }
914
+ const a = this.mediaRecorder, s = () => {
915
+ try {
916
+ const c = a.mimeType || "audio/webm", n = new Blob(this.audioChunks, { type: c });
917
+ this.cleanup(), t(n);
918
+ } catch (c) {
919
+ e(
920
+ new b(
921
+ `Failed to create audio blob: ${c instanceof Error ? c.message : String(c)}`,
922
+ "BLOB_CREATION_FAILED",
923
+ !1
924
+ )
925
+ );
926
+ }
927
+ };
928
+ a.addEventListener("stop", s, { once: !0 }), a.stop();
929
+ });
930
+ }
931
+ /**
932
+ * Transcribe audio blob using the STT API
933
+ */
934
+ async transcribe(t) {
935
+ const {
936
+ audioBlob: e,
937
+ model: a = this.config.model,
938
+ language: s = this.config.language,
939
+ includeTimestamps: c = this.config.includeTimestamps,
940
+ temperature: n = this.config.temperature
941
+ } = t;
942
+ if (!e || e.size === 0)
943
+ throw new b(
944
+ "Audio blob is empty or invalid",
945
+ "INVALID_AUDIO",
946
+ !1
947
+ );
948
+ try {
949
+ const o = new FormData(), m = new File([e], "recording.wav", {
950
+ type: e.type || "audio/wav"
951
+ });
952
+ o.append("file", m), o.append("model", a || "whisper-large-v3-turbo"), o.append("language", s || "en"), o.append("include_timestamps", String(c || !1)), o.append("temperature", String(n || 0));
953
+ const g = await H(
954
+ `${this.config.baseUrl}/speech/transcribe`,
232
955
  {
233
- className: "iw-p-2 iw-rounded iw-border iw-border-gray-300 iw-hover:bg-gray-100 iw-cursor-pointer iw-transition-colors",
234
- children: s
956
+ method: "POST",
957
+ headers: {
958
+ accept: "application/json",
959
+ "X-STT-Provider": this.config.provider || "groq"
960
+ },
961
+ body: o
235
962
  },
236
- i
237
- )) })
238
- ]
239
- }
240
- ), Y = ({ className: r = "" }) => {
241
- const s = j(null);
242
- return C(() => {
243
- let i = null;
244
- return (async () => {
963
+ {
964
+ attempts: 1,
965
+ backoff: "exponential",
966
+ baseDelay: 1e3,
967
+ maxDelay: 3e3,
968
+ jitter: !0
969
+ }
970
+ );
971
+ if (!g.ok) {
972
+ const u = await g.text();
973
+ let h = `STT request failed: ${g.status} ${g.statusText}`;
974
+ try {
975
+ const x = JSON.parse(u);
976
+ h = x.message || x.error || h;
977
+ } catch {
978
+ h = u || h;
979
+ }
980
+ throw new b(
981
+ h,
982
+ `HTTP_${g.status}`,
983
+ g.status >= 500
984
+ );
985
+ }
986
+ return {
987
+ transcript: (await g.json()).data.text ?? ""
988
+ };
989
+ } catch (o) {
990
+ throw o instanceof b ? o : new b(
991
+ `Transcription failed: ${o instanceof Error ? o.message : String(o)}`,
992
+ "TRANSCRIPTION_FAILED",
993
+ !0
994
+ );
995
+ }
996
+ }
997
+ /**
998
+ * Cancel current recording without processing
999
+ */
1000
+ cancelRecording() {
1001
+ this.autoStopTimeoutId && (clearTimeout(this.autoStopTimeoutId), this.autoStopTimeoutId = null), this.mediaRecorder && this.isRecording() && this.mediaRecorder.stop(), this.cleanup();
1002
+ }
1003
+ /**
1004
+ * Check if currently recording
1005
+ */
1006
+ isRecording() {
1007
+ return this.mediaRecorder !== null && this.mediaRecorder.state === "recording";
1008
+ }
1009
+ /**
1010
+ * Get supported MIME type for recording
1011
+ */
1012
+ getSupportedMimeType() {
1013
+ const t = [
1014
+ "audio/webm",
1015
+ "audio/webm;codecs=opus",
1016
+ "audio/ogg;codecs=opus",
1017
+ "audio/mp4",
1018
+ "audio/wav"
1019
+ ];
1020
+ for (const e of t)
1021
+ if (MediaRecorder.isTypeSupported(e))
1022
+ return e;
1023
+ return "audio/webm";
1024
+ }
1025
+ /**
1026
+ * Clean up recording resources
1027
+ */
1028
+ cleanup() {
1029
+ this.recordingStream && (this.recordingStream.getTracks().forEach((t) => t.stop()), this.recordingStream = null), this.mediaRecorder = null, this.audioChunks = [], this.autoStopTimeoutId && (clearTimeout(this.autoStopTimeoutId), this.autoStopTimeoutId = null);
1030
+ }
1031
+ }
1032
+ const O = new $e(), _e = (i = {}) => {
1033
+ const [t, e] = y(!1), [a, s] = y(!1), [c, n] = y(null), [o, m] = y(null), [g, d] = y(null);
1034
+ i.config && O.updateConfig(i.config);
1035
+ const u = v(async (j) => {
1036
+ var N;
1037
+ try {
1038
+ m(null), n(null), d(null), await O.startRecording(j, {
1039
+ onStart: () => {
1040
+ var w;
1041
+ e(!0), (w = i.onStart) == null || w.call(i);
1042
+ },
1043
+ onStop: () => {
1044
+ var w;
1045
+ e(!1), (w = i.onStop) == null || w.call(i);
1046
+ },
1047
+ onError: (w) => {
1048
+ var T;
1049
+ const p = w instanceof b ? w : new b(w.message, "RECORDING_ERROR", !0);
1050
+ m(p), e(!1), (T = i.onError) == null || T.call(i, p);
1051
+ }
1052
+ });
1053
+ } catch (w) {
1054
+ const p = w instanceof b ? w : new b(
1055
+ w instanceof Error ? w.message : String(w),
1056
+ "START_FAILED",
1057
+ !1
1058
+ );
1059
+ throw m(p), e(!1), (N = i.onError) == null || N.call(i, p), p;
1060
+ }
1061
+ }, []), h = v(async () => {
1062
+ var j, N;
1063
+ try {
1064
+ const w = await O.stopRecording();
1065
+ return d(w), e(!1), (j = i.onStop) == null || j.call(i), w;
1066
+ } catch (w) {
1067
+ const p = w instanceof b ? w : new b(
1068
+ w instanceof Error ? w.message : String(w),
1069
+ "STOP_FAILED",
1070
+ !1
1071
+ );
1072
+ throw m(p), e(!1), (N = i.onError) == null || N.call(i, p), p;
1073
+ }
1074
+ }, []), x = v(
1075
+ async (j, N = {}) => {
1076
+ var w, p;
245
1077
  try {
246
- i = await navigator.mediaDevices.getUserMedia({
247
- video: !0,
248
- audio: !1
249
- }), s.current && (s.current.srcObject = i);
250
- } catch (t) {
251
- console.error("Error accessing camera:", t);
1078
+ m(null), s(!0);
1079
+ const T = {
1080
+ audioBlob: j,
1081
+ ...N
1082
+ }, S = await O.transcribe(T);
1083
+ return n(S.transcript), s(!1), (w = i.onTranscriptionComplete) == null || w.call(i, S), S;
1084
+ } catch (T) {
1085
+ const S = T instanceof b ? T : new b(
1086
+ T instanceof Error ? T.message : String(T),
1087
+ "TRANSCRIPTION_FAILED",
1088
+ !0
1089
+ );
1090
+ throw m(S), s(!1), (p = i.onError) == null || p.call(i, S), S;
252
1091
  }
253
- })(), () => {
254
- i && i.getTracks().forEach((t) => t.stop());
1092
+ },
1093
+ []
1094
+ ), k = v(() => {
1095
+ O.cancelRecording(), e(!1), d(null);
1096
+ }, []);
1097
+ return {
1098
+ startRecording: u,
1099
+ stopRecording: h,
1100
+ transcribe: x,
1101
+ cancelRecording: k,
1102
+ isRecording: t,
1103
+ isTranscribing: a,
1104
+ transcript: c,
1105
+ error: o,
1106
+ audioBlob: g
1107
+ };
1108
+ };
1109
+ class Le {
1110
+ constructor(t = {}) {
1111
+ I(this, "config");
1112
+ I(this, "currentAudio", null);
1113
+ this.config = {
1114
+ baseUrl: "http://localhost:8000",
1115
+ provider: "piper",
1116
+ voice: "string",
1117
+ speed: 1,
1118
+ ...t
255
1119
  };
256
- }, []), /* @__PURE__ */ e.jsx("div", { className: `iw-relative ${r}`, children: /* @__PURE__ */ e.jsx(
257
- "video",
1120
+ }
1121
+ /**
1122
+ * Update TTS configuration
1123
+ */
1124
+ updateConfig(t) {
1125
+ this.config = { ...this.config, ...t };
1126
+ }
1127
+ /**
1128
+ * Get TTS audio from the API and return as blob
1129
+ */
1130
+ async synthesizeSpeech(t) {
1131
+ const {
1132
+ text: e,
1133
+ voice: a = this.config.voice,
1134
+ speed: s = this.config.speed
1135
+ } = t, c = new URLSearchParams();
1136
+ c.append("text", e), c.append("voice", a || "string"), c.append("speed", (s == null ? void 0 : s.toString()) || "1");
1137
+ const n = await H(
1138
+ `${this.config.baseUrl}/speech/synthesize`,
1139
+ {
1140
+ method: "POST",
1141
+ headers: {
1142
+ accept: "application/json",
1143
+ "X-TTS-Provider": this.config.provider || "piper",
1144
+ "Content-Type": "application/x-www-form-urlencoded"
1145
+ },
1146
+ body: c
1147
+ },
1148
+ {
1149
+ attempts: 1,
1150
+ backoff: "fixed",
1151
+ baseDelay: 1e3,
1152
+ maxDelay: 1e3,
1153
+ jitter: !1
1154
+ }
1155
+ );
1156
+ if (!n.ok)
1157
+ throw new Error(
1158
+ `TTS request failed: ${n.status} ${n.statusText}`
1159
+ );
1160
+ const o = n.headers.get("content-type");
1161
+ if (o && o.includes("audio/"))
1162
+ return n.blob();
1163
+ try {
1164
+ const m = await n.json();
1165
+ throw new Error(`TTS Error: ${JSON.stringify(m)}`);
1166
+ } catch {
1167
+ throw new Error("TTS request failed with unknown error");
1168
+ }
1169
+ }
1170
+ /**
1171
+ * Speak text and return a promise that resolves when playback completes
1172
+ */
1173
+ async speak(t, e) {
1174
+ var a, s;
1175
+ try {
1176
+ this.stop(), (a = e == null ? void 0 : e.onStart) == null || a.call(e);
1177
+ const c = await this.synthesizeSpeech(t), n = URL.createObjectURL(c);
1178
+ return this.currentAudio = new Audio(n), new Promise((o, m) => {
1179
+ if (!this.currentAudio) {
1180
+ m(new Error("Audio element not created"));
1181
+ return;
1182
+ }
1183
+ const g = this.currentAudio;
1184
+ g.onended = () => {
1185
+ var d;
1186
+ URL.revokeObjectURL(n), this.currentAudio = null, (d = e == null ? void 0 : e.onEnd) == null || d.call(e), o();
1187
+ }, g.onerror = (d) => {
1188
+ var h;
1189
+ URL.revokeObjectURL(n), this.currentAudio = null;
1190
+ const u = new Error(`Audio playback failed: ${d}`);
1191
+ (h = e == null ? void 0 : e.onError) == null || h.call(e, u), m(u);
1192
+ }, g.play().catch((d) => {
1193
+ var h;
1194
+ URL.revokeObjectURL(n), this.currentAudio = null;
1195
+ const u = new Error(`Failed to play audio: ${d.message}`);
1196
+ (h = e == null ? void 0 : e.onError) == null || h.call(e, u), m(u);
1197
+ });
1198
+ });
1199
+ } catch (c) {
1200
+ const n = c instanceof Error ? c : new Error(`TTS Error: ${String(c)}`);
1201
+ throw (s = e == null ? void 0 : e.onError) == null || s.call(e, n), n;
1202
+ }
1203
+ }
1204
+ /**
1205
+ * Stop current audio playback
1206
+ */
1207
+ stop() {
1208
+ this.currentAudio && (this.currentAudio.pause(), this.currentAudio.currentTime = 0, this.currentAudio = null);
1209
+ }
1210
+ /**
1211
+ * Check if audio is currently playing
1212
+ */
1213
+ isPlaying() {
1214
+ return this.currentAudio !== null && !this.currentAudio.paused;
1215
+ }
1216
+ }
1217
+ const B = new Le(), Ue = (i = {}) => {
1218
+ const [t, e] = y(!1), [a, s] = y(!1), [c, n] = y(null);
1219
+ i.config && B.updateConfig(i.config);
1220
+ const o = v(
1221
+ async (g, d = {}) => {
1222
+ var u;
1223
+ try {
1224
+ n(null), s(!0);
1225
+ const h = {
1226
+ text: g,
1227
+ ...d
1228
+ };
1229
+ await B.speak(h, {
1230
+ onStart: () => {
1231
+ var x;
1232
+ s(!1), e(!0), (x = i.onStart) == null || x.call(i);
1233
+ },
1234
+ onEnd: () => {
1235
+ var x;
1236
+ e(!1), (x = i.onEnd) == null || x.call(i);
1237
+ },
1238
+ onError: (x) => {
1239
+ var k;
1240
+ e(!1), s(!1), n(x), (k = i.onError) == null || k.call(i, x);
1241
+ }
1242
+ });
1243
+ } catch (h) {
1244
+ const x = h instanceof Error ? h : new Error(String(h));
1245
+ throw n(x), e(!1), s(!1), (u = i.onError) == null || u.call(i, x), x;
1246
+ }
1247
+ },
1248
+ [i]
1249
+ ), m = v(() => {
1250
+ B.stop(), e(!1), s(!1);
1251
+ }, []);
1252
+ return {
1253
+ speak: o,
1254
+ stop: m,
1255
+ isPlaying: t,
1256
+ isLoading: a,
1257
+ error: c
1258
+ };
1259
+ };
1260
+ function qe(i) {
1261
+ const t = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(i);
1262
+ return t ? {
1263
+ r: parseInt(t[1], 16),
1264
+ g: parseInt(t[2], 16),
1265
+ b: parseInt(t[3], 16)
1266
+ } : null;
1267
+ }
1268
+ function Fe(i, t, e) {
1269
+ return "#" + [i, t, e].map((a) => {
1270
+ const s = Math.round(a).toString(16);
1271
+ return s.length === 1 ? "0" + s : s;
1272
+ }).join("");
1273
+ }
1274
+ function V(i, t) {
1275
+ const e = qe(i);
1276
+ if (!e) return i;
1277
+ const a = e.r + (255 - e.r) * t, s = e.g + (255 - e.g) * t, c = e.b + (255 - e.b) * t;
1278
+ return Fe(a, s, c);
1279
+ }
1280
+ function Qe(i, t = 0.8) {
1281
+ const e = V(i, t), a = V(i, 0.7);
1282
+ return {
1283
+ background: `linear-gradient(to bottom, ${e}, #ffffff)`,
1284
+ border: `1px solid ${a}`,
1285
+ color: "#1f2937"
1286
+ };
1287
+ }
1288
+ function Be(i) {
1289
+ return new Promise((t) => setTimeout(t, i));
1290
+ }
1291
+ const He = ({
1292
+ state: i,
1293
+ className: t = "",
1294
+ defaultTimers: e = { thinking: 30, answering: 120, editing: 30 }
1295
+ }) => {
1296
+ const a = (d) => {
1297
+ const u = Math.floor(d / 60), h = d % 60;
1298
+ return `${u.toString().padStart(2, "0")}:${h.toString().padStart(2, "0")}`;
1299
+ }, s = (d) => ({
1300
+ [l.IDLE]: "Ready",
1301
+ [l.FETCHING_QUESTION]: "Loading Question...",
1302
+ [l.READING_QUESTION]: "Reading Question...",
1303
+ [l.THINKING]: "Preparation Time",
1304
+ [l.ANSWERING]: "Recording Answer",
1305
+ [l.TRANSCRIBING]: "Processing Speech...",
1306
+ [l.EDITING]: "Edit Your Answer",
1307
+ [l.SUBMITTING]: "Submitting...",
1308
+ [l.COMPLETED]: "Interview Complete"
1309
+ })[d] || d, c = (d) => ({
1310
+ [l.IDLE]: "iw-bg-gray-500",
1311
+ [l.FETCHING_QUESTION]: "iw-bg-blue-500",
1312
+ [l.READING_QUESTION]: "iw-bg-indigo-500",
1313
+ [l.THINKING]: "iw-bg-yellow-500",
1314
+ [l.ANSWERING]: "iw-bg-red-500",
1315
+ [l.TRANSCRIBING]: "iw-bg-purple-500",
1316
+ [l.EDITING]: "iw-bg-orange-500",
1317
+ [l.SUBMITTING]: "iw-bg-green-500",
1318
+ [l.COMPLETED]: "iw-bg-green-600"
1319
+ })[d] || "iw-bg-gray-500", n = (d) => ({
1320
+ [l.IDLE]: "iw-bg-gray-100 iw-text-gray-800",
1321
+ [l.FETCHING_QUESTION]: "iw-bg-blue-100 iw-text-blue-800",
1322
+ [l.READING_QUESTION]: "iw-bg-indigo-100 iw-text-indigo-800",
1323
+ [l.THINKING]: "iw-bg-yellow-100 iw-text-yellow-800",
1324
+ [l.ANSWERING]: "iw-bg-red-100 iw-text-red-800",
1325
+ [l.TRANSCRIBING]: "iw-bg-purple-100 iw-text-purple-800",
1326
+ [l.EDITING]: "iw-bg-orange-100 iw-text-orange-800",
1327
+ [l.SUBMITTING]: "iw-bg-green-100 iw-text-green-800",
1328
+ [l.COMPLETED]: "iw-bg-green-200 iw-text-green-900"
1329
+ })[d] || "iw-bg-gray-100 iw-text-gray-800", o = (d) => ({
1330
+ [l.IDLE]: "Ready to start next question.",
1331
+ [l.FETCHING_QUESTION]: "Please wait while we load the next question...",
1332
+ [l.READING_QUESTION]: "Listening to the question...",
1333
+ [l.THINKING]: "Take time to think about your answer.",
1334
+ [l.ANSWERING]: "Speak clearly into your microphone.",
1335
+ [l.TRANSCRIBING]: "Converting your speech to text...",
1336
+ [l.EDITING]: "Review and edit your answer.",
1337
+ [l.SUBMITTING]: "Submitting your answer...",
1338
+ [l.COMPLETED]: "Thank you for completing the interview!"
1339
+ })[d] || "";
1340
+ function m(d) {
1341
+ return {
1342
+ [l.THINKING]: e.thinking || 30,
1343
+ [l.ANSWERING]: e.answering || 120,
1344
+ [l.EDITING]: e.editing || 30
1345
+ }[d] || 1;
1346
+ }
1347
+ const g = i.currentPhaseTimeRemaining > 0;
1348
+ return /* @__PURE__ */ r.jsxs(
1349
+ "div",
258
1350
  {
259
- ref: s,
260
- autoPlay: !0,
261
- playsInline: !0,
262
- muted: !0,
263
- className: "iw-w-full iw-h-full iw-object-cover iw-rounded-md"
1351
+ className: `iw-iw-bg-white iw-rounded-lg iw-shadow-md iw-p-4 iw-border iw-border-gray-200 ${t}`,
1352
+ children: [
1353
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-justify-between iw-items-center iw-mb-4", children: [
1354
+ /* @__PURE__ */ r.jsxs("div", { children: [
1355
+ /* @__PURE__ */ r.jsx("h3", { className: "iw-text-sm iw-font-semibold iw-text-gray-700", children: "Interview Timer" }),
1356
+ /* @__PURE__ */ r.jsxs("p", { className: "iw-text-xs iw-text-gray-700 iw-my-3 iw-font-mono", children: [
1357
+ "Phase",
1358
+ " ",
1359
+ /* @__PURE__ */ r.jsx(
1360
+ "span",
1361
+ {
1362
+ className: `iw-px-3 iw-py-1.5 iw-rounded-md iw-font-medium ${n(
1363
+ i.phase
1364
+ )}`,
1365
+ children: i.phase
1366
+ }
1367
+ )
1368
+ ] }),
1369
+ /* @__PURE__ */ r.jsxs("p", { className: "iw-text-xs iw-text-gray-700 iw-font-mono", children: [
1370
+ "Question ",
1371
+ i.currentQuestionNumber
1372
+ ] })
1373
+ ] }),
1374
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-text-right", children: [
1375
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-2xl iw-font-bold iw-text-gray-900", children: a(i.totalTimeRemaining) }),
1376
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Total Time Left" })
1377
+ ] })
1378
+ ] }),
1379
+ /* @__PURE__ */ r.jsx("div", { className: "iw-mb-4", children: /* @__PURE__ */ r.jsx("div", { className: "iw-w-full iw-h-2 iw-iw-bg-gray-200 iw-rounded-full iw-overflow-hidden", children: /* @__PURE__ */ r.jsx(
1380
+ "div",
1381
+ {
1382
+ className: "iw-h-full iw-iw-bg-gradient-to-r iw-from-blue-500 iw-to-purple-500 iw-transition-all iw-duration-300",
1383
+ style: {
1384
+ width: `${i.totalTimeElapsed / (i.totalTimeElapsed + i.totalTimeRemaining) * 100}%`
1385
+ }
1386
+ }
1387
+ ) }) }),
1388
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-mb-4", children: [
1389
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-mb-2", children: [
1390
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
1391
+ /* @__PURE__ */ r.jsx(
1392
+ "div",
1393
+ {
1394
+ className: `iw-w-3 iw-h-3 iw-rounded-full ${c(
1395
+ i.phase
1396
+ )} ${g ? "iw-animate-pulse" : ""}`
1397
+ }
1398
+ ),
1399
+ /* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-gray-700", children: s(i.phase) })
1400
+ ] }),
1401
+ g && /* @__PURE__ */ r.jsx("span", { className: "iw-text-lg iw-font-bold iw-text-gray-900", children: a(i.currentPhaseTimeRemaining) })
1402
+ ] }),
1403
+ g && /* @__PURE__ */ r.jsx("div", { className: "iw-w-full iw-h-1.5 iw-iw-bg-gray-200 iw-rounded-full iw-overflow-hidden", children: /* @__PURE__ */ r.jsx(
1404
+ "div",
1405
+ {
1406
+ className: `iw-h-full ${c(
1407
+ i.phase
1408
+ )} iw-transition-all iw-duration-300`,
1409
+ style: {
1410
+ width: `${i.currentPhaseTimeRemaining / m(i.phase) * 100}%`
1411
+ }
1412
+ }
1413
+ ) })
1414
+ ] }),
1415
+ /* @__PURE__ */ r.jsx("div", { className: "iw-mt-3 iw-pt-3 iw-border-t iw-border-gray-200", children: /* @__PURE__ */ r.jsx("p", { className: "iw-text-xs iw-text-gray-600", children: o(i.phase) }) })
1416
+ ]
264
1417
  }
265
- ) });
266
- }, _ = ({
267
- label: r,
268
- error: s,
269
- fullWidth: i = !1,
1418
+ );
1419
+ }, We = ({
1420
+ label: i,
1421
+ error: t,
1422
+ fullWidth: e = !1,
270
1423
  className: a = "",
271
- id: t,
272
- ...l
1424
+ id: s,
1425
+ ...c
273
1426
  }) => {
274
- const w = t || `textarea-${Math.random().toString(36).substring(2, 9)}`, c = "iw-block iw-rounded-md iw-border iw-border-gray-300 iw-shadow-sm iw-px-4 iw-py-2 iw-text-sm iw-focus:border-primary-500 iw-focus:ring-primary-500 iw-focus:outline-none iw-transition-all", x = s ? "iw-border-red-500 iw-focus:border-red-500 iw-focus:ring-red-500" : "", m = i ? "iw-w-full" : "", o = a.includes("iw-h-full") ? "iw-h-full" : "";
275
- return /* @__PURE__ */ e.jsxs(
1427
+ const n = s || `textarea-${Math.random().toString(36).substring(2, 9)}`, o = "iw-block iw-rounded-md iw-border iw-border-gray-300 iw-shadow-sm iw-px-4 iw-py-2 iw-text-sm iw-focus:border-primary-500 iw-focus:ring-primary-500 iw-focus:outline-none iw-transition-all", m = t ? "iw-border-red-500 iw-focus:border-red-500 iw-focus:ring-red-500" : "", g = e ? "iw-w-full" : "", d = a.includes("iw-h-full") ? "iw-h-full" : "";
1428
+ return /* @__PURE__ */ r.jsxs(
276
1429
  "div",
277
1430
  {
278
- className: `${i ? "iw-w-full iw-h-full" : ""} ${o ? "iw-flex iw-flex-col" : ""}`,
1431
+ className: `${e ? "iw-w-full iw-h-full" : ""} ${d ? "iw-flex iw-flex-col" : ""}`,
279
1432
  children: [
280
- r && /* @__PURE__ */ e.jsx(
1433
+ i && /* @__PURE__ */ r.jsx(
281
1434
  "label",
282
1435
  {
283
- htmlFor: w,
1436
+ htmlFor: n,
284
1437
  className: "iw-block iw-text-sm iw-font-medium iw-text-gray-700 iw-mb-1",
285
- children: r
1438
+ children: i
286
1439
  }
287
1440
  ),
288
- /* @__PURE__ */ e.jsx(
1441
+ /* @__PURE__ */ r.jsx(
289
1442
  "textarea",
290
1443
  {
291
- id: w,
292
- className: `${c} ${x} ${m} ${o} ${a}`,
293
- "aria-invalid": s ? "true" : "false",
294
- ...l
1444
+ id: n,
1445
+ className: `${o} ${m} ${g} ${d} ${a}`,
1446
+ "aria-invalid": t ? "true" : "false",
1447
+ ...c
295
1448
  }
296
1449
  ),
297
- s && /* @__PURE__ */ e.jsx("p", { className: "iw-mt-1 iw-text-sm iw-text-red-600", children: s })
1450
+ t && /* @__PURE__ */ r.jsx("p", { className: "iw-mt-1 iw-text-sm iw-text-red-600", children: t })
298
1451
  ]
299
1452
  }
300
1453
  );
301
- }, U = ({
302
- value: r,
303
- onChange: s,
304
- onSubmit: i,
1454
+ }, ze = ({
1455
+ value: i,
1456
+ onChange: t,
1457
+ onSubmit: e,
305
1458
  isSubmitDisabled: a,
306
- remainingTimeText: t
1459
+ remainingTimeText: s
307
1460
  }) => {
308
- const l = (w) => {
309
- w.key === "Enter" && (w.ctrlKey || w.metaKey) && !a && (w.preventDefault(), i());
1461
+ const c = (n) => {
1462
+ n.key === "Enter" && (n.ctrlKey || n.metaKey) && !a && (n.preventDefault(), e());
310
1463
  };
311
- return /* @__PURE__ */ e.jsx("div", { className: "iw-mt-auto", children: /* @__PURE__ */ e.jsxs("div", { className: "iw-rounded-xl iw-overflow-hidden iw-border iw-border-gray-200", children: [
312
- /* @__PURE__ */ e.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-px-3 iw-py-2 iw-bg-gray-50 iw-border-b iw-border-gray-200", children: [
313
- /* @__PURE__ */ e.jsx("div", { className: "iw-text-sm iw-font-medium", children: "Your answer" }),
314
- t && /* @__PURE__ */ e.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: t })
1464
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-mt-auto", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-rounded-xl iw-overflow-hidden iw-border iw-border-gray-200", children: [
1465
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-justify-between iw-px-3 iw-py-2 iw-bg-gray-50 iw-border-b iw-border-gray-200", children: [
1466
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-sm iw-font-medium", children: "Your answer" }),
1467
+ s && /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: s })
315
1468
  ] }),
316
- /* @__PURE__ */ e.jsx(
317
- _,
1469
+ /* @__PURE__ */ r.jsx(
1470
+ We,
318
1471
  {
319
- value: r,
320
- onChange: s,
321
- onKeyDown: l,
1472
+ value: i,
1473
+ onChange: t,
1474
+ onKeyDown: c,
322
1475
  placeholder: "Type your answer here...",
323
1476
  className: "iw-bg-gray-50 iw-w-full iw-resize-none iw-focus:outline-none iw-bg-transparent iw-min-h-[112px]",
324
1477
  rows: 5,
325
1478
  fullWidth: !0
326
1479
  }
327
1480
  ),
328
- /* @__PURE__ */ e.jsxs("div", { className: "iw-p-2 iw-flex iw-justify-between iw-items-center iw-bg-gray-50", children: [
329
- /* @__PURE__ */ e.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: /* @__PURE__ */ e.jsx("kbd", { children: " Press Ctrl+Enter to submit" }) }),
330
- /* @__PURE__ */ e.jsx(
331
- k,
1481
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-p-2 iw-flex iw-justify-between iw-items-center iw-bg-gray-50", children: [
1482
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: /* @__PURE__ */ r.jsx("kbd", { children: " Press Ctrl+Enter to submit" }) }),
1483
+ /* @__PURE__ */ r.jsx(
1484
+ $,
332
1485
  {
333
- onClick: i,
1486
+ onClick: e,
334
1487
  disabled: a,
335
1488
  size: "sm",
336
1489
  variant: "gradient",
@@ -339,72 +1492,383 @@ const k = ({
339
1492
  )
340
1493
  ] })
341
1494
  ] }) });
342
- }, W = ({
343
- title: r = "Interview",
344
- questions: s = [],
345
- onComplete: i,
346
- onAnswerSubmit: a,
347
- className: t = ""
1495
+ }, Ye = ({
1496
+ question: i,
1497
+ isLoading: t = !1
348
1498
  }) => {
349
- const [l, w] = d(0), [c, x] = d([]), [m, o] = d(""), [u, f] = d(!1), [N, g] = d(!0), [n, h] = d(!1), [I] = d(!0), P = j(null), p = s[l], S = () => {
350
- const v = {
351
- questionId: (p == null ? void 0 : p.id) || "",
352
- answerText: m,
353
- timestamp: /* @__PURE__ */ new Date()
354
- };
355
- x([...c, v]), a && a(v), l < s.length - 1 ? (w((b) => b + 1), o("")) : (f(!0), i && i(c));
356
- }, M = A(() => {
357
- const b = 60 - Math.floor(Date.now() / 1e3 % 60), T = Math.floor(b / 60).toString().padStart(2, "0"), R = (b % 60).toString().padStart(2, "0");
358
- return `Time to Talk: ${T}:${R} min`;
359
- }, [l]);
360
- return n ? /* @__PURE__ */ e.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ e.jsx(
1499
+ const { baseColor: e } = F();
1500
+ return t ? /* @__PURE__ */ r.jsxs(
361
1501
  "div",
362
1502
  {
363
- ref: P,
364
- className: `iw-flex iw-flex-col iw-rounded-xl iw-shadow-lg iw-overflow-hidden iw-h-[calc(100vh-1rem)] ${t}`,
365
- children: /* @__PURE__ */ e.jsxs("div", { className: " iw-h-full iw-flex iw-flex-col", children: [
366
- /* @__PURE__ */ e.jsx(G, { title: r }),
367
- /* @__PURE__ */ e.jsx("div", { className: "iw-flex iw-flex-col iw-flex-grow iw-overflow-hidden iw-px-4 iw-py-5", children: u ? /* @__PURE__ */ e.jsxs("div", { className: "iw-flex iw-flex-col iw-items-center iw-justify-center iw-h-full", children: [
368
- /* @__PURE__ */ e.jsx("div", { className: "iw-text-xl iw-font-bold iw-mb-2", children: "Interview Complete!" }),
369
- /* @__PURE__ */ e.jsx("p", { className: "iw-text-center iw-mb-4", children: "Thank you for participating in this interview." })
370
- ] }) : /* @__PURE__ */ e.jsxs("div", { className: "iw-h-full iw-flex iw-flex-col ", children: [
371
- /* @__PURE__ */ e.jsx("div", { className: "iw-flex-1", children: p && /* @__PURE__ */ e.jsx(Q, { question: p }) }),
372
- /* @__PURE__ */ e.jsxs("div", { className: "iw-grid iw-grid-cols-2 iw-gap-4 iw-mt-4", children: [
373
- I && /* @__PURE__ */ e.jsx(
374
- "div",
375
- {
376
- className: "iw-mt-2 iw-border iw-border-gray-200 iw-rounded-xl iw-p-2",
377
- children: /* @__PURE__ */ e.jsx(Y, { className: "iw-w-full iw-h-[400px]" })
378
- }
379
- ),
380
- /* @__PURE__ */ e.jsx(
381
- U,
382
- {
383
- value: m,
384
- onChange: (v) => o(v.target.value),
385
- onSubmit: S,
386
- isSubmitDisabled: !m.trim() || !n,
387
- remainingTimeText: M
388
- }
389
- )
1503
+ className: "iw-rounded-xl iw-mb-4 iw-p-5",
1504
+ style: {
1505
+ background: "linear-gradient(to bottom, #eef2ff, #ffffff)",
1506
+ border: "1px solid #e0e7ff",
1507
+ color: "#1f2937"
1508
+ },
1509
+ children: [
1510
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-3 iw-mb-3", children: [
1511
+ /* @__PURE__ */ r.jsx(
1512
+ "div",
1513
+ {
1514
+ className: "iw-h-12 iw-w-12 iw-rounded-lg iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold iw-animate-pulse",
1515
+ style: { backgroundColor: e },
1516
+ children: "N"
1517
+ }
1518
+ ),
1519
+ /* @__PURE__ */ r.jsxs("div", { children: [
1520
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-sm iw-font-semibold", children: "Novara" }),
1521
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Assistant" })
390
1522
  ] })
391
- ] }) })
392
- ] })
1523
+ ] }),
1524
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-animate-pulse", children: [
1525
+ /* @__PURE__ */ r.jsx("div", { className: "iw-h-4 iw-bg-gray-200 iw-rounded iw-w-3/4 iw-mb-2" }),
1526
+ /* @__PURE__ */ r.jsx("div", { className: "iw-h-4 iw-bg-gray-200 iw-rounded iw-w-full" })
1527
+ ] })
1528
+ ]
1529
+ }
1530
+ ) : i ? /* @__PURE__ */ r.jsxs(
1531
+ "div",
1532
+ {
1533
+ className: "iw-rounded-xl iw-mb-4 message-animation iw-text-gray-800 iw-border iw-border-indigo-100 iw-p-5",
1534
+ style: Qe(e ?? "#8C75FB", 0.85),
1535
+ children: [
1536
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-3 iw-mb-3", children: [
1537
+ /* @__PURE__ */ r.jsx(
1538
+ "div",
1539
+ {
1540
+ className: "iw-h-12 iw-w-12 iw-rounded-lg iw-flex iw-items-center iw-justify-center iw-text-white iw-font-semibold",
1541
+ style: { backgroundColor: e },
1542
+ children: "N"
1543
+ }
1544
+ ),
1545
+ /* @__PURE__ */ r.jsxs("div", { children: [
1546
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-sm iw-font-semibold", children: "Novara" }),
1547
+ /* @__PURE__ */ r.jsx("div", { className: "iw-text-xs iw-text-gray-500", children: "Assistant" })
1548
+ ] })
1549
+ ] }),
1550
+ /* @__PURE__ */ r.jsx("p", { className: "iw-text-[15px] iw-leading-6", children: i.question })
1551
+ ]
393
1552
  }
394
- ) }) : /* @__PURE__ */ e.jsx("div", { className: "interview-widget-container iw-h-screen iw-w-screen", children: /* @__PURE__ */ e.jsx(
395
- F,
1553
+ ) : /* @__PURE__ */ r.jsx(
1554
+ "div",
396
1555
  {
397
- isOpen: N,
398
- onStart: () => {
399
- console.log("Permissions granted, starting interview"), h(!0), g(!1);
1556
+ className: "iw-rounded-xl iw-mb-4 iw-bg-gray-50 iw-text-gray-500 iw-border iw-border-gray-200 iw-p-5 iw-text-center",
1557
+ children: /* @__PURE__ */ r.jsx("p", { className: "iw-text-sm", children: "No question available" })
1558
+ }
1559
+ );
1560
+ }, Ke = ({
1561
+ interviewId: i,
1562
+ onComplete: t,
1563
+ className: e = ""
1564
+ }) => {
1565
+ const a = Oe(), { baseColor: s } = F(), { baseUrl: c } = Te(), { timers: n, stt: o, tts: m } = Ie(), [g, d] = y(null), [u, h] = y(""), [x, k] = y(!1), j = D(""), N = D(null), w = {
1566
+ thinkingTime: (n == null ? void 0 : n.thinkingDuration) || 30,
1567
+ answeringTime: (n == null ? void 0 : n.answeringDuration) || 120,
1568
+ editingTime: (n == null ? void 0 : n.editingDuration) || 30,
1569
+ totalTime: (n == null ? void 0 : n.totalInterviewDuration) || 600,
1570
+ minimumBufferTime: (n == null ? void 0 : n.minimumTimeForNextQuestion) || 120
1571
+ }, {
1572
+ thinkingTime: p,
1573
+ answeringTime: T,
1574
+ editingTime: S,
1575
+ totalTime: ie,
1576
+ minimumBufferTime: re
1577
+ } = w;
1578
+ A(() => {
1579
+ j.current = u;
1580
+ }, [u]);
1581
+ const _ = D(!1), {
1582
+ speak: te,
1583
+ isPlaying: se,
1584
+ error: W
1585
+ } = Ue({
1586
+ config: {
1587
+ baseUrl: c,
1588
+ provider: m == null ? void 0 : m.provider
1589
+ },
1590
+ onEnd: () => {
1591
+ console.log("TTS playback completed"), _.current = !1, E();
1592
+ },
1593
+ onError: (f) => {
1594
+ console.error("TTS Error:", f), _.current || (_.current = !0, E());
1595
+ }
1596
+ }), G = D(!1), L = D(!1), {
1597
+ startRecording: z,
1598
+ stopRecording: Y,
1599
+ transcribe: K,
1600
+ isRecording: ne,
1601
+ isTranscribing: ae,
1602
+ error: M
1603
+ } = _e({
1604
+ config: {
1605
+ baseUrl: c,
1606
+ provider: o == null ? void 0 : o.provider,
1607
+ model: o == null ? void 0 : o.model,
1608
+ language: o == null ? void 0 : o.language
1609
+ },
1610
+ onStart: () => {
1611
+ console.log("STT recording started"), G.current = !1, L.current = !1;
1612
+ },
1613
+ onStop: () => {
1614
+ console.log("STT recording stopped");
1615
+ },
1616
+ onTranscriptionComplete: (f) => {
1617
+ console.log("Transcription completed:", f), h(f.transcript), L.current || (L.current = !0, E());
1618
+ },
1619
+ onError: (f) => {
1620
+ console.error("STT Error:", f), G.current || (G.current = !0, E());
1621
+ }
1622
+ }), { state: R, startQuestion: Q, nextPhase: E } = De({
1623
+ config: {
1624
+ thinkingDuration: p,
1625
+ answeringDuration: T,
1626
+ editingDuration: S,
1627
+ totalInterviewDuration: ie,
1628
+ minimumTimeForNextQuestion: re
1629
+ },
1630
+ callbacks: {
1631
+ onPhaseChange: (f) => {
1632
+ switch (console.log("Phase changed:", f), f) {
1633
+ case l.FETCHING_QUESTION:
1634
+ oe();
1635
+ break;
1636
+ case l.READING_QUESTION:
1637
+ le();
1638
+ break;
1639
+ case l.ANSWERING:
1640
+ de();
1641
+ break;
1642
+ case l.TRANSCRIBING:
1643
+ we();
1644
+ break;
1645
+ case l.SUBMITTING:
1646
+ ce();
1647
+ break;
1648
+ }
1649
+ },
1650
+ onInterviewEnd: () => {
1651
+ t == null || t();
1652
+ }
1653
+ }
1654
+ }), { execute: oe } = Pe(
1655
+ async () => {
1656
+ var P, J;
1657
+ const f = await a.generateQuestion({
1658
+ interviewId: i,
1659
+ isInterviewDone: R.totalTimeRemaining < 120,
1660
+ question: ((P = N.current) == null ? void 0 : P.question) || "",
1661
+ qnaId: ((J = N.current) == null ? void 0 : J.qna_id) || "",
1662
+ answer: j.current
1663
+ });
1664
+ return N.current = f.data, f;
1665
+ },
1666
+ {
1667
+ onSuccess: async (f) => {
1668
+ console.log("Questions fetched successfully", f), f && f.data && (h(""), d(f.data), E());
1669
+ },
1670
+ onError: (f) => {
1671
+ console.error("Failed to fetch questions:", f);
400
1672
  }
401
1673
  }
1674
+ ), ce = v(async () => {
1675
+ console.log("Answer submitted successfully"), await Be(1500), Q();
1676
+ }, [Q]), le = v(async () => {
1677
+ var f;
1678
+ if ((f = N.current) != null && f.question)
1679
+ try {
1680
+ _.current = !1, console.log("Starting TTS for question"), await te(N.current.question);
1681
+ } catch (P) {
1682
+ console.error("Failed to speak question:", P);
1683
+ }
1684
+ else
1685
+ E();
1686
+ }, []), de = v(async () => {
1687
+ console.log("Starting recording...");
1688
+ try {
1689
+ const f = T;
1690
+ console.log("🚀 ~ maxDuration:", f), await z(f);
1691
+ } catch (f) {
1692
+ console.error("Failed to start recording:", f), E();
1693
+ }
1694
+ }, [z, E]), we = v(async () => {
1695
+ console.log("Stopping recording and processing STT...");
1696
+ try {
1697
+ const f = await Y();
1698
+ console.log("Recording stopped, audio blob size:", f.size), await K(f);
1699
+ } catch (f) {
1700
+ console.error("STT processing failed:", f), !G.current && !L.current && (G.current = !0, E());
1701
+ }
1702
+ }, [Y, K, E]), ue = () => {
1703
+ const { phase: f } = R;
1704
+ switch (f) {
1705
+ case l.IDLE:
1706
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-text-center iw-py-8", children: /* @__PURE__ */ r.jsx("p", { className: "iw-text-gray-600", children: "Ready to start..." }) });
1707
+ case l.FETCHING_QUESTION:
1708
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4" });
1709
+ case l.READING_QUESTION:
1710
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-bg-indigo-50 iw-border iw-border-indigo-200 iw-rounded-lg", children: [
1711
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
1712
+ /* @__PURE__ */ r.jsx("div", { className: "iw-w-3 iw-h-3 iw-bg-indigo-500 iw-rounded-full iw-animate-pulse" }),
1713
+ /* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-indigo-700", children: se ? "Playing question audio..." : "Reading the question..." })
1714
+ ] }),
1715
+ W && /* @__PURE__ */ r.jsxs("div", { className: "iw-mt-2 iw-text-xs iw-text-red-600", children: [
1716
+ "Audio playback failed: ",
1717
+ W.message
1718
+ ] })
1719
+ ] }) });
1720
+ case l.THINKING:
1721
+ case l.ANSWERING:
1722
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: f === l.ANSWERING && /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-bg-red-50 iw-border iw-border-red-200 iw-rounded-lg", children: [
1723
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
1724
+ /* @__PURE__ */ r.jsx("div", { className: "iw-w-3 iw-h-3 iw-bg-red-500 iw-rounded-full iw-animate-pulse" }),
1725
+ /* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-red-700", children: ne ? "Recording in progress..." : "Preparing to record..." })
1726
+ ] }),
1727
+ M && /* @__PURE__ */ r.jsxs("div", { className: "iw-mt-2 iw-text-xs iw-text-red-600", children: [
1728
+ "Recording error: ",
1729
+ M.message
1730
+ ] })
1731
+ ] }) });
1732
+ case l.TRANSCRIBING:
1733
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-p-4 iw-bg-purple-50 iw-border iw-border-purple-200 iw-rounded-lg", children: [
1734
+ /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
1735
+ /* @__PURE__ */ r.jsx("div", { className: "iw-animate-spin iw-h-4 iw-w-4 iw-border-2 iw-border-purple-500 iw-border-t-transparent iw-rounded-full" }),
1736
+ /* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-purple-700", children: ae ? "Transcribing your speech..." : "Processing audio..." })
1737
+ ] }),
1738
+ M && /* @__PURE__ */ r.jsxs("div", { className: "iw-mt-2 iw-text-xs iw-text-red-600", children: [
1739
+ "Transcription error: ",
1740
+ M.message,
1741
+ M.recoverable && " (attempting to continue)"
1742
+ ] })
1743
+ ] }) });
1744
+ case l.EDITING:
1745
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsx(
1746
+ ze,
1747
+ {
1748
+ value: u,
1749
+ onChange: (P) => h(P.target.value),
1750
+ onSubmit: () => E(),
1751
+ isSubmitDisabled: !u.trim(),
1752
+ remainingTimeText: `${R.currentPhaseTimeRemaining}s remaining`
1753
+ }
1754
+ ) });
1755
+ case l.SUBMITTING:
1756
+ return /* @__PURE__ */ r.jsx("div", { className: "iw-space-y-4", children: /* @__PURE__ */ r.jsx("div", { className: "iw-p-4 iw-bg-green-50 iw-border iw-border-green-200 iw-rounded-lg", children: /* @__PURE__ */ r.jsxs("div", { className: "iw-flex iw-items-center iw-space-x-2", children: [
1757
+ /* @__PURE__ */ r.jsx("div", { className: "iw-animate-spin iw-h-4 iw-w-4 iw-border-2 iw-border-green-500 iw-border-t-transparent iw-rounded-full" }),
1758
+ /* @__PURE__ */ r.jsx("span", { className: "iw-text-sm iw-font-medium iw-text-green-700", children: "Submitting your answer..." })
1759
+ ] }) }) });
1760
+ case l.COMPLETED:
1761
+ return /* @__PURE__ */ r.jsxs("div", { className: "iw-text-center iw-py-8", children: [
1762
+ /* @__PURE__ */ r.jsx("div", { className: "iw-mb-4", children: /* @__PURE__ */ r.jsx(
1763
+ "svg",
1764
+ {
1765
+ className: "iw-w-16 iw-h-16 iw-mx-auto iw-text-green-500",
1766
+ fill: "none",
1767
+ stroke: "currentColor",
1768
+ viewBox: "0 0 24 24",
1769
+ children: /* @__PURE__ */ r.jsx(
1770
+ "path",
1771
+ {
1772
+ strokeLinecap: "round",
1773
+ strokeLinejoin: "round",
1774
+ strokeWidth: 2,
1775
+ d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
1776
+ }
1777
+ )
1778
+ }
1779
+ ) }),
1780
+ /* @__PURE__ */ r.jsx("h3", { className: "iw-text-xl iw-font-bold iw-text-gray-900 iw-mb-2", children: "Interview Complete!" }),
1781
+ /* @__PURE__ */ r.jsx("p", { className: "iw-text-gray-600", children: "Thank you for your time. Your answers have been recorded." })
1782
+ ] });
1783
+ default:
1784
+ return null;
1785
+ }
1786
+ };
1787
+ return /* @__PURE__ */ r.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ r.jsxs(
1788
+ "div",
1789
+ {
1790
+ className: ` iw-max-w-3xl iw-mx-auto iw-space-y-4 iw-py-8 ${e}`,
1791
+ children: [
1792
+ R.phase !== l.IDLE && R.phase !== l.COMPLETED && /* @__PURE__ */ r.jsx(
1793
+ Ye,
1794
+ {
1795
+ question: g,
1796
+ isLoading: R.phase === l.FETCHING_QUESTION
1797
+ }
1798
+ ),
1799
+ /* @__PURE__ */ r.jsx("div", { className: "iw-bg-white iw-rounded-lg iw-shadow-md iw-p-6", children: ue() }),
1800
+ /* @__PURE__ */ r.jsx(
1801
+ He,
1802
+ {
1803
+ state: R,
1804
+ defaultTimers: {
1805
+ thinking: p,
1806
+ answering: T,
1807
+ editing: S
1808
+ }
1809
+ }
1810
+ ),
1811
+ x && (R.phase === l.THINKING || R.phase === l.ANSWERING || R.phase === l.EDITING) && /* @__PURE__ */ r.jsx($, { onClick: E, children: "Next Phase" }),
1812
+ !x && /* @__PURE__ */ r.jsx("div", { className: "iw-text-center iw-py-12 w-full", children: /* @__PURE__ */ r.jsx(
1813
+ $,
1814
+ {
1815
+ className: "w-full",
1816
+ style: { backgroundColor: s },
1817
+ onClick: () => {
1818
+ Q(), k(!0);
1819
+ },
1820
+ children: "Start Interview"
1821
+ }
1822
+ ) })
1823
+ ]
1824
+ }
1825
+ ) });
1826
+ }, Je = ({
1827
+ interviewId: i,
1828
+ title: t = "Interview",
1829
+ onInterviewEnd: e,
1830
+ className: a = ""
1831
+ }) => {
1832
+ const [s, c] = y(!1), [n, o] = y(!0), m = D(null);
1833
+ if (!s)
1834
+ return /* @__PURE__ */ r.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ r.jsx(
1835
+ Se,
1836
+ {
1837
+ isOpen: n,
1838
+ onStart: () => {
1839
+ console.log("Permissions granted, starting interview"), c(!0), o(!1);
1840
+ }
1841
+ }
1842
+ ) });
1843
+ const g = () => {
1844
+ e == null || e();
1845
+ };
1846
+ return /* @__PURE__ */ r.jsx("div", { className: "interview-widget-container", children: /* @__PURE__ */ r.jsx(
1847
+ "div",
1848
+ {
1849
+ ref: m,
1850
+ className: `iw-flex iw-flex-col iw-rounded-xl iw-shadow-lg iw-overflow-hidden iw-h-[calc(100vh-1rem)] ${a}`,
1851
+ children: /* @__PURE__ */ r.jsxs("div", { className: " iw-h-full iw-flex iw-flex-col", children: [
1852
+ /* @__PURE__ */ r.jsx(je, { title: t, onExit: g }),
1853
+ /* @__PURE__ */ r.jsx(
1854
+ Ke,
1855
+ {
1856
+ interviewId: i,
1857
+ className: a,
1858
+ onComplete: e || (() => {
1859
+ })
1860
+ }
1861
+ )
1862
+ ] })
1863
+ }
402
1864
  ) });
403
1865
  };
404
1866
  typeof window < "u" && (window.InterviewWidget = {
405
- InterviewWidget: W
1867
+ InterviewWidget: Je,
1868
+ InterviewWidgetProvider: Ne
406
1869
  });
407
1870
  export {
408
- W as InterviewWidget,
409
- W as default
1871
+ Je as InterviewWidget,
1872
+ Ne as InterviewWidgetProvider,
1873
+ Je as default
410
1874
  };