@sapia-ai/chatbot-v3 1.2.0 → 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 (51) hide show
  1. package/dist/{EmbeddedVideoPlayer-C_8tKis8.js → EmbeddedVideoPlayer-DTzRqNcQ.js} +14 -14
  2. package/dist/{Preview-CbNUoib5.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 +26 -3
  6. package/dist/api/types/responses.d.ts +19 -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 +14 -2
  10. package/dist/core/bubbles/counters.d.ts +10 -0
  11. package/dist/core/bubbles/types.d.ts +20 -0
  12. package/dist/core/constants.d.ts +13 -0
  13. package/dist/core/interview.d.ts +20 -7
  14. package/dist/core/store.d.ts +7 -8
  15. package/dist/{dist-7zan-9V3.js → dist-waE-4cub.js} +3 -3
  16. package/dist/embed/createChatbot.d.ts +2 -0
  17. package/dist/{fix-webm-duration-CJ-IsmuV.js → fix-webm-duration-IniZA6tF.js} +2 -2
  18. package/dist/index.js +5139 -4739
  19. package/dist/{jsx-runtime-CpK9sRtl.js → jsx-runtime-DN_m6Qdv.js} +2 -2
  20. package/dist/{messages-t5h3u6nr.js → messages-C00e82NS.js} +43 -38
  21. package/dist/places-CT6PNW7B.js +52 -0
  22. package/dist/react/AnswerInput.d.ts +6 -1
  23. package/dist/react/SapiaChatbot.d.ts +3 -1
  24. package/dist/react/bubbleViewModel.d.ts +9 -5
  25. package/dist/react/strings.d.ts +17 -7
  26. package/dist/react/usePlacesSuggestions.d.ts +16 -0
  27. package/dist/{react-Bx1VLQqP.js → react-A0_ZwPyM.js} +3 -3
  28. package/dist/{react--hlAJW6n.js → react-BDGt_WsZ.js} +3 -3
  29. package/dist/{react-BKQw6USG.js → react-B_YNH2g9.js} +3 -3
  30. package/dist/{react-yXcg2glq.js → react-ByP48xLV.js} +3 -3
  31. package/dist/{react-DFkljL-6.js → react-C9oBRlX8.js} +3 -3
  32. package/dist/{react-Bh9U4IBe.js → react-D5yWOfXN.js} +3 -3
  33. package/dist/{react-BtFG4mMU.js → react-DkQKleWD.js} +2 -2
  34. package/dist/{react-B6p_EGvt.js → react-d-THpGrV.js} +3 -3
  35. package/dist/{react-DJK2_GuR.js → react-euSb4sIX.js} +3 -3
  36. package/dist/ui/chat/ActionDock/ActionDock.d.ts +15 -0
  37. package/dist/ui/chat/ChatBubble/ChatBubble.d.ts +9 -2
  38. package/dist/ui/chat/ChatLog/ChatLog.d.ts +6 -4
  39. package/dist/ui/chat/EditBanner/EditBanner.d.ts +9 -3
  40. package/dist/ui/chat/SummaryCard/SummaryCard.d.ts +18 -23
  41. package/dist/ui/chat/types.d.ts +13 -2
  42. package/dist/ui/inputs/LocationAnswerInput/LocationAnswerInput.d.ts +34 -0
  43. package/dist/ui/inputs/PhoneAnswerInput/PhoneAnswerInput.d.ts +5 -2
  44. package/dist/ui/inputs/TextAnswerInput/TextAnswerInput.d.ts +11 -1
  45. package/dist/ui/shell/CopyLinkButton/CopyLinkButton.d.ts +10 -3
  46. package/dist/ui/shell/Header/AutoScrollTitle.d.ts +15 -0
  47. package/dist/ui/shell/Header/Header.d.ts +7 -4
  48. package/dist/ui/shell/Header/useAutoScrollTitle.d.ts +16 -0
  49. package/dist/ui/shell/WidgetRoot/themeVariables.d.ts +8 -0
  50. package/dist-umd/sapia-chatbot.umd.js +304 -304
  51. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { C as e } from "./messages-t5h3u6nr.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-CpK9sRtl.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,32 +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.SUBMIT_QUESTION = "SUBMIT_QUESTION_MESSAGE", e.FEEDBACK_CUSTOMER_SATISFACTION_QUESTION = "FEEDBACK_CUSTOMER_SATISFACTION_QUESTION_MESSAGE", 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) {
1973
- return e.TEXT = "Text", e.VOICE_PLAYER = "VoicePlayer", e.VIDEO_PLAYER = "VideoPlayer", e.SLIDER = "Slider", e;
1978
+ return e.ASSESSMENT_SUMMARY = "{assessment.summary}", e.ASSESSMENT_LINK = "{assessment.link}", e;
1974
1979
  }({}), $n = /* @__PURE__ */ function(e) {
1975
1980
  return e.HINT = "Hint", e.QUESTION = "Question", e;
1976
1981
  }({});
1977
1982
  //#endregion
1978
- export { o as C, Nn as S, l as T, An as _, Zn as a, kn as b, Kn as c, Hn as d, Jn as f, jn as g, Ln as h, Gn as i, qn as l, $ as m, Yn as n, $n as o, Bn as p, Qn as r, Un as s, Xn as t, Wn as u, Mn as v, s as w, Pn as x, On 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 };
1979
1984
 
1980
- //# sourceMappingURL=messages-t5h3u6nr.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
@@ -12,6 +12,8 @@ export type AnswerInputProps = {
12
12
  strings: UiStrings;
13
13
  candidateCountryCode?: string;
14
14
  region: Region;
15
+ /** Host's own Google Places key for the location question; defaults to the bundled key. */
16
+ placesApiKey?: string;
15
17
  /** Max video answer length in seconds (video questions). */
16
18
  maxVideoSeconds?: number;
17
19
  /** Stored answer to open the composer on when re-editing. */
@@ -22,5 +24,8 @@ export type AnswerInputProps = {
22
24
  isFeedbackComment: boolean;
23
25
  /** Called for each blocked paste attempt (AGC paste log). */
24
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;
25
30
  };
26
- export declare const AnswerInput: ({ engine, assessmentId, kind, disabled, wordCountRule, strings, candidateCountryCode, region, maxVideoSeconds, draft, allowPaste, isFeedbackComment, onBlockedPaste, }: 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;
@@ -17,6 +17,8 @@ export type SapiaChatbotProps = {
17
17
  language?: string;
18
18
  /** Absolute http(s) URL offered as a "continue" CTA once the interview ends. */
19
19
  redirectUrl?: string;
20
+ /** Host's own Google Places key for the location question; defaults to the bundled key. */
21
+ placesApiKey?: string;
20
22
  /** Receives every widget event; or pass an emitter via createChatbot. */
21
23
  onEvent?: ChatbotEventHandler;
22
24
  /** @internal used by embed/createChatbot to share its emitter. */
@@ -24,4 +26,4 @@ export type SapiaChatbotProps = {
24
26
  /** @internal streaming transport override (mock SSE for the demo / tests). */
25
27
  fetchImpl?: typeof fetch;
26
28
  };
27
- export declare const SapiaChatbot: ({ env, region, appId, assessmentId, apiOrigin, theme, showHeader, isInternalUser, language, redirectUrl, 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;
@@ -9,7 +9,7 @@ export type AnswerLocks = {
9
9
  };
10
10
  /** Per-card eyebrow + optional dark badge, keyed by agent bubble id. */
11
11
  export type QuestionCard = {
12
- label: string;
12
+ label?: string;
13
13
  badge?: string;
14
14
  };
15
15
  export declare const mapBubblesToChatItems: (bubbles: MessageBubble[], cards?: Map<string, QuestionCard>, locks?: AnswerLocks, streamingBubbleId?: string) => ChatLogItem[];
@@ -50,10 +50,14 @@ export type QuestionCardLabels = {
50
50
  };
51
51
  /**
52
52
  * Marks every agent question turn as a card (matching the prototype's permanent
53
- * question styling); conversational agent turns stay plain. Every card shows
54
- * "Question n of N" (choice questions included, matching the reference); video
55
- * adds a media badge. Cards persist through an edit — the docked edit banner, not a
56
- * 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.
57
61
  */
58
62
  export declare const buildQuestionCards: (bubbles: MessageBubble[], total: number, labels: QuestionCardLabels) => Map<string, QuestionCard>;
59
63
  /**
@@ -25,15 +25,18 @@ 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;
@@ -46,6 +49,8 @@ export declare const buildStrings: (t: Translator) => {
46
49
  richItalic: string;
47
50
  richBulletList: string;
48
51
  richNumberList: string;
52
+ composerExpand: string;
53
+ composerCollapse: string;
49
54
  inputPlaceholder: string;
50
55
  inputPlaceholderPaste: string;
51
56
  /** Placeholder for the optional feedback comment, which says sending empty skips it. */
@@ -79,6 +84,11 @@ export declare const buildStrings: (t: Translator) => {
79
84
  phoneCountryLabel: string;
80
85
  phoneInputLabel: string;
81
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;
82
92
  nameConfirmTitle: string;
83
93
  nameConfirmBody: (suggested: string) => string;
84
94
  useSuggestedLabel: (suggested: string) => string;
@@ -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 { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-Bx1VLQqP.js.map
218
+ //# sourceMappingURL=react-A0_ZwPyM.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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--hlAJW6n.js.map
458
+ //# sourceMappingURL=react-BDGt_WsZ.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-BKQw6USG.js.map
372
+ //# sourceMappingURL=react-B_YNH2g9.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-yXcg2glq.js.map
193
+ //# sourceMappingURL=react-ByP48xLV.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-DFkljL-6.js.map
2210
+ //# sourceMappingURL=react-C9oBRlX8.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-Bh9U4IBe.js.map
335
+ //# sourceMappingURL=react-D5yWOfXN.js.map
@@ -1,4 +1,4 @@
1
- import { C as e } from "./messages-t5h3u6nr.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-BtFG4mMU.js.map
295
+ //# sourceMappingURL=react-DkQKleWD.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-B6p_EGvt.js.map
368
+ //# sourceMappingURL=react-d-THpGrV.js.map
@@ -1,5 +1,5 @@
1
- import { T as e } from "./messages-t5h3u6nr.js";
2
- import { t } from "./react-BtFG4mMU.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-DJK2_GuR.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;
@@ -1,5 +1,5 @@
1
1
  import { ReactNode, Ref } from 'react';
2
- import { ChatLogItem } from '../types';
2
+ import { ChatCardKind, ChatLogItem } from '../types';
3
3
  export type SliderLabels = {
4
4
  /** Accessible name for the range input — the backend's question is the visible prompt. */
5
5
  label: string;
@@ -47,10 +47,17 @@ export type ChatBubbleProps = {
47
47
  rootRef?: Ref<HTMLLIElement>;
48
48
  /** Rendered inside the question card body (e.g. the video recorder). */
49
49
  footer?: ReactNode;
50
+ /**
51
+ * Replaces the quiet editing marker on the bubble under edit (the edit banner, for an
52
+ * option question that opens no composer for a docked one to sit above).
53
+ */
54
+ editingFooter?: ReactNode;
55
+ /** Draws one card the item names; the react glue owns each card's copy and data. */
56
+ renderCard?: (kind: ChatCardKind) => ReactNode;
50
57
  };
51
58
  /**
52
59
  * Memoized: the transcript re-renders on every store write (roughly 60/s while an agent message
53
60
  * streams in), and each render re-parses every settled paragraph's markdown from scratch. Default
54
61
  * shallow comparison suffices — ChatLog is passed stable item and label references.
55
62
  */
56
- export declare const ChatBubble: import('react').MemoExoticComponent<({ item, labels, sliderLabels, dropdownLabels, mediaLabels, onRetry, onSelectOption, onSubmitSlider, onEdit, onRetryVideo, onResolveVideoUrl, rootRef, footer, }: ChatBubbleProps) => import("react").JSX.Element>;
63
+ export declare const ChatBubble: import('react').MemoExoticComponent<({ item, labels, sliderLabels, dropdownLabels, mediaLabels, onRetry, onSelectOption, onSubmitSlider, onEdit, onRetryVideo, onResolveVideoUrl, rootRef, footer, editingFooter, renderCard, }: ChatBubbleProps) => import("react").JSX.Element>;
@@ -1,7 +1,7 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { ChatBubbleLabels, DropdownLabels, MediaLabels, SliderLabels } from '../ChatBubble/ChatBubble';
3
3
  import { HintDisclosureLabels } from '../HintDisclosure/HintDisclosure';
4
- import { ChatLogItem } from '../types';
4
+ import { ChatCardKind, ChatLogItem } from '../types';
5
5
  export type ChatLogProps = {
6
6
  items: ChatLogItem[];
7
7
  typing: boolean;
@@ -27,12 +27,14 @@ export type ChatLogProps = {
27
27
  cardFooter?: ReactNode;
28
28
  /** Bubble id whose card receives cardFooter. */
29
29
  cardFooterItemId?: string;
30
- /** Node pinned as the first transcript entry (e.g. the pre-interview summary card). */
31
- header?: ReactNode;
30
+ /** Node rendered under the bubble being re-edited, in place of its quiet editing marker. */
31
+ editingFooter?: ReactNode;
32
+ /** Draws one card an item names (the summary, the resume link); passed through to ChatBubble. */
33
+ renderCard?: (kind: ChatCardKind) => ReactNode;
32
34
  };
33
35
  /**
34
36
  * Scrollable interview transcript. The log auto-scrolls to the newest message; settled turns
35
37
  * are announced once through a separate visually-hidden live region (the transcript itself is
36
38
  * deliberately not one — see the announcer effect below).
37
39
  */
38
- export declare const ChatLog: ({ items, typing, typingLabel, typingReadingLabel, typingThinkingLabel, bubbleLabels, hintLabels, sliderLabels, dropdownLabels, mediaLabels, onRetry, onSelectOption, onSubmitSlider, onEdit, onRetryVideo, onResolveVideoUrl, cardFooter, cardFooterItemId, header, }: ChatLogProps) => import("react").JSX.Element;
40
+ export declare const ChatLog: ({ items, typing, typingLabel, typingReadingLabel, typingThinkingLabel, bubbleLabels, hintLabels, sliderLabels, dropdownLabels, mediaLabels, onRetry, onSelectOption, onSubmitSlider, onEdit, onRetryVideo, onResolveVideoUrl, cardFooter, cardFooterItemId, editingFooter, renderCard, }: ChatLogProps) => import("react").JSX.Element;
@@ -6,11 +6,17 @@ export type EditBannerProps = {
6
6
  /** Cancel copy, server-supplied ("Press ESC or click here to cancel editing"). */
7
7
  cancelLabel: string;
8
8
  onCancel: () => void;
9
+ /**
10
+ * Drops the docking chrome so the strip can sit in the transcript instead. An option
11
+ * question opens no composer, so a docked strip would strand the cancel control at the
12
+ * bottom of the widget while the options it belongs to sit further up the log.
13
+ */
14
+ inline?: boolean;
9
15
  };
10
16
  /**
11
- * Docked strip naming the answer under edit and offering the single cancel control.
12
- * Repeats the composer's own column classes so it lines up with the input box at any
17
+ * Strip naming the answer under edit and offering the single cancel control. Docked, it
18
+ * repeats the composer's own column classes so it lines up with the input box at any
13
19
  * container width. role="status" so entering edit mode is announced; the Escape
14
20
  * shortcut it advertises is bound in react/SapiaChatbot.
15
21
  */
16
- export declare const EditBanner: ({ label, questionLabel, cancelLabel, onCancel }: EditBannerProps) => import("react").JSX.Element;
22
+ export declare const EditBanner: ({ label, questionLabel, cancelLabel, onCancel, inline, }: EditBannerProps) => import("react").JSX.Element;