@sapia-ai/chatbot-v3 1.1.1 → 1.3.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.
Files changed (67) hide show
  1. package/dist/{EmbeddedVideoPlayer-COUZHpPa.js → EmbeddedVideoPlayer-DTzRqNcQ.js} +176 -186
  2. package/dist/{Preview-wPnYtccF.js → Preview-Dd7KyhMk.js} +3 -3
  3. package/dist/api/client.d.ts +10 -6
  4. package/dist/api/places.d.ts +33 -0
  5. package/dist/api/types/messages.d.ts +35 -4
  6. package/dist/api/types/responses.d.ts +20 -17
  7. package/dist/api.js +2 -2
  8. package/dist/core/bubbles/cards.d.ts +14 -0
  9. package/dist/core/bubbles/convert.d.ts +24 -2
  10. package/dist/core/bubbles/counters.d.ts +10 -0
  11. package/dist/core/bubbles/types.d.ts +21 -1
  12. package/dist/core/constants.d.ts +31 -0
  13. package/dist/core/events.d.ts +7 -0
  14. package/dist/core/internalUser.d.ts +13 -0
  15. package/dist/core/interview.d.ts +26 -9
  16. package/dist/core/persistence.d.ts +3 -0
  17. package/dist/core/redirect.d.ts +2 -0
  18. package/dist/core/store.d.ts +22 -9
  19. package/dist/core/validation/wordCount.d.ts +1 -0
  20. package/dist/{dist-Bwlks_W8.js → dist-waE-4cub.js} +3 -3
  21. package/dist/embed/compat.d.ts +1 -1
  22. package/dist/embed/createChatbot.d.ts +6 -0
  23. package/dist/{fix-webm-duration-QAy9T6AR.js → fix-webm-duration-IniZA6tF.js} +2 -2
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.js +6218 -5384
  26. package/dist/{jsx-runtime-24G8w2Bf.js → jsx-runtime-DN_m6Qdv.js} +2 -2
  27. package/dist/{messages-DCvBcspv.js → messages-C00e82NS.js} +44 -37
  28. package/dist/places-CT6PNW7B.js +52 -0
  29. package/dist/react/AnswerInput.d.ts +16 -5
  30. package/dist/react/SapiaChatbot.d.ts +7 -1
  31. package/dist/react/bubbleViewModel.d.ts +38 -11
  32. package/dist/react/strings.d.ts +46 -10
  33. package/dist/react/usePlacesSuggestions.d.ts +16 -0
  34. package/dist/{react-Bw5AugJc.js → react-A0_ZwPyM.js} +3 -3
  35. package/dist/{react-DEF8h8hc.js → react-BDGt_WsZ.js} +3 -3
  36. package/dist/{react-DDjfkpOE.js → react-B_YNH2g9.js} +3 -3
  37. package/dist/{react-D8hV9uow.js → react-ByP48xLV.js} +3 -3
  38. package/dist/{react-DPFikgTM.js → react-C9oBRlX8.js} +3 -3
  39. package/dist/{react-qa12DkXH.js → react-D5yWOfXN.js} +3 -3
  40. package/dist/{react-DOgLiyZi.js → react-DkQKleWD.js} +2 -2
  41. package/dist/{react-y4vaW3OH.js → react-d-THpGrV.js} +3 -3
  42. package/dist/{react-BjO903pN.js → react-euSb4sIX.js} +3 -3
  43. package/dist/ui/chat/ActionDock/ActionDock.d.ts +15 -0
  44. package/dist/ui/chat/ChatBubble/ChatBubble.d.ts +10 -3
  45. package/dist/ui/chat/ChatLog/ChatLog.d.ts +9 -4
  46. package/dist/ui/chat/EditBanner/EditBanner.d.ts +9 -3
  47. package/dist/ui/chat/HintDisclosure/HintDisclosure.d.ts +20 -0
  48. package/dist/ui/chat/SummaryCard/SummaryCard.d.ts +18 -23
  49. package/dist/ui/chat/types.d.ts +18 -2
  50. package/dist/ui/constants.d.ts +5 -0
  51. package/dist/ui/hooks/usePreventPaste.d.ts +17 -0
  52. package/dist/ui/inputs/LocationAnswerInput/LocationAnswerInput.d.ts +34 -0
  53. package/dist/ui/inputs/PhoneAnswerInput/PhoneAnswerInput.d.ts +5 -2
  54. package/dist/ui/inputs/SliderInput/SliderInput.d.ts +1 -2
  55. package/dist/ui/inputs/TextAnswerInput/TextAnswerInput.d.ts +38 -11
  56. package/dist/ui/media/EmbeddedVideo/EmbeddedVideoPlayer.d.ts +1 -1
  57. package/dist/ui/primitives/MarkdownText/MarkdownText.d.ts +24 -0
  58. package/dist/ui/shell/CohortClosedScreen/CohortClosedScreen.d.ts +9 -0
  59. package/dist/ui/shell/CopyLinkButton/CopyLinkButton.d.ts +10 -3
  60. package/dist/ui/shell/DoneScreen/DoneScreen.d.ts +4 -1
  61. package/dist/ui/shell/Header/AutoScrollTitle.d.ts +15 -0
  62. package/dist/ui/shell/Header/Header.d.ts +12 -0
  63. package/dist/ui/shell/Header/useAutoScrollTitle.d.ts +16 -0
  64. package/dist/ui/shell/TerminalMessageScreen/TerminalMessageScreen.d.ts +10 -0
  65. package/dist/ui/shell/WidgetRoot/themeVariables.d.ts +8 -0
  66. package/dist-umd/sapia-chatbot.umd.js +309 -309
  67. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { S as e } from "./messages-DCvBcspv.js";
1
+ import { C as e } from "./messages-C00e82NS.js";
2
2
  //#region ../../node_modules/.pnpm/react@19.2.7/node_modules/react/cjs/react-jsx-runtime.production.js
3
3
  var t = /* @__PURE__ */ e(((e) => {
4
4
  var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment");
@@ -21,4 +21,4 @@ var t = /* @__PURE__ */ e(((e) => {
21
21
  //#endregion
22
22
  export { n as t };
23
23
 
24
- //# sourceMappingURL=jsx-runtime-24G8w2Bf.js.map
24
+ //# sourceMappingURL=jsx-runtime-DN_m6Qdv.js.map
@@ -1825,17 +1825,15 @@ async function* In(e) {
1825
1825
  //#endregion
1826
1826
  //#region src/api/types/responses.ts
1827
1827
  var $ = /* @__PURE__ */ function(e) {
1828
- return e.RUN_STARTED = "RUN_STARTED", e.STATE_SNAPSHOT = "STATE_SNAPSHOT", e.ASSESSMENT_SUMMARY = "ASSESSMENT_SUMMARY", e.TEXT_MESSAGE_START = "TEXT_MESSAGE_START", e.TEXT_MESSAGE_CONTENT = "TEXT_MESSAGE_CONTENT", e.TEXT_MESSAGE_END = "TEXT_MESSAGE_END", e.CUSTOM = "CUSTOM", e.RUN_FINISHED = "RUN_FINISHED", e.RUN_ERROR = "RUN_ERROR", e;
1829
- }({}), Ln = /* @__PURE__ */ function(e) {
1830
- return e.PENDING = "PENDING", e.CLICKED = "CLICKED", e;
1831
- }({}), Rn = "next/stream error", zn = (...e) => globalThis.fetch(...e), Bn = class {
1828
+ return e.RUN_STARTED = "RUN_STARTED", e.STATE_SNAPSHOT = "STATE_SNAPSHOT", e.ASSESSMENT_SUMMARY = "ASSESSMENT_SUMMARY", e.ASSESSMENT_LINK = "ASSESSMENT_LINK", e.TEXT_MESSAGE_START = "TEXT_MESSAGE_START", e.TEXT_MESSAGE_CONTENT = "TEXT_MESSAGE_CONTENT", e.TEXT_MESSAGE_END = "TEXT_MESSAGE_END", e.CUSTOM = "CUSTOM", e.RUN_FINISHED = "RUN_FINISHED", e.RUN_ERROR = "RUN_ERROR", e;
1829
+ }({}), Ln = "next/stream error", Rn = (...e) => globalThis.fetch(...e), zn = class {
1832
1830
  constructor(e) {
1833
1831
  var t, n, r;
1834
1832
  this.baseUrl = Pn(e), this.baseHeaders = {
1835
1833
  [wn]: e.appId,
1836
1834
  [Tn]: En,
1837
1835
  [Dn]: "1.0"
1838
- }, this.http = (t = e.httpClient) == null ? Q.create({ headers: this.baseHeaders }) : t, this.putImpl = (n = e.putImpl) == null ? Q.put : n, this.fetchImpl = (r = e.fetchImpl) == null ? zn : r;
1836
+ }, this.http = (t = e.httpClient) == null ? Q.create({ headers: this.baseHeaders }) : t, this.putImpl = (n = e.putImpl) == null ? Q.put : n, this.fetchImpl = (r = e.fetchImpl) == null ? Rn : r;
1839
1837
  }
1840
1838
  fiTokenHeaders() {
1841
1839
  return this.fiToken ? { [this.fiToken.name]: this.fiToken.value } : {};
@@ -1847,8 +1845,8 @@ var $ = /* @__PURE__ */ function(e) {
1847
1845
  let t = await this.http.post(`${this.baseUrl}/${e}/start/ats`);
1848
1846
  return this.fiToken = t.data.fiToken, t.data;
1849
1847
  }
1850
- async nextStream(e, t, n, r) {
1851
- let i = await this.fetchImpl(`${this.baseUrl}/${e}/next/stream`, {
1848
+ async nextStream(e, t, n) {
1849
+ let r = await this.fetchImpl(`${this.baseUrl}/${e}/next/stream`, {
1852
1850
  method: "POST",
1853
1851
  headers: {
1854
1852
  ...this.baseHeaders,
@@ -1856,40 +1854,45 @@ var $ = /* @__PURE__ */ function(e) {
1856
1854
  "Content-Type": "application/json",
1857
1855
  Accept: "text/event-stream"
1858
1856
  },
1859
- body: JSON.stringify({
1860
- candidateResponse: t,
1861
- summaryContinued: r == null ? void 0 : r.summaryContinued
1862
- }),
1857
+ body: JSON.stringify({ candidateResponse: t }),
1863
1858
  signal: n.signal
1864
1859
  });
1865
- if (!i.ok || !i.body) throw Error(`next/stream failed: ${i.status}`);
1866
- let a, o = !1;
1867
- for await (let e of In(i.body)) {
1860
+ if (!r.ok || !r.body) throw Error(`next/stream failed: ${r.status}`);
1861
+ let i, a = !1;
1862
+ for await (let e of In(r.body)) {
1868
1863
  let t = JSON.parse(e.data);
1869
1864
  switch (t.type) {
1870
1865
  case $.RUN_ERROR:
1871
- var s;
1872
- throw Error((s = t.message) == null ? Rn : s);
1866
+ var o;
1867
+ throw Error((o = t.message) == null ? Ln : o);
1873
1868
  case $.STATE_SNAPSHOT:
1874
- var c, l;
1875
- (c = t.snapshot) != null && c.question && ((l = n.onMeta) == null || l.call(n, Vn(t.snapshot.question)));
1869
+ var s;
1870
+ if ((s = t.snapshot) != null && s.question) {
1871
+ var c, l;
1872
+ let e = t.snapshot.question;
1873
+ (c = n.onMeta) == null || c.call(n, Bn(e), (l = e.messageId) == null ? e._id : l);
1874
+ }
1876
1875
  break;
1877
1876
  case $.ASSESSMENT_SUMMARY:
1878
1877
  var u;
1879
1878
  t.summary && ((u = n.onSummary) == null || u.call(n, t.summary));
1880
1879
  break;
1881
- case $.TEXT_MESSAGE_CONTENT:
1880
+ case $.ASSESSMENT_LINK:
1882
1881
  var d;
1883
- t.delta && n.onDelta(t.delta, (d = t.messageId) == null ? "" : d);
1882
+ t.url && ((d = n.onLink) == null || d.call(n, t.url));
1883
+ break;
1884
+ case $.TEXT_MESSAGE_CONTENT:
1885
+ var f;
1886
+ t.delta && n.onDelta(t.delta, (f = t.messageId) == null ? "" : f);
1884
1887
  break;
1885
1888
  case $.RUN_FINISHED:
1886
- a = t.result, o = !0;
1889
+ i = t.result, a = !0;
1887
1890
  break;
1888
1891
  }
1889
- if (o) break;
1892
+ if (a) break;
1890
1893
  }
1891
- if (!o) throw Error("next/stream ended without a RUN_FINISHED frame");
1892
- return a != null && a.fiToken && (this.fiToken = a.fiToken), a;
1894
+ if (!a) throw Error("next/stream ended without a RUN_FINISHED frame");
1895
+ return i != null && i.fiToken && (this.fiToken = i.fiToken), i;
1893
1896
  }
1894
1897
  async editAnswer(e, t) {
1895
1898
  return (await this.http.post(`${this.baseUrl}/${e}/edit-answer`, { editAnswerInput: t }, { headers: this.fiTokenHeaders() })).data;
@@ -1932,7 +1935,7 @@ var $ = /* @__PURE__ */ function(e) {
1932
1935
  async getTranslation(e) {
1933
1936
  return (await this.http.get(`${this.baseUrl}/translation/${e}`)).data;
1934
1937
  }
1935
- }, Vn = (e) => {
1938
+ }, Bn = (e) => {
1936
1939
  var t;
1937
1940
  return {
1938
1941
  _id: e._id,
@@ -1949,30 +1952,34 @@ var $ = /* @__PURE__ */ function(e) {
1949
1952
  component: e.component
1950
1953
  }))
1951
1954
  };
1952
- }, Hn = /* @__PURE__ */ function(e) {
1955
+ }, Vn = /* @__PURE__ */ function(e) {
1953
1956
  return e.MAX_TEXT_LENGTH = "maxTextLength", e.MIN_TEXT_LENGTH = "minTextLength", e.RECOMMENDED_TEXT_LENGTH = "recommendedTextLength", e.MAX_VOICE_SECONDS = "maxVoiceSeconds", e.MIN_VOICE_SECONDS = "minVoiceSeconds", e.RECOMMENDED_VOICE_SECONDS = "recommendedVoiceSeconds", e;
1954
- }({}), Un = /* @__PURE__ */ function(e) {
1957
+ }({}), Hn = /* @__PURE__ */ function(e) {
1955
1958
  return e.AGENT = "AGENT", e.CANDIDATE = "CANDIDATE", e;
1959
+ }({}), Un = /* @__PURE__ */ function(e) {
1960
+ return e.HINT = "HINT", e.FTQ = "FTQ", e.MCQ = "MCQ", e.VOICE = "VOICE", e.VIDEO = "VIDEO", e.SLIDER = "SLIDER", e.DROPDOWN = "DROPDOWN", e.BGQ = "BUTTON_GROUP_QUESTION", e.BREAK = "BREAK", e;
1956
1961
  }({}), Wn = /* @__PURE__ */ function(e) {
1957
- return e.HINT = "HINT", e.FTQ = "FTQ", e.MCQ = "MCQ", e.VOICE = "VOICE", e.VIDEO = "VIDEO", e.SLIDER = "SLIDER", e.DROPDOWN = "DROPDOWN", e.BGQ = "BUTTON_GROUP_QUESTION", e;
1958
- }({}), Gn = /* @__PURE__ */ function(e) {
1959
1962
  return e.TEXT = "TEXT", e.VOICE = "VOICE", e.VIDEO = "VIDEO", e.SLIDER = "SLIDER", e;
1960
- }({}), Kn = /* @__PURE__ */ function(e) {
1963
+ }({}), Gn = /* @__PURE__ */ function(e) {
1961
1964
  return e.GENERAL_PY = "GENERAL_PY", e.CUSTOMER_SATISFACTION = "CUSTOMER_SATISFACTION", e.PII = "PII", e.SENSITIVE = "SENSITIVE", e.DISPLAY_IN_TI = "DISPLAY_IN_TI", e.HEXACO_PERSONALITY_TEST = "HEXACO_PERSONALITY_TEST", e;
1962
- }({}), qn = /* @__PURE__ */ function(e) {
1965
+ }({}), Kn = /* @__PURE__ */ function(e) {
1963
1966
  return e.FULL_NAME = "fullName", e.FIRST_NAME = "first_name", e.LAST_NAME = "last_name", e.EMAIL = "email", e.PHONE_NUMBER = "phoneNumber", e.LOCATION = "location", e;
1964
- }({}), Jn = /* @__PURE__ */ function(e) {
1967
+ }({}), qn = /* @__PURE__ */ function(e) {
1965
1968
  return e.TEST_CAMERA = "test_camera", e;
1966
- }({}), Yn = /* @__PURE__ */ function(e) {
1969
+ }({}), Jn = /* @__PURE__ */ function(e) {
1967
1970
  return e.PRIMARY = "PRIMARY", e.SECONDARY = "SECONDARY", e.DEFAULT = "DEFAULT", e;
1968
- }({}), Xn = /* @__PURE__ */ function(e) {
1971
+ }({}), Yn = /* @__PURE__ */ function(e) {
1969
1972
  return e.FI_ATS_ASSESSMENT_ORDER_COMPLETED = "FI_ATS_ASSESSMENT_ORDER_COMPLETED", e.FI_ASSESSMENT_STARTED = "FI_ASSESSMENT_STARTED", e.FI_ASSESSMENT_PII_SAVED = "FI_ASSESSMENT_PII_SAVED", e.FI_ASSESSMENT_PII_COMPLETED = "FI_ASSESSMENT_PII_COMPLETED", e.FI_ASSESSMENT_INPROGRESS = "FI_ASSESSMENT_INPROGRESS", e.FI_ASSESSMENT_COMPLETED = "FI_ASSESSMENT_COMPLETED", e.FI_ASSESSMENT_ENDED = "FI_ASSESSMENT_ENDED", e.FI_ASSESSMENT_DROPPED_OUT = "FI_ASSESSMENT_DROPPED_OUT", e.FI_PREDICTION_STARTED = "FI_PREDICTION_STARTED", e.FI_PREDICTION_COMPLETED = "FI_PREDICTION_COMPLETED", e.FI_ASSESSMENT_DUPLICATED = "FI_ASSESSMENT_DUPLICATED", e;
1973
+ }({}), Xn = /* @__PURE__ */ function(e) {
1974
+ return e.SMS_CONSENT_QUESTION = "SMS_CONSENT_QUESTION_MESSAGE", e.SMS_CONSENT_ANSWER = "SMS_CONSENT_ANSWER_MESSAGE", e.TERMS_CONSENT_QUESTION = "TERMS_AND_CONDITIONS_CONSENT_QUESTION_MESSAGE", e.TERMS_CONSENT_ANSWER = "TERMS_AND_CONDITIONS_CONSENT_ANSWER_MESSAGE", e.SUBMIT_QUESTION = "SUBMIT_QUESTION_MESSAGE", e.SUBMIT_ANSWER = "SUBMIT_ANSWER_MESSAGE", e.RATING_CUSTOMER_SATISFACTION_QUESTION = "RATING_CUSTOMER_SATISFACTION_QUESTION_MESSAGE", e.RATING_CUSTOMER_SATISFACTION_ANSWER = "RATING_CUSTOMER_SATISFACTION_ANSWER_MESSAGE", e.FEEDBACK_CUSTOMER_SATISFACTION_QUESTION = "FEEDBACK_CUSTOMER_SATISFACTION_QUESTION_MESSAGE", e.FEEDBACK_CUSTOMER_SATISFACTION_ANSWER = "FEEDBACK_CUSTOMER_SATISFACTION_ANSWER_MESSAGE", e;
1970
1975
  }({}), Zn = /* @__PURE__ */ function(e) {
1971
- return e.TEXT = "Text", e.VOICE_PLAYER = "VoicePlayer", e.VIDEO_PLAYER = "VideoPlayer", e.SLIDER = "Slider", e;
1976
+ return e.TEXT = "Text", e.VOICE_PLAYER = "VoicePlayer", e.VIDEO_PLAYER = "VideoPlayer", e.SLIDER = "Slider", e.ASSESSMENT_SUMMARY = "AssessmentSummary", e.COPY_LINK = "CopyLink", e;
1972
1977
  }({}), Qn = /* @__PURE__ */ function(e) {
1978
+ return e.ASSESSMENT_SUMMARY = "{assessment.summary}", e.ASSESSMENT_LINK = "{assessment.link}", e;
1979
+ }({}), $n = /* @__PURE__ */ function(e) {
1973
1980
  return e.HINT = "Hint", e.QUESTION = "Question", e;
1974
1981
  }({});
1975
1982
  //#endregion
1976
- export { s as C, o as S, Mn as _, Qn as a, Pn as b, qn as c, Jn as d, Bn as f, An as g, jn as h, Gn as i, Wn as l, Ln as m, Yn as n, Un as o, $ as p, Zn as r, Kn as s, Xn as t, Hn as u, On as v, l as w, Nn as x, kn as y };
1983
+ export { o as C, Nn as S, l as T, An as _, Wn as a, kn as b, Hn as c, Un as d, Vn as f, jn as g, $ as h, Qn as i, Gn as l, zn as m, Jn as n, Xn as o, qn as p, Zn as r, $n as s, Yn as t, Kn as u, Mn as v, s as w, Pn as x, On as y };
1977
1984
 
1978
- //# sourceMappingURL=messages-DCvBcspv.js.map
1985
+ //# sourceMappingURL=messages-C00e82NS.js.map
@@ -0,0 +1,52 @@
1
+ //#region src/api/places.ts
2
+ var e = "AIzaSyCWSAROQu-uLQmQ-fq0ip7aXHpBjPESaQQ", t = "https://places.googleapis.com/v1", n = `${t}/places:autocomplete`, r = `${t}/places`, i = "X-Goog-Api-Key", a = "X-Goog-FieldMask", o = "Content-Type", s = "application/json", c = [
3
+ "suggestions.placePrediction.placeId",
4
+ "suggestions.placePrediction.text",
5
+ "suggestions.placePrediction.structuredFormat.mainText",
6
+ "suggestions.placePrediction.structuredFormat.secondaryText"
7
+ ].join(","), l = [
8
+ "id",
9
+ "formattedAddress",
10
+ "location",
11
+ "displayName"
12
+ ].join(","), u = "en", d = async (t, n, { apiKey: r, signal: c, fetchImpl: l }, u) => {
13
+ let d = await (l == null ? globalThis.fetch : l)(t, {
14
+ method: u ? "POST" : "GET",
15
+ headers: {
16
+ [i]: r == null ? e : r,
17
+ [a]: n,
18
+ ...u ? { [o]: s } : {}
19
+ },
20
+ body: u ? JSON.stringify(u) : void 0,
21
+ signal: c
22
+ });
23
+ if (!d.ok) throw Error(`places request failed: ${d.status}`);
24
+ return await d.json();
25
+ }, f = async (e, t = {}) => {
26
+ var r;
27
+ return e.trim() ? ((r = (await d(n, c, t, {
28
+ input: e,
29
+ languageCode: u
30
+ })).suggestions) == null ? [] : r).map(({ placePrediction: e }) => {
31
+ var t, n, r, i;
32
+ return {
33
+ placeId: e.placeId,
34
+ description: e.text.text,
35
+ mainText: (t = (n = e.structuredFormat) == null || (n = n.mainText) == null ? void 0 : n.text) == null ? e.text.text : t,
36
+ secondaryText: (r = (i = e.structuredFormat) == null || (i = i.secondaryText) == null ? void 0 : i.text) == null ? "" : r
37
+ };
38
+ }) : [];
39
+ }, p = async (e, t = {}) => {
40
+ let n = await d(`${r}/${e.placeId}`, l, t);
41
+ return {
42
+ address: n.formattedAddress || e.description,
43
+ coordinate: n.location ? {
44
+ lat: n.location.latitude,
45
+ lng: n.location.longitude
46
+ } : null
47
+ };
48
+ };
49
+ //#endregion
50
+ export { p as fetchPlaceAnswer, f as fetchPlaceSuggestions };
51
+
52
+ //# sourceMappingURL=places-CT6PNW7B.js.map
@@ -1,20 +1,31 @@
1
1
  import { InterviewEngine } from '../core/interview';
2
2
  import { Region } from '../api/config';
3
- import { CurrentInputKind, EditingDraft, TextRules } from './bubbleViewModel';
3
+ import { CurrentInputKind, EditingDraft, WordCountRule } from './bubbleViewModel';
4
4
  import { UiStrings } from './strings';
5
5
  export type AnswerInputProps = {
6
6
  engine: InterviewEngine;
7
+ /** Scopes the "don't show me this again" opt-out to this interview. */
8
+ assessmentId: string;
7
9
  kind: CurrentInputKind;
8
10
  disabled: boolean;
9
- textRules: TextRules;
11
+ wordCountRule: WordCountRule;
10
12
  strings: UiStrings;
11
13
  candidateCountryCode?: string;
12
14
  region: Region;
15
+ /** Host's own Google Places key for the location question; defaults to the bundled key. */
16
+ placesApiKey?: string;
13
17
  /** Max video answer length in seconds (video questions). */
14
18
  maxVideoSeconds?: number;
15
19
  /** Stored answer to open the composer on when re-editing. */
16
20
  draft?: EditingDraft;
17
- /** Called when the candidate pastes into a text answer (AGC paste log). */
18
- onPaste?: () => void;
21
+ /** Permits paste in the free-text composer (ALLOW_PASTE tag or an internal session). */
22
+ allowPaste: boolean;
23
+ /** The optional post-interview feedback comment: no word rules, and an empty send is a skip. */
24
+ isFeedbackComment: boolean;
25
+ /** Called for each blocked paste attempt (AGC paste log). */
26
+ onBlockedPaste?: () => void;
27
+ /** Fullscreen composer state, owned by the shell so the transcript it covers can go inert. */
28
+ expanded: boolean;
29
+ onExpandedChange: (expanded: boolean) => void;
19
30
  };
20
- export declare const AnswerInput: ({ engine, kind, disabled, textRules, strings, candidateCountryCode, region, maxVideoSeconds, draft, onPaste, }: AnswerInputProps) => import("react").JSX.Element;
31
+ export declare const AnswerInput: ({ engine, assessmentId, kind, disabled, wordCountRule, strings, candidateCountryCode, region, placesApiKey, maxVideoSeconds, draft, allowPaste, isFeedbackComment, onBlockedPaste, expanded, onExpandedChange, }: AnswerInputProps) => import("react").JSX.Element;
@@ -11,8 +11,14 @@ export type SapiaChatbotProps = {
11
11
  apiOrigin?: string;
12
12
  theme?: Theme;
13
13
  showHeader?: boolean;
14
+ /** Internal session (Sapia staff / QA): permits paste on every question. */
15
+ isInternalUser?: boolean;
14
16
  /** Interview language override (e.g. "fr"); defaults to the browser language. */
15
17
  language?: string;
18
+ /** Absolute http(s) URL offered as a "continue" CTA once the interview ends. */
19
+ redirectUrl?: string;
20
+ /** Host's own Google Places key for the location question; defaults to the bundled key. */
21
+ placesApiKey?: string;
16
22
  /** Receives every widget event; or pass an emitter via createChatbot. */
17
23
  onEvent?: ChatbotEventHandler;
18
24
  /** @internal used by embed/createChatbot to share its emitter. */
@@ -20,4 +26,4 @@ export type SapiaChatbotProps = {
20
26
  /** @internal streaming transport override (mock SSE for the demo / tests). */
21
27
  fetchImpl?: typeof fetch;
22
28
  };
23
- export declare const SapiaChatbot: ({ env, region, appId, assessmentId, apiOrigin, theme, showHeader, language, onEvent, emitter, fetchImpl, }: SapiaChatbotProps) => import("react").JSX.Element;
29
+ export declare const SapiaChatbot: ({ env, region, appId, assessmentId, apiOrigin, theme, showHeader, isInternalUser, language, redirectUrl, placesApiKey, onEvent, emitter, fetchImpl, }: SapiaChatbotProps) => import("react").JSX.Element;
@@ -1,15 +1,27 @@
1
1
  import { MessageBubble } from '../core/bubbles/types';
2
2
  import { ChatLogItem } from '../ui/chat/types';
3
+ /** Interview-wide conditions that freeze answers the candidate has already given. */
4
+ export type AnswerLocks = {
5
+ /** Terms accepted: consent is tied to the identity on file, so PII and SMS consent freeze. */
6
+ termsAccepted: boolean;
7
+ /** The final submit is through: the whole transcript is the submission, so nothing is editable. */
8
+ submitted: boolean;
9
+ };
3
10
  /** Per-card eyebrow + optional dark badge, keyed by agent bubble id. */
4
11
  export type QuestionCard = {
5
- label: string;
12
+ label?: string;
6
13
  badge?: string;
7
14
  };
8
- export declare const mapBubblesToChatItems: (bubbles: MessageBubble[], cards?: Map<string, QuestionCard>, streamingBubbleId?: string) => ChatLogItem[];
9
- export type TextRules = {
10
- minLength?: number;
11
- maxLength?: number;
12
- recommendedLength?: number;
15
+ export declare const mapBubblesToChatItems: (bubbles: MessageBubble[], cards?: Map<string, QuestionCard>, locks?: AnswerLocks, streamingBubbleId?: string) => ChatLogItem[];
16
+ /**
17
+ * Word bounds for the current question. The rule names say "TextLength" but the
18
+ * values are word counts — the backend interpolates them into the question text
19
+ * the candidate reads as "between {recommended} and {max} words".
20
+ */
21
+ export type WordCountRule = {
22
+ min?: number;
23
+ recommend?: number;
24
+ max?: number;
13
25
  };
14
26
  /**
15
27
  * The agent bubble whose answer the bottom input targets: the question under
@@ -38,10 +50,14 @@ export type QuestionCardLabels = {
38
50
  };
39
51
  /**
40
52
  * Marks every agent question turn as a card (matching the prototype's permanent
41
- * question styling); conversational agent turns stay plain. Every card shows
42
- * "Question n of N" (choice questions included, matching the reference); video
43
- * adds a media badge. Cards persist through an edit — the docked edit banner, not a
44
- * restyled transcript, is what signals edit mode.
53
+ * question styling); conversational agent turns stay plain. Video adds a media badge.
54
+ * Cards persist through an edit — the docked edit banner, not a restyled transcript, is what
55
+ * signals edit mode.
56
+ *
57
+ * Only normal questions carry "Question n of N": consent gates, PII fields, the submit button
58
+ * and the post-submit feedback questions are not part of the count the BE totals in
59
+ * `numOfNormalQuestion`, so numbering them would both misname them and overrun the total. They
60
+ * stay cards — they still need an answer — just without the eyebrow.
45
61
  */
46
62
  export declare const buildQuestionCards: (bubbles: MessageBubble[], total: number, labels: QuestionCardLabels) => Map<string, QuestionCard>;
47
63
  /**
@@ -61,6 +77,17 @@ export declare enum CurrentInputKind {
61
77
  VIDEO = "video"
62
78
  }
63
79
  export declare const currentInputKind: (bubbles: MessageBubble[], editingQuestionId?: string) => CurrentInputKind;
64
- export declare const currentTextRules: (bubbles: MessageBubble[], editingQuestionId?: string) => TextRules;
80
+ export declare const currentWordCountRule: (bubbles: MessageBubble[], editingQuestionId?: string) => WordCountRule;
81
+ /**
82
+ * Whether the question the composer currently targets opts out of the paste block. Reads the same
83
+ * bubble as the other composer selectors, so re-editing an earlier answer picks up that question's
84
+ * tag rather than the newest question's.
85
+ */
86
+ export declare const currentQuestionAllowsPaste: (bubbles: MessageBubble[], editingQuestionId?: string) => boolean;
87
+ /**
88
+ * Whether the composer currently targets the optional post-interview feedback comment. Sending
89
+ * nothing is a valid answer there, and it carries none of the word-count rules an FTQ does.
90
+ */
91
+ export declare const isFeedbackCommentQuestion: (bubbles: MessageBubble[], editingQuestionId?: string) => boolean;
65
92
  /** Max video answer length in seconds (legacy reuses the voice-seconds rule). */
66
93
  export declare const currentMaxVideoSeconds: (bubbles: MessageBubble[], editingQuestionId?: string) => number;
@@ -25,29 +25,36 @@ export declare const buildStrings: (t: Translator) => {
25
25
  welcomePause: string;
26
26
  welcomeNext: string;
27
27
  welcomeReassurance: string;
28
- /** Total-questions meta, e.g. "3 questions". */
29
- summaryQuestions: (count: number) => string;
30
- /** Estimated-time meta, e.g. "~9 min". */
31
- summaryMinutes: (minutes: number) => string;
32
- /** Uppercase label for the summary total panel, e.g. "Total". */
28
+ /** Uppercase label for the summary total panel, e.g. "TOTAL". */
33
29
  summaryTotal: string;
30
+ /** Total line, e.g. "10 Questions (~ 30 minutes)". */
31
+ summaryCount: (totalQuestions: number, estimatedMinutes: number) => string;
32
+ summaryPrivacyText: string;
33
+ summaryPrivacyLink: string;
34
+ summaryPrivacyUrl: string;
34
35
  /**
35
- * FE-owned label + description + icon kind for a breakdown category (the backend sends the
36
- * QuestionType only). Unknown types fall back to a generic "Questions" label with no description.
36
+ * Label + description + icon for a breakdown row (the backend sends the QuestionType only).
37
+ * The video description interpolates the retry budget the recorder actually enforces, so the
38
+ * card and the recorder can never disagree. Unknown types fall back to a generic "Questions"
39
+ * label with no description.
37
40
  */
38
41
  summaryCategory: (type: QuestionType) => {
39
42
  label: string;
40
43
  description: string;
41
44
  kind: SummaryKind;
42
45
  };
43
- answerLooksGood: string;
44
46
  composerFooter: string;
45
47
  richToolbar: string;
46
48
  richBold: string;
47
49
  richItalic: string;
48
50
  richBulletList: string;
49
51
  richNumberList: string;
52
+ composerExpand: string;
53
+ composerCollapse: string;
50
54
  inputPlaceholder: string;
55
+ inputPlaceholderPaste: string;
56
+ /** Placeholder for the optional feedback comment, which says sending empty skips it. */
57
+ feedbackCommentPlaceholder: string;
51
58
  inputLabel: string;
52
59
  sendLabel: string;
53
60
  retryLabel: string;
@@ -56,12 +63,20 @@ export declare const buildStrings: (t: Translator) => {
56
63
  editingLabel: string;
57
64
  editBannerLabel: string;
58
65
  optionsGroupLabel: string;
66
+ /** Opens a folded run of intro hints. */
67
+ hintExpand: string;
68
+ /** Closes it again. */
69
+ hintCollapse: string;
59
70
  senderAgent: string;
60
71
  senderCandidate: string;
61
72
  opensNewTab: string;
62
73
  widgetLabel: string;
74
+ /**
75
+ * Accessible name for the rating slider, with no visible counterpart: the backend's own question
76
+ * ("Please rate your experience.") is the prompt, so a second line of widget copy saying the same
77
+ * thing read as a duplicate on screen and announced twice off it.
78
+ */
63
79
  sliderLabel: string;
64
- sliderHint: string;
65
80
  submitRatingLabel: string;
66
81
  dropdownSearchPlaceholder: string;
67
82
  dropdownSearchLabel: string;
@@ -69,11 +84,26 @@ export declare const buildStrings: (t: Translator) => {
69
84
  phoneCountryLabel: string;
70
85
  phoneInputLabel: string;
71
86
  phonePlaceholder: string;
87
+ locationInputLabel: string;
88
+ locationPlaceholder: string;
89
+ locationSuggestionsLabel: string;
90
+ /** Announced once a set of predictions settles, e.g. "5 locations found". */
91
+ locationSuggestionsFound: (count: number) => string;
72
92
  nameConfirmTitle: string;
73
93
  nameConfirmBody: (suggested: string) => string;
74
94
  useSuggestedLabel: (suggested: string) => string;
75
95
  useOriginalLabel: string;
76
- minLengthHint: (min: number) => string;
96
+ /** Composer word counter, e.g. "42 words". */
97
+ wordCount: (count: number) => string;
98
+ shortResponseHint: (min: number) => string;
99
+ goodResponseHint: string;
100
+ maxWordsHint: string;
101
+ shortAnswerTitle: (min: number) => string;
102
+ shortAnswerAim: (min: number, recommended?: number) => string;
103
+ shortAnswerEditAnytime: string;
104
+ shortAnswerEditNow: string;
105
+ dontShowAgainLabel: string;
106
+ continueLabel: string;
77
107
  loadingLabel: string;
78
108
  preparingLabel: string;
79
109
  doneTitle: (name?: string) => string;
@@ -81,7 +111,10 @@ export declare const buildStrings: (t: Translator) => {
81
111
  doneNextLabel: string;
82
112
  doneSteps: [string, string, string];
83
113
  doneRatingPrompt: string;
114
+ doneRedirect: string;
84
115
  startFailedMessage: string;
116
+ cohortClosedTitle: string;
117
+ cohortClosedMessage: string;
85
118
  /** PII validation error message for a given fi_error_pii* key. */
86
119
  piiError: (key: string) => string;
87
120
  videoOpenCamera: string;
@@ -117,5 +150,8 @@ export declare const buildStrings: (t: Translator) => {
117
150
  agcMessage: (attempt: number) => string;
118
151
  agcEdit: string;
119
152
  agcContinue: string;
153
+ editFailedTitle: string;
154
+ editFailedMessage: string;
155
+ editFailedDismiss: string;
120
156
  };
121
157
  export type UiStrings = ReturnType<typeof buildStrings>;
@@ -0,0 +1,16 @@
1
+ import { LocationAnswer, PlaceSuggestion } from '../api/places';
2
+ export type PlacesSuggestions = {
3
+ suggestions: PlaceSuggestion[];
4
+ /**
5
+ * Autocomplete is unavailable (no network, quota, blocked key). The composer stays usable and
6
+ * sends the typed address with a null coordinate — legacy's manual mode.
7
+ */
8
+ manualMode: boolean;
9
+ search: (input: string) => void;
10
+ clear: () => void;
11
+ /** Resolves the chosen prediction to its coordinates; null when the details call fails. */
12
+ resolve: (suggestion: PlaceSuggestion) => Promise<LocationAnswer | null>;
13
+ };
14
+ export declare const usePlacesSuggestions: ({ apiKey }: {
15
+ apiKey?: string;
16
+ }) => PlacesSuggestions;
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { n as r } from "./hls-mBncGwsE.js";
5
5
  import { a as i, i as a, n as o, r as s, t as c } from "./classPrivateFieldSet2-DtQPURVD.js";
@@ -215,4 +215,4 @@ var b = v({
215
215
  //#endregion
216
216
  export { b as default };
217
217
 
218
- //# sourceMappingURL=react-Bw5AugJc.js.map
218
+ //# sourceMappingURL=react-A0_ZwPyM.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  import { t as c } from "./dist-FvHBWiRa.js";
@@ -455,4 +455,4 @@ var $ = Z({
455
455
  //#endregion
456
456
  export { $ as default };
457
457
 
458
- //# sourceMappingURL=react-DEF8h8hc.js.map
458
+ //# sourceMappingURL=react-BDGt_WsZ.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  //#region ../../node_modules/.pnpm/super-media-element@1.4.2/node_modules/super-media-element/super-media-element.js
@@ -369,4 +369,4 @@ var P = M({
369
369
  //#endregion
370
370
  export { P as default };
371
371
 
372
- //# sourceMappingURL=react-DDjfkpOE.js.map
372
+ //# sourceMappingURL=react-B_YNH2g9.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { i as r, n as i, t as a } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  import { n as o, t as s } from "./dist-BOe6WyvN.js";
@@ -190,4 +190,4 @@ var S = b({
190
190
  //#endregion
191
191
  export { S as default };
192
192
 
193
- //# sourceMappingURL=react-D8hV9uow.js.map
193
+ //# sourceMappingURL=react-ByP48xLV.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  import { t as c } from "./dist-FvHBWiRa.js";
@@ -2207,4 +2207,4 @@ var rt = tt({
2207
2207
  //#endregion
2208
2208
  export { rt as default };
2209
2209
 
2210
- //# sourceMappingURL=react-DPFikgTM.js.map
2210
+ //# sourceMappingURL=react-C9oBRlX8.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  //#region ../../node_modules/.pnpm/tiktok-video-element@0.1.2/node_modules/tiktok-video-element/dist/tiktok-video-element.js
@@ -332,4 +332,4 @@ var K = W({
332
332
  //#endregion
333
333
  export { K as default };
334
334
 
335
- //# sourceMappingURL=react-qa12DkXH.js.map
335
+ //# sourceMappingURL=react-D5yWOfXN.js.map
@@ -1,4 +1,4 @@
1
- import { S as e } from "./messages-DCvBcspv.js";
1
+ import { C as e } from "./messages-C00e82NS.js";
2
2
  //#region ../../node_modules/.pnpm/react@19.2.7/node_modules/react/cjs/react.production.js
3
3
  var t = /* @__PURE__ */ e(((e) => {
4
4
  var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.portal"), r = Symbol.for("react.fragment"), i = Symbol.for("react.strict_mode"), a = Symbol.for("react.profiler"), o = Symbol.for("react.consumer"), s = Symbol.for("react.context"), c = Symbol.for("react.forward_ref"), l = Symbol.for("react.suspense"), u = Symbol.for("react.memo"), d = Symbol.for("react.lazy"), f = Symbol.for("react.activity"), p = Symbol.iterator;
@@ -292,4 +292,4 @@ var t = /* @__PURE__ */ e(((e) => {
292
292
  //#endregion
293
293
  export { n as t };
294
294
 
295
- //# sourceMappingURL=react-DOgLiyZi.js.map
295
+ //# sourceMappingURL=react-DkQKleWD.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  //#region ../../node_modules/.pnpm/twitch-video-element@0.1.6/node_modules/twitch-video-element/dist/twitch-video-element.js
@@ -365,4 +365,4 @@ var J = K({
365
365
  //#endregion
366
366
  export { J as default };
367
367
 
368
- //# sourceMappingURL=react-y4vaW3OH.js.map
368
+ //# sourceMappingURL=react-d-THpGrV.js.map
@@ -1,5 +1,5 @@
1
- import { w as e } from "./messages-DCvBcspv.js";
2
- import { t } from "./react-DOgLiyZi.js";
1
+ import { T as e } from "./messages-C00e82NS.js";
2
+ import { t } from "./react-DkQKleWD.js";
3
3
  import { t as n } from "./defineProperty-DiFpLzd2.js";
4
4
  import { a as r, i, n as a, r as o, t as s } from "./classPrivateFieldSet2-DtQPURVD.js";
5
5
  //#region ../../node_modules/.pnpm/spotify-audio-element@1.0.4/node_modules/spotify-audio-element/dist/spotify-audio-element.js
@@ -309,4 +309,4 @@ var W = H({
309
309
  //#endregion
310
310
  export { W as default };
311
311
 
312
- //# sourceMappingURL=react-BjO903pN.js.map
312
+ //# sourceMappingURL=react-euSb4sIX.js.map
@@ -0,0 +1,15 @@
1
+ export type ActionDockProps = {
2
+ label: string;
3
+ /** The click is accepted — the prompt is the current one and no answer is in flight. */
4
+ enabled: boolean;
5
+ /** An acknowledgement is in flight. */
6
+ pending?: boolean;
7
+ onClick: () => void;
8
+ };
9
+ /**
10
+ * Bottom-docked CTA for a one-off control prompt — a break acknowledgement, the terms consent, the
11
+ * final submit. Docked rather than drawn in the transcript because those steps carry arbitrarily
12
+ * tall content (a brief, an embedded video) and the control has to stay on screen regardless.
13
+ * Chrome matches the composer's, which shares this slot.
14
+ */
15
+ export declare const ActionDock: ({ label, enabled, pending, onClick }: ActionDockProps) => import("react").JSX.Element;