@xinghunm/ai-chat 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ module.exports = __toCommonJS(src_exports);
47
47
 
48
48
  // src/components/ai-chat/index.tsx
49
49
  var import_styled17 = __toESM(require("@emotion/styled"));
50
- var import_compass_ui4 = require("@xinghunm/compass-ui");
50
+ var import_compass_ui5 = require("@xinghunm/compass-ui");
51
51
 
52
52
  // src/components/ai-chat-provider/index.tsx
53
53
  var import_react2 = require("react");
@@ -89,7 +89,10 @@ var DEFAULT_AI_CHAT_LABELS = {
89
89
  questionnaireSubmitting: "Submitting...",
90
90
  questionnaireSubmitted: "Selection submitted. Waiting for the plan to continue...",
91
91
  questionnaireValidationPrefix: "Please complete:",
92
- questionnaireSubmitFailed: "Failed to submit. Please try again."
92
+ questionnaireSubmitFailed: "Failed to submit. Please try again.",
93
+ questionnaireMultiSelectHint: "Multiple choice",
94
+ questionnaireOtherOptionLabel: "Other",
95
+ questionnaireOtherPlaceholder: "Other"
93
96
  };
94
97
 
95
98
  // src/store/chat-store.ts
@@ -124,6 +127,22 @@ var mergeStreamingBlocks = (existingBlocks, incomingBlocks) => {
124
127
  nextBlocks.push(incomingBlock);
125
128
  return;
126
129
  }
130
+ if (incomingBlock.type === "questionnaire" && incomingBlock.questionnaire.blockKey) {
131
+ const mergePolicy = incomingBlock.questionnaire.mergePolicy ?? "append";
132
+ if (mergePolicy !== "append") {
133
+ const existingIndex2 = nextBlocks.findIndex(
134
+ (block) => block.type === "questionnaire" && block.questionnaire.blockKey === incomingBlock.questionnaire.blockKey
135
+ );
136
+ if (existingIndex2 !== -1) {
137
+ if (mergePolicy === "replace") {
138
+ nextBlocks[existingIndex2] = incomingBlock;
139
+ }
140
+ return;
141
+ }
142
+ }
143
+ nextBlocks.push(incomingBlock);
144
+ return;
145
+ }
127
146
  if (incomingBlock.type !== "questionnaire") {
128
147
  nextBlocks.push(incomingBlock);
129
148
  return;
@@ -1024,7 +1043,7 @@ var getTimelineBlockKey = (block, index) => {
1024
1043
  case "result_summary":
1025
1044
  return `${index}:result_summary:${block.summary.summaryId}:${block.summary.status}`;
1026
1045
  case "questionnaire":
1027
- return `${index}:questionnaire:${block.questionnaire.questionnaireId}`;
1046
+ return block.questionnaire.blockKey ? `questionnaire:${block.questionnaire.blockKey}` : `${index}:questionnaire:${block.questionnaire.questionnaireId}`;
1028
1047
  case "custom":
1029
1048
  return block.blockKey ? `custom:${block.blockKey}` : `${index}:custom:${block.kind}:${stringifyTimelineKeyPart(block.data)}`;
1030
1049
  default:
@@ -1518,29 +1537,120 @@ var Value = import_styled3.default.span`
1518
1537
  // src/components/chat-thread/components/questionnaire-card.tsx
1519
1538
  var import_react7 = require("react");
1520
1539
  var import_styled4 = __toESM(require("@emotion/styled"));
1521
- var import_jsx_runtime5 = require("@emotion/react/jsx-runtime");
1540
+ var import_compass_ui = require("@xinghunm/compass-ui");
1541
+
1542
+ // src/components/chat-thread/components/questionnaire-card-helpers.ts
1522
1543
  var OTHER_OPTION_VALUE = "__other__";
1523
- var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
1524
- submitting: "Submitting...",
1525
- submitted: "Selection submitted. Waiting for the plan to continue...",
1526
- validationPrefix: "Please complete:",
1527
- submitFailed: "Failed to submit. Please try again."
1528
- };
1529
- var createInitialAnswers = (questionnaire) => ({
1530
- ...questionnaire.answers ?? {}
1531
- });
1544
+ var getQuestionnaireQuestion = (questionnaire) => questionnaire.question;
1532
1545
  var getMultiSelectAnswerValues = (answer) => Array.isArray(answer) ? answer : [];
1533
- var getSingleSelectDraftState = (question, answer) => {
1546
+ var getQuestionOptionValues = (question) => new Set(question.options.map((option) => option.value));
1547
+ var extractSingleSelectOtherDraft = (question, answer) => {
1548
+ if (typeof answer !== "string") {
1549
+ return "";
1550
+ }
1551
+ return getQuestionOptionValues(question).has(answer) ? "" : answer;
1552
+ };
1553
+ var extractMultiSelectOtherDraft = (question, answer) => {
1554
+ if (!Array.isArray(answer)) {
1555
+ return "";
1556
+ }
1557
+ const optionValues = getQuestionOptionValues(question);
1558
+ const customValue = answer.find(
1559
+ (value) => typeof value === "string" && value !== OTHER_OPTION_VALUE && !optionValues.has(value)
1560
+ );
1561
+ return typeof customValue === "string" ? customValue : "";
1562
+ };
1563
+ var createInitialAnswers = (questionnaire) => {
1564
+ const initialAnswers = {};
1565
+ const question = getQuestionnaireQuestion(questionnaire);
1566
+ if (!question) {
1567
+ return initialAnswers;
1568
+ }
1569
+ const answer = questionnaire.answers?.[question.id];
1570
+ switch (question.kind) {
1571
+ case "single_select": {
1572
+ if (typeof answer !== "string") {
1573
+ break;
1574
+ }
1575
+ if (getQuestionOptionValues(question).has(answer)) {
1576
+ initialAnswers[question.id] = answer;
1577
+ break;
1578
+ }
1579
+ if (question.allowOther) {
1580
+ initialAnswers[question.id] = OTHER_OPTION_VALUE;
1581
+ }
1582
+ break;
1583
+ }
1584
+ case "multi_select": {
1585
+ if (!Array.isArray(answer)) {
1586
+ break;
1587
+ }
1588
+ const optionValues = getQuestionOptionValues(question);
1589
+ const selectedValues = [];
1590
+ let hasOtherValue = false;
1591
+ for (const value of answer) {
1592
+ if (typeof value !== "string") {
1593
+ continue;
1594
+ }
1595
+ if (optionValues.has(value)) {
1596
+ selectedValues.push(value);
1597
+ continue;
1598
+ }
1599
+ if (question.allowOther && !hasOtherValue) {
1600
+ selectedValues.push(OTHER_OPTION_VALUE);
1601
+ hasOtherValue = true;
1602
+ }
1603
+ }
1604
+ initialAnswers[question.id] = selectedValues;
1605
+ break;
1606
+ }
1607
+ default:
1608
+ initialAnswers[question.id] = answer;
1609
+ }
1610
+ return initialAnswers;
1611
+ };
1612
+ var createInitialOtherDrafts = (questionnaire) => {
1613
+ const drafts = {};
1614
+ const question = getQuestionnaireQuestion(questionnaire);
1615
+ if (!question) {
1616
+ return drafts;
1617
+ }
1618
+ const answer = questionnaire.answers?.[question.id];
1619
+ switch (question.kind) {
1620
+ case "single_select":
1621
+ if (question.allowOther) {
1622
+ drafts[question.id] = extractSingleSelectOtherDraft(question, answer);
1623
+ }
1624
+ break;
1625
+ case "multi_select":
1626
+ if (question.allowOther) {
1627
+ drafts[question.id] = extractMultiSelectOtherDraft(question, answer);
1628
+ }
1629
+ break;
1630
+ default:
1631
+ break;
1632
+ }
1633
+ return drafts;
1634
+ };
1635
+ var getMultiSelectDraftState = (question, answer, otherDraft) => {
1636
+ const answerValues = getMultiSelectAnswerValues(answer);
1637
+ return {
1638
+ selectedValues: answerValues,
1639
+ otherValue: otherDraft,
1640
+ hasOtherSelected: question.allowOther === true && answerValues.includes(OTHER_OPTION_VALUE)
1641
+ };
1642
+ };
1643
+ var getSingleSelectDraftState = (question, answer, otherDraft) => {
1534
1644
  if (typeof answer !== "string") {
1535
1645
  return {
1536
1646
  selectedValue: void 0,
1537
- otherValue: ""
1647
+ otherValue: otherDraft
1538
1648
  };
1539
1649
  }
1540
- const matchesOption = question.options.some((option) => option.value === answer);
1650
+ const matchesOption = answer !== OTHER_OPTION_VALUE && question.options.some((option) => option.value === answer);
1541
1651
  return {
1542
1652
  selectedValue: matchesOption ? answer : question.allowOther ? OTHER_OPTION_VALUE : void 0,
1543
- otherValue: matchesOption ? "" : answer
1653
+ otherValue: otherDraft
1544
1654
  };
1545
1655
  };
1546
1656
  var updateAnswerValue = (current, questionId, value) => ({
@@ -1552,6 +1662,17 @@ var toggleMultiSelectAnswer = (current, questionId, optionValue) => {
1552
1662
  const nextValues = currentValues.includes(optionValue) ? currentValues.filter((value) => value !== optionValue) : [...currentValues, optionValue];
1553
1663
  return updateAnswerValue(current, questionId, nextValues);
1554
1664
  };
1665
+ var toggleMultiSelectOtherAnswer = (current, question) => {
1666
+ const currentValues = getMultiSelectAnswerValues(current[question.id]);
1667
+ if (currentValues.includes(OTHER_OPTION_VALUE)) {
1668
+ return updateAnswerValue(
1669
+ current,
1670
+ question.id,
1671
+ currentValues.filter((value) => value !== OTHER_OPTION_VALUE)
1672
+ );
1673
+ }
1674
+ return updateAnswerValue(current, question.id, [...currentValues, OTHER_OPTION_VALUE]);
1675
+ };
1555
1676
  var getTextInputValue = (answer) => typeof answer === "string" ? String(answer) : "";
1556
1677
  var getNumberInputValue = (answer) => typeof answer === "number" || typeof answer === "string" ? String(answer) : "";
1557
1678
  var getOptionChoiceLabel = (index) => {
@@ -1560,20 +1681,49 @@ var getOptionChoiceLabel = (index) => {
1560
1681
  }
1561
1682
  return String(index + 1);
1562
1683
  };
1563
- var isMissingRequiredAnswer = (question, answers) => {
1564
- const answer = answers[question.id];
1684
+ var normalizeQuestionAnswer = (question, answer, otherDraft = "") => {
1685
+ if (answer === void 0) {
1686
+ return void 0;
1687
+ }
1565
1688
  switch (question.kind) {
1566
- case "boolean":
1567
- return typeof answer !== "boolean";
1568
1689
  case "multi_select":
1569
- return !Array.isArray(answer) || answer.length === 0;
1570
- case "number":
1571
- return typeof answer !== "number" || Number.isNaN(answer);
1572
- case "text":
1690
+ if (!Array.isArray(answer)) {
1691
+ return void 0;
1692
+ }
1693
+ return (() => {
1694
+ const optionValues = getQuestionOptionValues(question);
1695
+ const normalizedOtherDraft = otherDraft.trim();
1696
+ const normalizedValues = answer.flatMap((value) => {
1697
+ if (typeof value !== "string") {
1698
+ return [];
1699
+ }
1700
+ if (optionValues.has(value)) {
1701
+ return [value];
1702
+ }
1703
+ if (!question.allowOther || value !== OTHER_OPTION_VALUE) {
1704
+ return [];
1705
+ }
1706
+ return normalizedOtherDraft === "" ? [] : [normalizedOtherDraft];
1707
+ });
1708
+ return normalizedValues.length > 0 ? normalizedValues : void 0;
1709
+ })();
1573
1710
  case "single_select":
1574
- return typeof answer !== "string" || answer.trim() === "";
1711
+ if (answer === OTHER_OPTION_VALUE) {
1712
+ const normalizedOtherDraft = otherDraft.trim();
1713
+ return normalizedOtherDraft === "" ? void 0 : normalizedOtherDraft;
1714
+ }
1715
+ if (typeof answer !== "string" || answer.trim() === "") {
1716
+ return void 0;
1717
+ }
1718
+ return getQuestionOptionValues(question).has(answer) ? answer : void 0;
1719
+ case "text":
1720
+ return typeof answer === "string" && answer.trim() !== "" ? answer : void 0;
1721
+ case "number":
1722
+ return typeof answer === "number" && !Number.isNaN(answer) ? answer : void 0;
1723
+ case "boolean":
1724
+ return typeof answer === "boolean" ? answer : void 0;
1575
1725
  default:
1576
- return true;
1726
+ return answer;
1577
1727
  }
1578
1728
  };
1579
1729
  var formatQuestionAnswer = (question, answer) => {
@@ -1601,79 +1751,221 @@ var formatQuestionAnswer = (question, answer) => {
1601
1751
  return String(answer);
1602
1752
  }
1603
1753
  };
1604
- var normalizeQuestionAnswer = (question, answer) => {
1754
+ var buildQuestionSubmissionDetail = (question, answer) => {
1605
1755
  if (answer === void 0) {
1606
1756
  return void 0;
1607
1757
  }
1608
1758
  switch (question.kind) {
1609
- case "multi_select":
1610
- return Array.isArray(answer) && answer.length > 0 ? answer : void 0;
1611
- case "single_select":
1612
- case "text":
1613
- return typeof answer === "string" && answer.trim() !== "" ? answer : void 0;
1614
- case "number":
1615
- return typeof answer === "number" && !Number.isNaN(answer) ? answer : void 0;
1616
- case "boolean":
1617
- return typeof answer === "boolean" ? answer : void 0;
1759
+ case "single_select": {
1760
+ if (typeof answer !== "string") {
1761
+ return void 0;
1762
+ }
1763
+ const optionValues = getQuestionOptionValues(question);
1764
+ const trimmedAnswer = answer.trim();
1765
+ return {
1766
+ questionId: question.id,
1767
+ kind: question.kind,
1768
+ value: answer,
1769
+ selectedOptionValues: optionValues.has(answer) ? [answer] : [],
1770
+ otherValue: optionValues.has(answer) || trimmedAnswer === "" ? void 0 : trimmedAnswer
1771
+ };
1772
+ }
1773
+ case "multi_select": {
1774
+ if (!Array.isArray(answer)) {
1775
+ return void 0;
1776
+ }
1777
+ const optionValues = getQuestionOptionValues(question);
1778
+ const selectedOptionValues = answer.filter(
1779
+ (value) => typeof value === "string" && optionValues.has(value)
1780
+ );
1781
+ const otherValue = answer.find(
1782
+ (value) => typeof value === "string" && !optionValues.has(value)
1783
+ );
1784
+ return {
1785
+ questionId: question.id,
1786
+ kind: question.kind,
1787
+ value: answer,
1788
+ selectedOptionValues,
1789
+ otherValue: otherValue?.trim() ? otherValue.trim() : void 0
1790
+ };
1791
+ }
1618
1792
  default:
1619
- return answer;
1793
+ return {
1794
+ questionId: question.id,
1795
+ kind: question.kind,
1796
+ value: answer
1797
+ };
1620
1798
  }
1621
1799
  };
1800
+ var getMissingRequiredQuestions = (questionnaire, answers, otherDrafts) => {
1801
+ const question = getQuestionnaireQuestion(questionnaire);
1802
+ if (!question || !question.required) {
1803
+ return [];
1804
+ }
1805
+ return normalizeQuestionAnswer(question, answers[question.id], otherDrafts[question.id]) === void 0 ? [question] : [];
1806
+ };
1807
+ var prepareQuestionnaireSubmission = (questionnaire, answers, otherDrafts) => {
1808
+ const question = getQuestionnaireQuestion(questionnaire);
1809
+ if (!question) {
1810
+ return {
1811
+ normalizedAnswers: {},
1812
+ submissionDetails: void 0,
1813
+ content: questionnaire.title ?? "Questionnaire responses"
1814
+ };
1815
+ }
1816
+ const value = normalizeQuestionAnswer(question, answers[question.id], otherDrafts[question.id]);
1817
+ const normalizedAnswers = value === void 0 ? {} : { [question.id]: value };
1818
+ const detail = buildQuestionSubmissionDetail(question, normalizedAnswers[question.id]);
1819
+ const submissionDetails = detail === void 0 ? void 0 : { [question.id]: detail };
1820
+ return {
1821
+ normalizedAnswers,
1822
+ submissionDetails,
1823
+ content: [
1824
+ questionnaire.title ?? "Questionnaire responses",
1825
+ ...normalizedAnswers[question.id] === void 0 ? [] : [
1826
+ `- ${question.label}: ${formatQuestionAnswer(question, normalizedAnswers[question.id])}`
1827
+ ]
1828
+ ].join("\n")
1829
+ };
1830
+ };
1831
+ var getQuestionnaireStateKey = (questionnaire) => JSON.stringify([
1832
+ questionnaire.questionnaireId,
1833
+ questionnaire.blockKey,
1834
+ questionnaire.question,
1835
+ questionnaire.status,
1836
+ questionnaire.statusMessage
1837
+ ]);
1838
+
1839
+ // src/components/chat-thread/components/questionnaire-card.tsx
1840
+ var import_jsx_runtime5 = require("@emotion/react/jsx-runtime");
1841
+ var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
1842
+ submitting: "Submitting...",
1843
+ submitted: "Selection submitted. Waiting for the plan to continue...",
1844
+ validationPrefix: "Please complete:",
1845
+ submitFailed: "Failed to submit. Please try again.",
1846
+ multiSelectHint: "Multiple choice",
1847
+ otherOptionLabel: "Other",
1848
+ otherPlaceholder: "Other"
1849
+ };
1850
+ var stopInputClickPropagation = (event) => {
1851
+ event.stopPropagation();
1852
+ };
1853
+ var stopInputKeyPropagation = (event) => {
1854
+ event.stopPropagation();
1855
+ };
1856
+ var OptionChoice = ({
1857
+ questionId,
1858
+ optionLabel,
1859
+ index,
1860
+ isSelected,
1861
+ isInteractionLocked,
1862
+ onClick,
1863
+ inlineInput,
1864
+ tone = "default"
1865
+ }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1866
+ OptionChoiceItem,
1867
+ {
1868
+ role: "button",
1869
+ tabIndex: isInteractionLocked ? -1 : 0,
1870
+ "aria-pressed": isSelected,
1871
+ "data-selected": isSelected,
1872
+ "data-tone": tone,
1873
+ "data-testid": `question-option-${questionId}-${index}`,
1874
+ onClick: (event) => {
1875
+ if (isInteractionLocked) {
1876
+ return;
1877
+ }
1878
+ if (event.target instanceof HTMLElement && event.target.closest("input")) {
1879
+ return;
1880
+ }
1881
+ onClick();
1882
+ },
1883
+ onKeyDown: (event) => {
1884
+ if (isInteractionLocked) {
1885
+ return;
1886
+ }
1887
+ if (event.key !== "Enter" && event.key !== " ") {
1888
+ return;
1889
+ }
1890
+ event.preventDefault();
1891
+ onClick();
1892
+ },
1893
+ children: [
1894
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceMarker, { "data-selected": isSelected, children: getOptionChoiceLabel(index) }),
1895
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionChoiceContent, { children: [
1896
+ inlineInput ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceLabel, { children: optionLabel }),
1897
+ inlineInput
1898
+ ] })
1899
+ ]
1900
+ }
1901
+ );
1622
1902
  var QuestionnaireCardInner = ({
1623
1903
  questionnaire,
1624
1904
  interactive = false,
1625
1905
  onSubmit,
1626
1906
  labels
1627
1907
  }) => {
1908
+ const questionnaireRef = (0, import_react7.useRef)(questionnaire);
1909
+ const otherInputRefs = (0, import_react7.useRef)({});
1628
1910
  const [answers, setAnswers] = (0, import_react7.useState)(
1629
1911
  () => createInitialAnswers(questionnaire)
1630
1912
  );
1913
+ const [otherDrafts, setOtherDrafts] = (0, import_react7.useState)(
1914
+ () => createInitialOtherDrafts(questionnaire)
1915
+ );
1631
1916
  const [errorMessage, setErrorMessage] = (0, import_react7.useState)(null);
1632
1917
  const [isSubmitting, setIsSubmitting] = (0, import_react7.useState)(false);
1633
1918
  const [isSubmitted, setIsSubmitted] = (0, import_react7.useState)(false);
1919
+ const [pendingFocusQuestionId, setPendingFocusQuestionId] = (0, import_react7.useState)(null);
1634
1920
  const resolvedLabels = {
1635
1921
  ...DEFAULT_QUESTIONNAIRE_CARD_LABELS,
1636
1922
  ...labels
1637
1923
  };
1638
1924
  const hasExternalFailureStatus = questionnaire.status === "expired" || questionnaire.status === "failed";
1925
+ const question = getQuestionnaireQuestion(questionnaire);
1639
1926
  const visibleErrorMessage = questionnaire.statusMessage ?? errorMessage;
1640
1927
  const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus;
1928
+ questionnaireRef.current = questionnaire;
1929
+ (0, import_react7.useEffect)(() => {
1930
+ setAnswers(createInitialAnswers(questionnaireRef.current));
1931
+ setOtherDrafts(createInitialOtherDrafts(questionnaireRef.current));
1932
+ }, [questionnaire.answers]);
1933
+ (0, import_react7.useEffect)(() => {
1934
+ if (!pendingFocusQuestionId || isInteractionLocked) {
1935
+ return;
1936
+ }
1937
+ const inputElement = otherInputRefs.current[pendingFocusQuestionId];
1938
+ if (!inputElement) {
1939
+ return;
1940
+ }
1941
+ inputElement.focus();
1942
+ setPendingFocusQuestionId(null);
1943
+ }, [isInteractionLocked, pendingFocusQuestionId]);
1641
1944
  const handleSubmit = async () => {
1642
1945
  if (isSubmitting || isSubmitted) {
1643
1946
  return;
1644
1947
  }
1645
- const missingQuestions = questionnaire.questions.filter(
1646
- (question) => question.required && isMissingRequiredAnswer(question, answers)
1647
- );
1948
+ const missingQuestions = getMissingRequiredQuestions(questionnaire, answers, otherDrafts);
1648
1949
  if (missingQuestions.length > 0) {
1649
1950
  setErrorMessage(
1650
- `${resolvedLabels.validationPrefix} ${missingQuestions.map((question) => question.label).join(", ")}`
1951
+ `${resolvedLabels.validationPrefix} ${missingQuestions.map((question2) => question2.label).join(", ")}`
1651
1952
  );
1652
1953
  return;
1653
1954
  }
1654
1955
  setErrorMessage(null);
1655
1956
  setIsSubmitting(true);
1656
- const normalizedAnswers = Object.fromEntries(
1657
- questionnaire.questions.flatMap((question) => {
1658
- const value = normalizeQuestionAnswer(question, answers[question.id]);
1659
- return value === void 0 ? [] : [[question.id, value]];
1660
- })
1957
+ const { normalizedAnswers, submissionDetails, content } = prepareQuestionnaireSubmission(
1958
+ questionnaire,
1959
+ answers,
1960
+ otherDrafts
1661
1961
  );
1662
- const contentLines = [
1663
- questionnaire.title ?? "Questionnaire responses",
1664
- ...questionnaire.questions.flatMap((question) => {
1665
- const value = normalizedAnswers[question.id];
1666
- if (value === void 0) {
1667
- return [];
1668
- }
1669
- return [`- ${question.label}: ${formatQuestionAnswer(question, value)}`];
1670
- })
1671
- ];
1672
1962
  try {
1673
1963
  await onSubmit?.({
1674
1964
  questionnaireId: questionnaire.questionnaireId,
1965
+ ...questionnaire.blockKey ? { blockKey: questionnaire.blockKey } : {},
1675
1966
  answers: normalizedAnswers,
1676
- content: contentLines.join("\n")
1967
+ details: submissionDetails,
1968
+ content
1677
1969
  });
1678
1970
  setIsSubmitted(true);
1679
1971
  } catch (error) {
@@ -1682,125 +1974,156 @@ var QuestionnaireCardInner = ({
1682
1974
  setIsSubmitting(false);
1683
1975
  }
1684
1976
  };
1685
- const renderQuestion = (question) => {
1686
- const renderOptionChoice = ({
1687
- questionId,
1688
- optionLabel,
1689
- index,
1690
- isSelected,
1691
- onClick,
1692
- inlineInput,
1693
- tone = "default"
1694
- }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1695
- OptionChoiceItem,
1696
- {
1697
- role: "button",
1698
- tabIndex: isInteractionLocked ? -1 : 0,
1699
- "aria-pressed": isSelected,
1700
- "data-selected": isSelected,
1701
- "data-tone": tone,
1702
- "data-testid": `question-option-${questionId}-${index}`,
1703
- onClick: (event) => {
1704
- if (isInteractionLocked) {
1705
- return;
1706
- }
1707
- if (event.target instanceof HTMLElement && event.target.closest("input")) {
1708
- return;
1709
- }
1710
- onClick();
1711
- },
1712
- onKeyDown: (event) => {
1713
- if (isInteractionLocked) {
1714
- return;
1715
- }
1716
- if (event.key !== "Enter" && event.key !== " ") {
1717
- return;
1718
- }
1719
- event.preventDefault();
1720
- onClick();
1721
- },
1722
- children: [
1723
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceMarker, { "data-selected": isSelected, children: getOptionChoiceLabel(index) }),
1724
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionChoiceContent, { children: [
1725
- inlineInput ? null : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionChoiceLabel, { children: optionLabel }),
1726
- inlineInput
1727
- ] })
1728
- ]
1729
- },
1730
- `${questionId}-${optionLabel}`
1731
- );
1732
- switch (question.kind) {
1733
- case "multi_select":
1734
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(OptionList, { children: question.options.map((option, index) => {
1735
- const selectedValues = getMultiSelectAnswerValues(answers[question.id]);
1736
- const isSelected = selectedValues.includes(option.value);
1737
- return renderOptionChoice({
1738
- questionId: question.id,
1739
- optionLabel: option.label,
1740
- index,
1741
- isSelected,
1742
- onClick: () => setAnswers(
1743
- (current) => toggleMultiSelectAnswer(current, question.id, option.value)
1744
- )
1745
- });
1746
- }) }) });
1977
+ if (!question) {
1978
+ return null;
1979
+ }
1980
+ const renderQuestion = (questionToRender) => {
1981
+ switch (questionToRender.kind) {
1982
+ case "multi_select": {
1983
+ const multiSelectDraft = getMultiSelectDraftState(
1984
+ questionToRender,
1985
+ answers[questionToRender.id],
1986
+ otherDrafts[questionToRender.id] ?? ""
1987
+ );
1988
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionList, { children: [
1989
+ questionToRender.options.map((option, index) => {
1990
+ const isSelected = multiSelectDraft.selectedValues.includes(option.value);
1991
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1992
+ OptionChoice,
1993
+ {
1994
+ questionId: questionToRender.id,
1995
+ optionLabel: option.label,
1996
+ index,
1997
+ isSelected,
1998
+ isInteractionLocked,
1999
+ onClick: () => setAnswers(
2000
+ (current) => toggleMultiSelectAnswer(current, questionToRender.id, option.value)
2001
+ )
2002
+ },
2003
+ option.value
2004
+ );
2005
+ }),
2006
+ questionToRender.allowOther ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2007
+ OptionChoice,
2008
+ {
2009
+ questionId: questionToRender.id,
2010
+ optionLabel: resolvedLabels.otherOptionLabel,
2011
+ index: questionToRender.options.length,
2012
+ isSelected: multiSelectDraft.hasOtherSelected,
2013
+ isInteractionLocked,
2014
+ tone: "other",
2015
+ onClick: () => {
2016
+ if (!multiSelectDraft.hasOtherSelected) {
2017
+ setPendingFocusQuestionId(questionToRender.id);
2018
+ }
2019
+ setAnswers((current) => toggleMultiSelectOtherAnswer(current, questionToRender));
2020
+ },
2021
+ inlineInput: multiSelectDraft.hasOtherSelected ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2022
+ InlineOtherInput,
2023
+ {
2024
+ ref: (node) => {
2025
+ otherInputRefs.current[questionToRender.id] = node;
2026
+ },
2027
+ "data-testid": `question-input-${questionToRender.id}`,
2028
+ type: "text",
2029
+ value: multiSelectDraft.otherValue,
2030
+ placeholder: resolvedLabels.otherPlaceholder,
2031
+ readOnly: isInteractionLocked,
2032
+ onClick: stopInputClickPropagation,
2033
+ onKeyDown: stopInputKeyPropagation,
2034
+ onChange: (event) => {
2035
+ setOtherDrafts((current) => ({
2036
+ ...current,
2037
+ [questionToRender.id]: event.target.value
2038
+ }));
2039
+ }
2040
+ }
2041
+ ) : null
2042
+ },
2043
+ `${questionToRender.id}-other`
2044
+ ) : null
2045
+ ] }) });
2046
+ }
1747
2047
  case "single_select": {
1748
- const singleSelectDraft = getSingleSelectDraftState(question, answers[question.id]);
2048
+ const singleSelectDraft = getSingleSelectDraftState(
2049
+ questionToRender,
2050
+ answers[questionToRender.id],
2051
+ otherDrafts[questionToRender.id] ?? ""
2052
+ );
1749
2053
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionList, { children: [
1750
- question.options.map((option, index) => {
2054
+ questionToRender.options.map((option, index) => {
1751
2055
  const isSelected = singleSelectDraft.selectedValue === option.value;
1752
- return renderOptionChoice({
1753
- questionId: question.id,
1754
- optionLabel: option.label,
1755
- index,
1756
- isSelected,
1757
- onClick: () => setAnswers((current) => updateAnswerValue(current, question.id, option.value))
1758
- });
1759
- }),
1760
- question.allowOther ? renderOptionChoice({
1761
- questionId: question.id,
1762
- optionLabel: "Other",
1763
- index: question.options.length,
1764
- isSelected: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE,
1765
- tone: "other",
1766
- onClick: () => setAnswers(
1767
- (current) => updateAnswerValue(current, question.id, singleSelectDraft.otherValue)
1768
- ),
1769
- inlineInput: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1770
- InlineOtherInput,
2056
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2057
+ OptionChoice,
1771
2058
  {
1772
- "data-testid": `question-input-${question.id}`,
1773
- type: "text",
1774
- value: singleSelectDraft.otherValue,
1775
- placeholder: "Other",
1776
- readOnly: isInteractionLocked,
1777
- onClick: (event) => {
1778
- event.stopPropagation();
1779
- },
1780
- onKeyDown: (event) => {
1781
- event.stopPropagation();
1782
- },
1783
- onChange: (event) => {
1784
- setAnswers(
1785
- (current) => updateAnswerValue(current, question.id, event.target.value)
1786
- );
2059
+ questionId: questionToRender.id,
2060
+ optionLabel: option.label,
2061
+ index,
2062
+ isSelected,
2063
+ isInteractionLocked,
2064
+ onClick: () => setAnswers(
2065
+ (current) => updateAnswerValue(current, questionToRender.id, option.value)
2066
+ )
2067
+ },
2068
+ option.value
2069
+ );
2070
+ }),
2071
+ questionToRender.allowOther ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2072
+ OptionChoice,
2073
+ {
2074
+ questionId: questionToRender.id,
2075
+ optionLabel: resolvedLabels.otherOptionLabel,
2076
+ index: questionToRender.options.length,
2077
+ isSelected: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE,
2078
+ isInteractionLocked,
2079
+ tone: "other",
2080
+ onClick: () => {
2081
+ if (singleSelectDraft.selectedValue !== OTHER_OPTION_VALUE) {
2082
+ setPendingFocusQuestionId(questionToRender.id);
1787
2083
  }
1788
- }
1789
- ) : null
1790
- }) : null
2084
+ setAnswers(
2085
+ (current) => updateAnswerValue(current, questionToRender.id, OTHER_OPTION_VALUE)
2086
+ );
2087
+ },
2088
+ inlineInput: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2089
+ InlineOtherInput,
2090
+ {
2091
+ ref: (node) => {
2092
+ otherInputRefs.current[questionToRender.id] = node;
2093
+ },
2094
+ "data-testid": `question-input-${questionToRender.id}`,
2095
+ type: "text",
2096
+ value: singleSelectDraft.otherValue,
2097
+ placeholder: resolvedLabels.otherPlaceholder,
2098
+ readOnly: isInteractionLocked,
2099
+ onClick: stopInputClickPropagation,
2100
+ onKeyDown: stopInputKeyPropagation,
2101
+ onChange: (event) => {
2102
+ setOtherDrafts((current) => ({
2103
+ ...current,
2104
+ [questionToRender.id]: event.target.value
2105
+ }));
2106
+ }
2107
+ }
2108
+ ) : null
2109
+ },
2110
+ `${questionToRender.id}-other`
2111
+ ) : null
1791
2112
  ] }) });
1792
2113
  }
1793
2114
  case "text":
1794
2115
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1795
2116
  TextInput,
1796
2117
  {
1797
- "data-testid": `question-input-${question.id}`,
2118
+ "data-testid": `question-input-${questionToRender.id}`,
1798
2119
  type: "text",
1799
- value: getTextInputValue(answers[question.id]),
1800
- placeholder: question.placeholder,
2120
+ value: getTextInputValue(answers[questionToRender.id]),
2121
+ placeholder: questionToRender.placeholder,
1801
2122
  readOnly: isInteractionLocked,
1802
2123
  onChange: (event) => {
1803
- setAnswers((current) => updateAnswerValue(current, question.id, event.target.value));
2124
+ setAnswers(
2125
+ (current) => updateAnswerValue(current, questionToRender.id, event.target.value)
2126
+ );
1804
2127
  }
1805
2128
  }
1806
2129
  ) });
@@ -1809,55 +2132,63 @@ var QuestionnaireCardInner = ({
1809
2132
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1810
2133
  TextInput,
1811
2134
  {
1812
- "data-testid": `question-input-${question.id}`,
2135
+ "data-testid": `question-input-${questionToRender.id}`,
1813
2136
  type: "number",
1814
- value: getNumberInputValue(answers[question.id]),
1815
- placeholder: question.placeholder,
2137
+ value: getNumberInputValue(answers[questionToRender.id]),
2138
+ placeholder: questionToRender.placeholder,
1816
2139
  readOnly: isInteractionLocked,
1817
2140
  onChange: (event) => {
1818
2141
  setAnswers(
1819
2142
  (current) => updateAnswerValue(
1820
2143
  current,
1821
- question.id,
2144
+ questionToRender.id,
1822
2145
  event.target.value === "" ? void 0 : Number(event.target.value)
1823
2146
  )
1824
2147
  );
1825
2148
  }
1826
2149
  }
1827
2150
  ),
1828
- question.unit ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Unit, { children: question.unit }) : null
2151
+ questionToRender.unit ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Unit, { children: questionToRender.unit }) : null
1829
2152
  ] }) });
1830
2153
  case "boolean":
1831
2154
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(OptionList, { children: [
1832
- renderOptionChoice({
1833
- questionId: question.id,
1834
- optionLabel: question.trueLabel ?? "Yes",
1835
- index: 0,
1836
- isSelected: answers[question.id] === true,
1837
- onClick: () => setAnswers((current) => updateAnswerValue(current, question.id, true))
1838
- }),
1839
- renderOptionChoice({
1840
- questionId: question.id,
1841
- optionLabel: question.falseLabel ?? "No",
1842
- index: 1,
1843
- isSelected: answers[question.id] === false,
1844
- onClick: () => setAnswers((current) => updateAnswerValue(current, question.id, false))
1845
- })
2155
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2156
+ OptionChoice,
2157
+ {
2158
+ questionId: questionToRender.id,
2159
+ optionLabel: questionToRender.trueLabel ?? "Yes",
2160
+ index: 0,
2161
+ isSelected: answers[questionToRender.id] === true,
2162
+ isInteractionLocked,
2163
+ onClick: () => setAnswers((current) => updateAnswerValue(current, questionToRender.id, true))
2164
+ }
2165
+ ),
2166
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2167
+ OptionChoice,
2168
+ {
2169
+ questionId: questionToRender.id,
2170
+ optionLabel: questionToRender.falseLabel ?? "No",
2171
+ index: 1,
2172
+ isSelected: answers[questionToRender.id] === false,
2173
+ isInteractionLocked,
2174
+ onClick: () => setAnswers((current) => updateAnswerValue(current, questionToRender.id, false))
2175
+ }
2176
+ )
1846
2177
  ] }) });
1847
2178
  default:
1848
2179
  return null;
1849
2180
  }
1850
2181
  };
1851
2182
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card4, { "data-testid": "questionnaire-card", children: [
1852
- questionnaire.title ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Title3, { children: questionnaire.title }) : null,
1853
2183
  questionnaire.description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Description, { children: questionnaire.description }) : null,
1854
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: questionnaire.questions.map((question) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
2184
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
1855
2185
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionLabel, { children: [
1856
2186
  question.label,
1857
2187
  question.required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Required, { children: "*" }) : null
1858
2188
  ] }),
2189
+ question.kind === "multi_select" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionHint, { children: resolvedLabels.multiSelectHint }) : null,
1859
2190
  renderQuestion(question)
1860
- ] }, question.id)) }),
2191
+ ] }, question.id) }),
1861
2192
  visibleErrorMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
1862
2193
  isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : interactive && !hasExternalFailureStatus ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1863
2194
  SubmitButton,
@@ -1873,12 +2204,6 @@ var QuestionnaireCardInner = ({
1873
2204
  ) : null
1874
2205
  ] });
1875
2206
  };
1876
- var getQuestionnaireStateKey = (questionnaire) => JSON.stringify([
1877
- questionnaire.questionnaireId,
1878
- questionnaire.questions,
1879
- questionnaire.status,
1880
- questionnaire.statusMessage
1881
- ]);
1882
2207
  var QuestionnaireCard = (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionnaireCardInner, { ...props }, getQuestionnaireStateKey(props.questionnaire));
1883
2208
  var Card4 = import_styled4.default.section`
1884
2209
  display: grid;
@@ -1888,11 +2213,6 @@ var Card4 = import_styled4.default.section`
1888
2213
  border: 1px solid rgba(255, 255, 255, 0.08);
1889
2214
  background: rgba(255, 255, 255, 0.03);
1890
2215
  `;
1891
- var Title3 = import_styled4.default.strong`
1892
- color: rgba(255, 255, 255, 0.94);
1893
- font-size: 16px;
1894
- line-height: 1.4;
1895
- `;
1896
2216
  var Description = import_styled4.default.p`
1897
2217
  margin: 0;
1898
2218
  color: rgba(255, 255, 255, 0.72);
@@ -1911,13 +2231,18 @@ var QuestionCard = import_styled4.default.div`
1911
2231
  `;
1912
2232
  var QuestionLabel = import_styled4.default.div`
1913
2233
  color: rgba(255, 255, 255, 0.9);
1914
- font-size: 13px;
2234
+ font-size: 14px;
1915
2235
  font-weight: 600;
1916
2236
  `;
1917
2237
  var Required = import_styled4.default.span`
1918
2238
  margin-left: 4px;
1919
2239
  color: rgba(255, 122, 122, 0.9);
1920
2240
  `;
2241
+ var QuestionHint = import_styled4.default.div`
2242
+ color: rgba(132, 180, 255, 0.9);
2243
+ font-size: 12px;
2244
+ line-height: 1.4;
2245
+ `;
1921
2246
  var QuestionBody = import_styled4.default.div`
1922
2247
  display: grid;
1923
2248
  gap: 10px;
@@ -1935,7 +2260,7 @@ var OptionChoiceItem = import_styled4.default.div`
1935
2260
  border: 1px solid rgba(255, 255, 255, 0.1);
1936
2261
  border-radius: 14px;
1937
2262
  background: rgba(255, 255, 255, 0.03);
1938
- padding: 12px 14px;
2263
+ padding: 2px 12px;
1939
2264
  color: rgba(255, 255, 255, 0.9);
1940
2265
  cursor: pointer;
1941
2266
  transition:
@@ -1986,8 +2311,11 @@ var OptionChoiceMarker = import_styled4.default.span`
1986
2311
  }
1987
2312
  `;
1988
2313
  var OptionChoiceContent = import_styled4.default.span`
1989
- display: grid;
1990
- gap: 2px;
2314
+ display: flex;
2315
+ flex-direction: column;
2316
+ justify-content: center;
2317
+ gap: 4px;
2318
+ min-height: 40px;
1991
2319
  min-width: 0;
1992
2320
  flex: 1;
1993
2321
  `;
@@ -2010,8 +2338,37 @@ var TextInput = import_styled4.default.input`
2010
2338
  color: rgba(255, 255, 255, 0.34);
2011
2339
  }
2012
2340
  `;
2013
- var InlineOtherInput = (0, import_styled4.default)(TextInput)`
2341
+ var InlineOtherInput = (0, import_styled4.default)(import_compass_ui.InputField)`
2342
+ width: 100%;
2014
2343
  margin-top: 0;
2344
+
2345
+ .compass-input-field-wrapper {
2346
+ min-height: 30px;
2347
+ border: 1px solid rgba(255, 255, 255, 0.1);
2348
+ border-radius: 10px;
2349
+ background: rgba(13, 15, 21, 0.55);
2350
+ box-shadow: none;
2351
+ padding: 2px 9px;
2352
+ }
2353
+
2354
+ .compass-input-field-wrapper:hover {
2355
+ border-color: rgba(126, 160, 255, 0.28);
2356
+ }
2357
+
2358
+ .compass-input-field-wrapper:focus-within {
2359
+ border-color: rgba(126, 160, 255, 0.42);
2360
+ box-shadow: 0 0 0 1px rgba(126, 160, 255, 0.14);
2361
+ }
2362
+
2363
+ .compass-input-field-input {
2364
+ color: rgba(255, 255, 255, 0.92);
2365
+ font-size: 13px;
2366
+ line-height: 1.2;
2367
+ }
2368
+
2369
+ .compass-input-field-input::placeholder {
2370
+ color: rgba(255, 255, 255, 0.34);
2371
+ }
2015
2372
  `;
2016
2373
  var NumberInputRow = import_styled4.default.div`
2017
2374
  display: flex;
@@ -2320,9 +2677,7 @@ var arePlanQuestionsEqual = (previousQuestion, nextQuestion) => {
2320
2677
  return false;
2321
2678
  }
2322
2679
  };
2323
- var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.status === nextQuestionnaire.status && previousQuestionnaire.statusMessage === nextQuestionnaire.statusMessage && previousQuestionnaire.questions.length === nextQuestionnaire.questions.length && previousQuestionnaire.questions.every(
2324
- (question, index) => arePlanQuestionsEqual(question, nextQuestionnaire.questions[index])
2325
- ) && areQuestionAnswerMapsEqual(previousQuestionnaire.answers, nextQuestionnaire.answers);
2680
+ var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.status === nextQuestionnaire.status && previousQuestionnaire.statusMessage === nextQuestionnaire.statusMessage && arePlanQuestionsEqual(previousQuestionnaire.question, nextQuestionnaire.question) && areQuestionAnswerMapsEqual(previousQuestionnaire.answers, nextQuestionnaire.answers);
2326
2681
  var areMessageBlocksEqual = (previousBlocks, nextBlocks) => {
2327
2682
  if (previousBlocks === nextBlocks) {
2328
2683
  return true;
@@ -2476,14 +2831,17 @@ var ChatMessageItemView = ({
2476
2831
  submitting: labels.questionnaireSubmitting,
2477
2832
  submitted: labels.questionnaireSubmitted,
2478
2833
  validationPrefix: labels.questionnaireValidationPrefix,
2479
- submitFailed: labels.questionnaireSubmitFailed
2834
+ submitFailed: labels.questionnaireSubmitFailed,
2835
+ multiSelectHint: labels.questionnaireMultiSelectHint,
2836
+ otherOptionLabel: labels.questionnaireOtherOptionLabel,
2837
+ otherPlaceholder: labels.questionnaireOtherPlaceholder
2480
2838
  },
2481
2839
  onSubmit: canSubmitQuestionnaire ? (submission) => onQuestionnaireSubmit({
2482
2840
  ...submission,
2483
2841
  sourceMessageId: message.id
2484
2842
  }) : void 0
2485
2843
  }
2486
- ) }, `questionnaire-${index}`);
2844
+ ) }, block.questionnaire.blockKey ?? `questionnaire-${index}`);
2487
2845
  case "custom":
2488
2846
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: renderMessageBlock?.({
2489
2847
  block,
@@ -2735,8 +3093,34 @@ var CollapseToggle = import_styled7.default.button`
2735
3093
  `;
2736
3094
  var Content = import_styled7.default.div`
2737
3095
  color: rgba(255, 255, 255, 0.92);
3096
+ font-size: 14px;
2738
3097
  line-height: 1.6;
2739
3098
 
3099
+ h1,
3100
+ h2,
3101
+ h3,
3102
+ h4,
3103
+ h5,
3104
+ h6 {
3105
+ margin: 0;
3106
+ line-height: 2.5;
3107
+ }
3108
+
3109
+ h1 {
3110
+ font-size: 18px;
3111
+ }
3112
+
3113
+ h2 {
3114
+ font-size: 16px;
3115
+ }
3116
+
3117
+ h3,
3118
+ h4,
3119
+ h5,
3120
+ h6 {
3121
+ font-size: 14px;
3122
+ }
3123
+
2740
3124
  p {
2741
3125
  margin: 0;
2742
3126
  }
@@ -2748,7 +3132,7 @@ var Content = import_styled7.default.div`
2748
3132
  table {
2749
3133
  width: 100%;
2750
3134
  border-collapse: collapse;
2751
- margin: 0;
3135
+ margin: 8px 0 0;
2752
3136
  overflow: hidden;
2753
3137
  border-radius: 14px;
2754
3138
  border: 1px solid rgba(255, 255, 255, 0.08);
@@ -2772,6 +3156,10 @@ var Content = import_styled7.default.div`
2772
3156
  tbody tr:last-of-type td {
2773
3157
  border-bottom: none;
2774
3158
  }
3159
+ ul,
3160
+ ol {
3161
+ margin: 0 0 8px;
3162
+ }
2775
3163
  `;
2776
3164
  var ContentStack = import_styled7.default.div`
2777
3165
  display: flex;
@@ -4070,7 +4458,7 @@ var CloseGlyph = import_styled10.default.span`
4070
4458
 
4071
4459
  // src/components/chat-composer/components/chat-model-control.tsx
4072
4460
  var import_styled11 = __toESM(require("@emotion/styled"));
4073
- var import_compass_ui = require("@xinghunm/compass-ui");
4461
+ var import_compass_ui2 = require("@xinghunm/compass-ui");
4074
4462
  var import_jsx_runtime12 = require("@emotion/react/jsx-runtime");
4075
4463
  var ChatModelControl = ({
4076
4464
  selectedModel,
@@ -4171,7 +4559,7 @@ var ModelReloadButton = import_styled11.default.button`
4171
4559
  var ReloadIcon = import_styled11.default.svg`
4172
4560
  flex-shrink: 0;
4173
4561
  `;
4174
- var ModelSelect = (0, import_styled11.default)(import_compass_ui.Select)`
4562
+ var ModelSelect = (0, import_styled11.default)(import_compass_ui2.Select)`
4175
4563
  && {
4176
4564
  width: auto;
4177
4565
  min-width: 0;
@@ -4192,7 +4580,7 @@ var ModelSelect = (0, import_styled11.default)(import_compass_ui.Select)`
4192
4580
 
4193
4581
  // src/components/chat-composer/components/chat-mode-control.tsx
4194
4582
  var import_styled12 = __toESM(require("@emotion/styled"));
4195
- var import_compass_ui2 = require("@xinghunm/compass-ui");
4583
+ var import_compass_ui3 = require("@xinghunm/compass-ui");
4196
4584
  var import_jsx_runtime13 = require("@emotion/react/jsx-runtime");
4197
4585
  var ChatModeControl = ({
4198
4586
  value,
@@ -4215,7 +4603,7 @@ var ChatModeControl = ({
4215
4603
  }
4216
4604
  );
4217
4605
  };
4218
- var ModeSelect = (0, import_styled12.default)(import_compass_ui2.Select)`
4606
+ var ModeSelect = (0, import_styled12.default)(import_compass_ui3.Select)`
4219
4607
  && {
4220
4608
  flex: 0 1 auto;
4221
4609
  width: auto;
@@ -4237,7 +4625,7 @@ var ModeSelect = (0, import_styled12.default)(import_compass_ui2.Select)`
4237
4625
 
4238
4626
  // src/components/chat-composer/components/chat-send-actions.tsx
4239
4627
  var import_styled13 = __toESM(require("@emotion/styled"));
4240
- var import_compass_ui3 = require("@xinghunm/compass-ui");
4628
+ var import_compass_ui4 = require("@xinghunm/compass-ui");
4241
4629
  var import_jsx_runtime14 = require("@emotion/react/jsx-runtime");
4242
4630
  var ArrowUpIcon = () => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4243
4631
  "svg",
@@ -4291,7 +4679,7 @@ var ChatSendActions = ({
4291
4679
  onClick: () => void onSend()
4292
4680
  }
4293
4681
  ) });
4294
- var PrimaryButton = (0, import_styled13.default)(import_compass_ui3.Button)`
4682
+ var PrimaryButton = (0, import_styled13.default)(import_compass_ui4.Button)`
4295
4683
  && {
4296
4684
  min-width: 24px;
4297
4685
  width: 24px;
@@ -4317,7 +4705,7 @@ var PrimaryButton = (0, import_styled13.default)(import_compass_ui3.Button)`
4317
4705
  }
4318
4706
  }
4319
4707
  `;
4320
- var StopButton = (0, import_styled13.default)(import_compass_ui3.Button)`
4708
+ var StopButton = (0, import_styled13.default)(import_compass_ui4.Button)`
4321
4709
  && {
4322
4710
  min-width: 24px;
4323
4711
  width: 24px;
@@ -4890,7 +5278,7 @@ var ChatConversationList = () => {
4890
5278
  };
4891
5279
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Container3, { children: [
4892
5280
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Toolbar, { children: [
4893
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Title4, { children: "Sessions" }),
5281
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Title3, { children: "Sessions" }),
4894
5282
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(CreateButton, { type: "button", "data-testid": "chat-create-session", onClick: handleCreateSession, children: labels.newChat })
4895
5283
  ] }),
4896
5284
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(List2, { "data-testid": "chat-session-list", children: sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -4919,7 +5307,7 @@ var Toolbar = import_styled16.default.div`
4919
5307
  flex-direction: column;
4920
5308
  gap: 12px;
4921
5309
  `;
4922
- var Title4 = import_styled16.default.h2`
5310
+ var Title3 = import_styled16.default.h2`
4923
5311
  margin: 0;
4924
5312
  font-size: 14px;
4925
5313
  color: var(--text-secondary);
@@ -4944,7 +5332,7 @@ var List2 = import_styled16.default.div`
4944
5332
  // src/components/ai-chat/index.tsx
4945
5333
  var import_jsx_runtime18 = require("@emotion/react/jsx-runtime");
4946
5334
  var AiChat = ({ showConversationList = false, ...providerProps }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4947
- import_compass_ui4.ConfigProvider,
5335
+ import_compass_ui5.ConfigProvider,
4948
5336
  {
4949
5337
  theme: {
4950
5338
  token: {